我有一个插入触发器函数,其中NEW.schema_name引用一个模式。我想动态地将该模式中的表格('foobaz','barbaz')复制为'foo'和'bar'。然后我可以在没有动态sql的情况下执行查询。
如何创建函数或简单地复制/粘贴相同的代码块以实现该功能。
编辑:
我无法让这个动态查询起作用。 WITH语句中的部分正在工作。 不是底部的“执行”部分。我不知道它是一个语法问题,还是坏的转换或pgsql中的任何约束使它无法正常工作。
WITH info_schema_subset_table as (SELECT table_schema, table_name,
array_to_string((regexp_split_to_array(table_name,'_'))[4:array_length(regexp_split_to_array(table_name,'_'),1)-1] as new_table
FROM information_schema.tables
where table_schema = "schema_searched"
ORDER BY new_table ASC)
EXECUTE 'CREATE TABLE $2 as (SELECT * FROM $1)'
USING info_schema_subset_table.table_schema || '.' ||info_schema_subset_table.table_name,info_schema_subset_table.new_table;
编辑2
......删除了破碎的代码......
在下面的代码中,我不确定语法是否正确,我从触发器中得到以下内容
提供商错误: 添加功能时出现PostGIS错误:ERREUR:l'opérateurn'existepas:record ~~ unknown 第1行:SELECT old_table LIKE'%ens%' ^ 提示:Aucunopérateurne对应aunomdonnéetaux types d'arguments。 Vous devez ajouter des conversions explicites de type。 QUERY:SELECT old_table LIKE'%ens%' 背景信息:功能PL / pgsql validation_sio.afi_validation_sio(),ligne 18àCASE
编辑3:
CREATE OR REPLACE FUNCTION foo.foo()
RETURNS TRIGGER AS
$BODY$
DECLARE
old_table record;
new_table record;
dynamic_query text;
BEGIN
IF TG_OP = 'INSERT'
THEN
FOR old_table IN SELECT table_schema|| '.' ||table_name
FROM information_schema.tables
where table_schema = NEW.nom_schema
LOOP
CASE
WHEN
old_table LIKE '%ens%' THEN
new_table := concat('SIT_',array_to_string((regexp_split_to_array(info_schema.old_table,'_'))[4:array_length(regexp_split_to_array(info_schema.old_table,'_'),1)-1],'_'));
ELSE
new_table := concat('SID_',array_to_string((regexp_split_to_array(info_schema.old_table,'_'))[4:array_length(regexp_split_to_array(info_schema.old_table,'_'),1)-1],'_'));
END CASE;
dynamic_query := format('SELECT * FROM' || old_table ||);
EXECUTE dynamic_query
INTO new_table;
END LOOP;
RETURN NEW;
END IF;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;
CREATE TRIGGER foo
AFTER INSERT ON validation.validationfoo
FOR EACH ROW EXECUTE PROCEDURE foo.foo();
答案 0 :(得分:0)
在SQL语句中不能有EXECUTE
,它是PL / pgSQL语句。
遍历表格并为每个表格发出一个EXECUTE
。
请注意,您不能将模式或表名作为USING
的参数,因为这些名称需要在分析时知道。
使用format
函数构造动态语句,以避免恶意创建具有奇怪名称的表的用户进行SQL注入。
答案 1 :(得分:0)
我已经重新格式化了你的触发功能并改变了一些事情,看看是否有效。
CREATE OR REPLACE FUNCTION foo.foo()
RETURNS TRIGGER AS
$BODY$
DECLARE
old_table record;
new_table record;
dynamic_query text;
BEGIN
IF TG_OP = 'INSERT' THEN
FOR old_table IN
SELECT table_schema || '.' || table_name AS old_table_name
FROM information_schema.tables
WHERE table_schema = NEW.nom_schema
LOOP
new_table := concat(CASE WHEN old_table.old_table_name LIKE '%ens%' THEN 'SIT_' ELSE 'SID_' END,array_to_string((regexp_split_to_array(info_schema.old_table,'_'))[4:array_length(regexp_split_to_array(info_schema.old_table,'_'),1)-1],'_'));
dynamic_query := 'CREATE TABLE ' || new_table || ' AS SELECT * FROM ' || old_table.old_table_name;
EXECUTE dynamic_query;
END LOOP;
RETURN NEW;
END IF;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;
所以主要的事情:
old_table
是一条记录,因此您将其与LIKE
的字符串进行比较失败。您需要使用字段名称。所以我给你的字段命名,并在LIKE
比较中使用了该字段名称。new_table
分配,只将CASE
语句放在更改的一个项目上,以使差异更明显,代码更简洁。请注意,我不知道该行的其余部分是否真的有效,我只是保持原样。dynamic_query
。正如我在评论中所说,format
函数使用不正确,所以我只是使用标准字符串连接。 dynamic_query
的SQL更改为我认为您真正希望它执行的操作。您希望它将表的内容复制到新表中,对吧?这样就可以了。