web-dev-qa-db-ja.com

COPYコマンドの自動化-Postgres 9.2

いくつかの異なるIDを持つバックアップテーブルがあります... IDでそれらの行のバックアップを実行します。

  • 関数は、account_idの制限で実行する必要があります(select dump(21);-where 21 = number of account_id to be touched to the function

  • 各account_idには異なるファイル名を付ける必要があります。以下の例:

例:

_COPY 
(
SELECT * FROM backup_table WHERE id = 1112 AND status = 1
) 
TO '/var/lib/pgsql/1112.sql';

COPY 
(
SELECT * FROM backup_table WHERE id = 1113 AND status = 1
) 
TO '/var/lib/pgsql/1113.sql';

COPY 
(
SELECT * FROM backup_table WHERE id = 1114 AND status = 1
) 
TO '/var/lib/pgsql/1114.sql';
_

質問:

それを自動的に行う関数を作成できますか?それらのIDSは数千あり、手動で行うには時間がかかります。

更新1:

しようとしました:

_CREATE or REPLACE FUNCTION dump(integer)
RETURNS integer AS $$

declare
   crtRow record;
begin
      FOR crtRow in execute 'select account_id from backup_table WHERE migrated = 1 AND account_id = '|| $1

      LOOP
    COPY
        (SELECT * FROM backup_table WHERE migrated = 1 AND account_id = crtRow.account_id)
    TO '/var/lib/pgsql/backup/%s.sql';
    end loop;
    return integer;
end

$$ language 'plpgsql';
_
  • 各account_Idには、IDを持つファイルがあります
  • 関数を呼び出すときに、ダンプしたいaccount_Idの数を指定したい

しかし、それは機能していません...

更新2

_CREATE or REPLACE FUNCTION function_1(rows integer)
RETURNS void AS $$

declare
   crtRow record;
begin
      FOR crtRow in EXECUTE 'select DISTINCT(account_id) from backup_table WHERE migrated = 1 AND account_id IN '|| $1

      LOOP
    COPY
        (SELECT * FROM backup_table WHERE migrated = 1 AND account_id = crtRow.account_id)
    TO '/var/lib/pgsql/' || crtrow.account_id || '.csv';
    end loop;
end

$$ language 'plpgsql';
_

エラー:

エラー: "||"またはその近くの構文エラー12行目:TO '/ var/lib/pgsql /' || crtrow.account_id | ...

PDATE:amacvarの答え

_CREATE or REPLACE FUNCTION function_1(rows integer)
RETURNS void AS $$

begin
execute 'COPY
(
SELECT * FROM backup_table WHERE id = ' || rows || 'AND status = 1
)
TO ''/var/lib/pgsql/'||rows||'.sql''';

end

$$ language 'plpgsql';
_

Amacvarの答えに基づく上記の関数は機能します。問題は、ID番号を指定する必要があることです...

例:

_`select function_1(25)` - Where 25 = id
_

私には何千ものIDがあり、それらを手動で指定することができないので、それは私には良くありません。

私が必要なのは:

上記と同じ関数ですが、関数の呼び出し時にIDSのLIMITを指定します。

例:

select function_1(100)-WHERE 100 =コピーするIDの数

  • どうやってやるの?
3
Patrick B.

上記のスクリプトの回答は明らかに機能します。

しかし、DB内から実行する必要がある場合は(理由を教えてください:))、以下のコード(ループを除いたもの)で解決できます。

あなたは非常に近いところでした。

CREATE or REPLACE FUNCTION function_1(rows text)
RETURNS void AS $$
begin
  execute 'COPY (
    SELECT * 
      FROM backup_table
     WHERE id = ' || rows || ' 
       AND status = 1
  ) TO ''/var/lib/pgsql/'||rows||'.dat''';
end
$$ language 'plpgsql';

編集1:関数ループの例とフォーマット

CREATE or REPLACE FUNCTION function_loop(rows_arr text[])
RETURNS void AS $$
declare
  crtRow text;
begin
  ForEach crtRow in array rows_arr
  LOOP
     perform function_1(crtRow);  
  end loop;
end
$$ language 'plpgsql';

として実行

select function_loop('{1,2,3}');

ここではチェックが行われていないことに注意してください。

例えば。これにより、テーブルにid = 3がない場合でも、0バイトの3.datが作成されます。

編集2:数千のIDのためのより拡張可能なオプションは、

CREATE or REPLACE FUNCTION function_loop1(startId int, endId int)
RETURNS void AS $$
declare
  allIds text[];
  crtRow text;
begin
  select array_agg(id::text) into allIds 
    from backup_table
   where status=1 
     and id between startId and endId;
  ForEach crtRow in array allIds
  LOOP
    perform function_1(crtRow);  
  end loop;
end
$$ language 'plpgsql';
2
amacvar

あなたはbashスクリプトで以下のようなことを試すことができます:

#!/bin/bash

su postgres

for id in `psql -d database -c"select DISTINCT(account_id) from backup_table WHERE migrated = 1 AND account_id IN ";` 
do
  psql -d database -c"COPY (SELECT * FROM backup_table WHERE id = "$id" AND status = 1) TO '/var/lib/pgsql/"$id".sql'";
done

次に、これをスクリプトでcrontabを介して実行します。

1
Manii