根据this question的建议,我使用to_regclass
函数检查表是否存在,如果不存在则创建表。但是,如果表格是在当前交易中创建的,to_regclass
仍然会返回null
。
预计会出现这种情况吗?或者这是一个错误吗?
详细
以下是出现问题的简短示例:
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;
答案 0 :(得分:2)
您未正确使用%I
格式说明符。
如果您的类别为1
,那么您最终会调用to_regclass('test.test_1')
,即检查架构test_1
中的表格test
。
但是,format('create table %I', 'test.test_1')
会将format参数视为单个标识符,并相应地引用它,评估为'create table "test.test_1"'
。这将在您的默认架构中创建一个名为"test.test_1"
的表(可能是public
)。
相反,您需要将架构和表名称视为单独的标识符。将表名定义为:
child_table_name = format('test.%I', 'test_' || new.category);
...在构建SQL字符串时,只需直接替换此值(即使用%s
而不是%I
)。