在PostgreSQL 9.1的PL/pgSQL中,给定一个查询:
select fk_list.relname from ...
其中relname
是类型name
(例如,"表名")。
如何获得可直接在UPDATE
语句中使用的"relname"的适当值:
Update <relname> set ...
在PL/pgSQL脚本中?
使用quote_ident(r.relname)
作为:
Update quote_ident(r.relname) Set ...
失败:
在"("行55处或附近出现语法错误:更新报价标识(r.相关名称)....
完整的代码,我的工作:
CREATE FUNCTION merge_children_of_icd9 (ocicd9 text,
ocdesc text, ncicd9 text, ncdesc text)
RETURNS void AS $BODY$
DECLARE
r RECORD;
BEGIN
FOR r IN
WITH fk_actions ( code, action ) AS (
VALUES ('a', 'error'),
('r', 'restrict'),
('c', 'cascade'),
('n', 'set null'),
('d', 'set default')
), fk_list AS (
SELECT pg_constraint.oid AS fkoid, conrelid, confrelid::regclass AS parentid,
conname, relname, nspname,
fk_actions_update.action AS update_action,
fk_actions_delete.action AS delete_action,
conkey AS key_cols
FROM pg_constraint
JOIN pg_class ON conrelid = pg_class.oid
JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid
JOIN fk_actions AS fk_actions_update ON confupdtype = fk_actions_update.code
JOIN fk_actions AS fk_actions_delete ON confdeltype = fk_actions_delete.code
WHERE contype = 'f'
), fk_attributes AS (
SELECT fkoid, conrelid, attname, attnum
FROM fk_list
JOIN pg_attribute ON conrelid = attrelid AND attnum = ANY(key_cols)
ORDER BY fkoid, attnum
), fk_cols_list AS (
SELECT fkoid, array_agg(attname) AS cols_list
FROM fk_attributes
GROUP BY fkoid
)
SELECT fk_list.fkoid, fk_list.conrelid, fk_list.parentid, fk_list.conname,
fk_list.relname, fk_cols_list.cols_list
FROM fk_list
JOIN fk_cols_list USING (fkoid)
WHERE parentid = 'icd9'::regclass
LOOP
RAISE NOTICE 'now in loop. relname is %', quote_ident(r.relname);
RAISE NOTICE 'cols_list[1] is %', quote_ident(r.cols_list[1]);
RAISE NOTICE 'cols_list[2] is %', quote_ident(r.cols_list[2]);
RAISE NOTICE 'now doing update';
UPDATE quote_ident(r.relname) SET r.cols_list[1] = ncicd9, r.cols_list[2] = ncdesc
WHERE r.cols_list[1] = ocicd9 AND r.cols_list[2] = ocdesc;
RAISE NOTICE 'finished update';
END LOOP;
RETURN;
END $BODY$ LANGUAGE plpgsql VOLATILE;
-- select merge_children_of_icd9('', 'aodm type 2', '', 'aodm, type 2');
我相信这种事情经常发生,但是我似乎找不到任何类似的使用PostgreSQL的方法。有更好的方法吗?
2条答案
按热度按时间e5nqia271#
在PL/pgSQL的
UPDATE
语句中,表名必须以文字形式给出。如果要动态设置表名和列,则应使用EXECUTE
命令并将查询字符串粘贴在一起:USING
子句只能用于替换数据值,如上所示。hc8w905p2#
你需要使用
EXECUTE
的动态SQL,比如已经提供的@Patrick。然而,你的函数和EXECUTE
部分可以简单得多。特别是,使用**format()
**安全地连接更长的查询字符串(从9.1页开始提供):如果FK约束未跨越至少两列,或者列的数据类型与
text
不兼容,则函数将出错。可能会也可能不会按预期进行。有关如何安全传递标识符和执行动态SQL的详细信息: