2017-03-02 4 views
0

私はテナントが同じデータベース内の異なるスキーマに設定されているマルチテナントアプリケーションを持っています。その理由は、スキーマの1つで使用する共有データがいくつかあるからです。複数のスキーマに対するPostgresの実行文

これまでは、新しいスキーマが追加されるたびに更新する必要のあるスキーマのリストを持つbashスクリプトを使用していましたが、アカウント全体でスキーマの変更を行う必要があります。たとえば、テーブルに新しい列を追加する。

はPostgresの、psqlでの方法は、例えばbashのように別のスクリプトで文字列置換を行うことなく、インスタンス

ALTER TABLE some_table ADD COLUMN some_column TEXT NOT NULL DEFAULT ''; 

のために実行する...など、あります。

つまり、スキーマを取得するには簡単な方法があります。psqlにforループを書くと、スキーマを繰り返し処理し、それぞれの場合にsearch_pathを設定して文を実行します。

デベロッパーではない管理者がテナント数を増やし、新しいテナントを追加できる理由は、常にシェルスクリプトを更新しているからです。これは指数関数的にしか成長しません。この種の問題を処理する標準的な方法はありますか?

+0

はい、メインのスキーマ(posgres)のプロシージャを作成してすべての方式をフェッチするINFORMATION_SCHEMAスキーマと同様に、コマンドを実行して変更を加えてください –

答えて

3

あなたは少しPL/pgSQLのブロックとすることを行うことができます。

do 
$$ 
declare 
    s_rec record; 
begin 
    for s_rec in select schema_name 
       from information_schema.schemata 
       where schema_name not in ('pg_catalog', 'information_schema') 
    loop 
    execute format ('ALTER TABLE if exists %I.some_table ADD COLUMN some_column TEXT NOT NULL DEFAULT ''''), s_rec.schema_name); 
    end loop; 
end; 
$$ 

if existsは、その表がスキーマに存在しない場合、文は失敗しないことを確認します。


あなた、あなたの質問に簡略化オーバーと実際にはスキーマごとに一回の完全なスクリプトを実行したい場合は、実際のスクリプトを含んでいる各スキーマのためのスクリプトを生成することは、おそらく簡単です:

select concat(format('set search_path = %I;', schema_name), 
       chr(10), 
       '\i complete_migration_script.sql') 
from information_schema.schemata 
where schema_name not in ('pg_catalog', 'information_schema') 

することができますその文の出力をファイルにスプールしてからpsqlを使用してそのファイルを実行します(complete_migration_script.sqlを実際のスクリプト名に置き換える必要があります)

+0

驚くべきことに、実際には両方の例が必要です。ありがとうございました!!! –

関連する問題