在Postgresql中创建重复行

时间:2018-04-08 08:52:37

标签: postgresql duplicates

我正在编写迁移脚本来迁移数据库。考虑到不同的数据库在表中可以有n个不同的列,我必须通过递增主键来复制行。我无法在查询中编写每一列。如果我只是复制该行,那么我将收到重复的密钥错误。

Query: INSERT INTO table_name SELECT * FROM table_name WHERE id=255;

ERROR:  duplicate key value violates unique constraint "table_name_pkey"
DETAIL:  Key (id)=(255) already exist

在这里,我不必提及所有列名称。我可以通过*来选择所有列。但是,同时我也遇到了重复的密钥错误。

这个问题的解决方案是什么?任何帮助,将不胜感激。提前谢谢。

2 个答案:

答案 0 :(得分:1)

如果您愿意输入所有列名,可以写

INSERT INTO table_name (
    pri_key
    ,col2
    ,col3
    )
SELECT (
        SELECT MAX(pri_key) + 1
        FROM table_name
        )
    ,col2
    ,col3
FROM table_name
WHERE id = 255;

其他选项(不键入所有列,但您知道主键)是CREATE临时表,更新它并在事务中重新插入。

BEGIN;
CREATE TEMP TABLE temp_tab ON COMMIT DROP AS SELECT * FROM table_name WHERE id=255;
UPDATE temp_tab SET pri_key_col = ( select MAX(pri_key_col) + 1 FROM table_name );
INSERT INTO table_name select * FROM temp_tab;
COMMIT;

答案 1 :(得分:1)

这只是一个DO块,但您可以创建一个函数,将表名等内容作为参数。

设定:

CREATE TABLE public.t1 (a TEXT, b TEXT, c TEXT, id SERIAL PRIMARY KEY, e TEXT, f TEXT);
INSERT INTO public.t1 (e) VALUES ('x'), ('y'), ('z');

重复没有主键列的值的代码:

DO $$
DECLARE
        _table_schema   TEXT := 'public';
        _table_name     TEXT := 't1';
        _pk_column_name TEXT := 'id';
        _columns        TEXT;
BEGIN
        SELECT STRING_AGG(column_name, ',')
                INTO _columns
        FROM information_schema.columns
        WHERE table_name = _table_name
        AND table_schema = _table_schema
        AND column_name <> _pk_column_name;

        EXECUTE FORMAT('INSERT INTO %1$s.%2$s (%3$s) SELECT %3$s FROM %1$s.%2$s', _table_schema, _table_name, _columns);
END $$

它创建并运行的查询是:INSERT INTO public.t1 (a,b,c,e,f) SELECT a,b,c,e,f FROM public.t1。它选择了除PK之外的所有列。您可以将此代码放在一个函数中,并将其用于您想要的任何表,或者只是像这样使用它并为任何表编辑它。