【发布时间】:2015-12-13 17:46:14
【问题描述】:
我创建了一个函数copy_rows_from_table(_tbl regclass),它复制表中的记录并为它们提供一个新的主键值。它返回一个包含成对 old_id => new_id 的 hstore。例如,对于表 books,我的函数将创建两个额外的记录并返回一个 hstore。
books 最初:
id | title | price | author_id | publisher_id
----+---------------+-------+-----------+--------------
1 | The Cyberiad | 15.00 | 23 | 46
2 | The Trial | 10.00 | 12 | 67
books 评估后copy_rows_from_table('books'):
id | title | price | author_id | publisher_id
----+---------------+-------+-----------+--------------
1 | The Cyberiad | 15.00 | 23 | 46
2 | The Trial | 10.00 | 12 | 67
3 | The Cyberiad | 15.00 | 23 | 46
4 | The Trial | 10.00 | 12 | 67
返回的 hstore:
"1"=>"3", "2"=>"4"
它工作正常。现在我想创建一个函数,它从几个表中复制记录(以数组形式传递),然后使用返回的 hstore 更新所有外键。例如,在复制 books 和 authors 之后,我希望在 books 表中更新 author_id 列。在books、authors 和publishers 上使用我的函数后,如果我有一个包含"1"=>"3", "2"=>"4","23"=>"167","12"=>"98","46"=>"87","67"=>"102" 的hstore,我的函数应该以这种方式更新books 表:
id | title | price | author_id | publisher_id
----+---------------+-------+-----------+--------------
1 | The Cyberiad | 15.00 | 23 | 46
2 | The Trial | 10.00 | 12 | 67
3 | The Cyberiad | 15.00 | 167 | 87
4 | The Trial | 10.00 | 98 | 102
我想出了这样的东西:
CREATE OR REPLACE FUNCTION copy_tables(_tbls regclass[])
RETURNS void AS
$func$
DECLARE
_tbl regclass;
_id_pairs hstore;
_table_id_pairs hstore;
_row record;
BEGIN
FOR _tbl IN SELECT _tbls
LOOP
EXECUTE format('SELECT copy_rows_from_table(''%1$s'')', _tbl)
INTO _table_id_pairs;
SELECT COALESCE(_id_pairs, hstore('')) || COALESCE(_table_id_pairs, hstore('')) INTO _id_pairs;
END LOOP;
FOR _tbl IN SELECT _tbls
LOOP
FOR _row IN EXECUTE format('SELECT * FROM %1$s WHERE id = ANY(''%2$s''::uuid[])', _tbl, avals(_id_pairs))
LOOP
EXECUTE (
SELECT format('UPDATE %1$s SET (%2$s) = (%3$s) WHERE id = %4$s'
, _tbl, string_agg(quote_ident(attname), ', '),
string_agg(COALESCE(_id_pairs -> ('_row.' || quote_ident(attname)), '_row.' || quote_ident(attname)), ', '), _row.id)
FROM pg_attribute
WHERE attrelid = _tbl
AND NOT attisdropped
AND attnum > 0
AND attname LIKE '%_id'
);
END LOOP;
END LOOP;
END
$func$
LANGUAGE plpgsql;
但它并不完全有效。有没有可能按照我解释的方式更新记录?
【问题讨论】:
标签: sql database postgresql plpgsql