2016-09-15 14 views
1

this questionの提案に続いて、私はto_regclass関数を使用して、テーブルが存在するかどうかをチェックし、存在しない場合はテーブルを作成しています。ただし、テーブルが現在のトランザクションで作成された場合、to_regclassはまだnullを返します。PostgreSQLのトランザクションDDLとto_regclass

この現象は予期されていますか?それともバグですか?あなたは間違って%I書式指定子を使用している

begin; 
create schema test; 
create table test.test (id serial, category integer); 

create or replace function test.test_insert() returns trigger as $$ 
declare 
    child_table_name text; 
    table_id  text; 
begin 
    child_table_name = concat('test.test_', text(new.category)); 
    table_id = to_regclass(child_table_name::cstring); 
    if table_id is null then 
     execute format('create table %I (primary key (id), check (category = %L)) inherits (test.test)', child_table_name, new.category); 
    end if; 
    execute format ('insert into %I values ($1.*)', child_table_name) using new; 
    return null; 
end; 
$$ language plpgsql; 

create trigger test_insert before insert on test.test for each row execute procedure test.test_insert(); 

insert into test.test (category) values (1); 
insert into test.test (category) values (1); 
insert into test.test (category) values (1); 
commit; 
+1

なぜ、 'create table if not exist'を使うのですか? –

+0

ああ...はい、あなたは私をそこに連れてきました。 – Tom

答えて

1

詳細は

ここでは、これがうまくいかないところの短い例です。

カテゴリが1の場合は、という表のtest_1を確認することで、to_regclass('test.test_1')が呼び出されます。

ただし、format('create table %I', 'test.test_1')は、フォーマット引数を単一の識別子として扱い、それに応じて、'create table "test.test_1"'と評価します。これにより、デフォルトのスキーマに"test.test_1"というテーブルが作成されます(おそらくpublic)。

代わりに、スキーマとテーブル名を別々の識別子として扱う必要があります。あなたのテーブル名を定義します。

child_table_name = format('test.%I', 'test_' || new.category); 

...とあなたのSQL文字列を構築するときに、ちょうど(すなわち%sではなく%Iで)直接この値を代入。

+0

多くのありがとう。私は百万年の間にそれを見つけられませんでした。 – Tom

関連する問題