重复单个数据库记录

时间:2013-04-15 08:44:40

标签: postgresql plpgsql postgresql-9.0

您好,在同一个表上复制数据库记录的最简单方法是什么?

我的问题是,我这样做的表有很多列,比如100+,我不喜欢解决方案的样子。这是我做的(这是在plpqsql函数内): ...

1。重复记录

INSERT INTO history 
  (SELECT NEXTVAL('history_id_seq'), col_1, col_2, ... , col_100)
   FROM history
   WHERE history_id = 1234
   ORDER BY datetime DESC
   LIMIT 1)
 RETURNING
   history_id INTO new_history_id;

2。更新一些列

UPDATE history
SET 
    col_5 = 'test_5', 
    col_23 = 'test_23', 
    datetime = CURRENT_TIMESTAMP
WHERE history_id = new_history_id;

以下是我试图解决的问题

  1. 列出所有这100多个列看起来很蹩脚
  2. 添加新列时,最终也应该更新该功能
  3. 在单独的数据库实例上,列顺序可能不同,这会导致函数失败
  4. 我不确定我是否可以再次列出它们(解决问题3),例如insert into <table> (<columns_list>) values (<query>),但查询看起来更加丑陋。

    我希望实现类似'insert into'的功能,但这似乎不可能唯一的主键约束会引发重复错误。

    有什么建议吗?

    先谢谢你的时间。

2 个答案:

答案 0 :(得分:1)

您无论如何都不需要更新,您可以直接在SELECT语句中提供常量值:

INSERT INTO history 
SELECT NEXTVAL('history_id_seq'), 
       col_1, 
       col_2, 
       col_3, 
       col_4, 
       'test_5', 
       ... 
       'test_23', 
       ...,
       col_100
FROM history
WHERE history_sid = 1234
ORDER BY datetime DESC
LIMIT 1
 RETURNING history_sid INTO new_history_sid;

答案 1 :(得分:1)

这不是很好或者特别优化,但有几种方法可以解决这个问题。理想情况下,您可能希望在UPDATE触发器中执行此操作,尽管您可以实现类似这样的复制功能:

-- create source table
CREATE TABLE history (history_id serial not null primary key, col_2 int, col_3 int, col_4 int, datetime timestamptz default now());

-- add some data
INSERT INTO history (col_2, col_3, col_4)
  SELECT g, g * 10, g * 100 FROM generate_series(1, 100) AS g;

-- function to duplicate record
CREATE OR REPLACE FUNCTION fn_history_duplicate(p_history_id integer) RETURNS SETOF history AS
$BODY$
DECLARE
  cols text;
  insert_statement text;
BEGIN

  -- build list of columns
  SELECT array_to_string(array_agg(column_name::name), ',') INTO cols
    FROM information_schema.columns 
    WHERE (table_schema, table_name) = ('public', 'history')
    AND column_name <> 'history_id';

  -- build insert statement
  insert_statement := 'INSERT INTO history (' || cols || ') SELECT ' || cols || ' FROM history WHERE history_id = $1 RETURNING *';

  -- execute statement
  RETURN QUERY EXECUTE insert_statement USING p_history_id;

  RETURN;

END;
$BODY$
  LANGUAGE 'plpgsql';

-- test
SELECT * FROM fn_history_duplicate(1);
 history_id | col_2 | col_3 | col_4 |           datetime            
------------+-------+-------+-------+-------------------------------
        101 |     1 |    10 |   100 | 2013-04-15 14:56:11.131507+00
(1 row)

正如我在原始评论中所述,您可能还会查看colnames extension作为查询信息架构的替代方法。