仅更新动态选择的列

时间:2015-12-13 17:46:15

标签: sql database postgresql plpgsql

我创建了一个函数result1 = {{"B",1,2,3,4}}; result2 = {{"D",1,2,3,4}}; resultEdit1 = {{"C",1,2,3,4}}; ,它复制表中的记录并为它们提供新的主键值。它返回一个包含old_id =>对的hstore; NEW_ID。例如,对于表copy_rows_from_table(_tbl regclass),我的函数将创建两个额外的记录并返回一个hstore。

最初

books

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')

返回hstore: 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"books之后,我希望在authors表中更新author_id列。在booksbooksauthors上使用我的函数后,如果我有一个包含publishers的hstore,我的函数应该以这种方式更新"1"=>"3", "2"=>"4","23"=>"167","12"=>"98","46"=>"87","67"=>"102"表:

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

但它不太有用。是否有可能以我解释的方式更新记录?

2 个答案:

答案 0 :(得分:1)

我终于找到了在PLpgSQL中实现它的方法。我只是遍历每个记录的每一列。这是我的工作职能:

CREATE OR REPLACE FUNCTION copy_tables(_tbls regclass[])
RETURNS void AS
$func$
DECLARE
  _id_pairs hstore;
  _table_id_pairs hstore;
  _row record;
  _hs_row record;
BEGIN
  FOR I IN array_lower(_tbls, 1)..array_upper(_tbls, 1)
  LOOP
    EXECUTE format('SELECT copy_rows_from_table(''%1$s'')', _tbls[I])
    INTO _table_id_pairs;
    SELECT COALESCE(_id_pairs, hstore('')) || COALESCE(_table_id_pairs, hstore('')) INTO _id_pairs;
  END LOOP;

  FOR I IN array_lower(_tbls, 1)..array_upper(_tbls, 1)
  LOOP
    FOR _row IN EXECUTE format('SELECT * FROM %1$s WHERE id = ANY(''%2$s''::uuid[])', _tbls[I], avals(_id_pairs))
    LOOP
      FOR _hs_row IN SELECT kv."key", kv."value" FROM each(hstore(_row)) kv
      LOOP
        IF _hs_row."value" = ANY(akeys(_id_pairs)) THEN
          EXECUTE format('UPDATE %1$s SET %2$s = ''%3$s'' WHERE id = ''%4$s''',
                          _tbls[I], _hs_row."key", _id_pairs -> _hs_row."value", _row.id);
        END IF;
      END LOOP;
    END LOOP;
  END LOOP;
END
$func$
LANGUAGE plpgsql;

答案 1 :(得分:0)

PLpgSQL不是动态更新的好工具。可能还有其他一些可能性,但没有人是微不足道的。其他方式:

  1. 使用更动态的PL语言 - PLPythonu,PLPerl
  2. 使用附加信息https://github.com/okbob/pltoolbox - 功能record_get_fieldsrecord_set_fields