首页 文章

插入时空表上持久的“唯一约束违例”

提问于
浏览
2

我们假设我正在管理一个简单的表格 . 此外,每个用户可以间接创建每行的副本并自行修改 .

这是我的设置:

-- the original table
CREATE TABLE test
(
    id integer PRIMARY KEY,
    a integer,
    b integer NOT NULL,
    c integer
);

-- the table holding a modified copy of the former table
CREATE TABLE test_copy
(
    copy_position integer NOT NULL, -- some additional data attached to the copy
    id integer PRIMARY KEY REFERENCES test(id), -- the id of the copied row
    a integer,
    b integer NOT NULL,
    c integer
);

-- some sample data
INSERT INTO test VALUES (1, 4, 4, 4), (2, 7, 3, 2), (3, 72, 23, 7), (4, 11, 22, 33);

我必须创建一个函数,它复制 test 表中的现有行 . 但是,以下声明应该执行此操作,但失败了:

INSERT INTO test_copy(copy_position, id, a, b, c)
    (SELECT 666, 3, t.a, t.b, t.c
        FROM test AS t);

发出以下错误:

ERROR:  duplicate key value violates unique constraint "test_copy_pkey"
DETAIL:  Key (id)=(3) already exists.

test_copy 表完全为空 . 前一个语句是唯一的 INSERT 语句,为表提供任何行,但它以某种方式违反了唯一约束 . 手动插入值而不使用 SELECT 子查询将成功执行 . 经过几个小时的研究,我使用PostgreSQL 9.4 .

2 回答

  • 0

    您需要为每条记录创建一个新ID .

    代替

    INSERT INTO test_copy(copy_position, id, a, b, c)
        (SELECT 666, 3, t.a, t.b, t.c
            FROM test AS t);
    

    对测试中存在的每条记录始终使用id 3 .

    如果id是autoincrement类型,请尝试使用以下代码 .

    INSERT INTO test_copy(copy_position, a, b, c)
        (SELECT 666, t.a, t.b, t.c
            FROM test AS t);
    

    在这种情况下,您将丢失原始ID . 如果您需要保留原始ID,则需要使用以下内容更改表结构:

    CREATE TABLE test_copy
    (
        copy_position integer NOT NULL, -- some additional data attached to the copy
        id integer PRIMARY KEY autoincrement,
        original_id FOREIGN KEY REFERENCES test(id), -- the id of the copied row
        a integer,
        b integer NOT NULL,
        c integer
    );
    

    并且插入变为:

    INSERT INTO test_copy(copy_position, original_id, a, b, c)
            (SELECT 666, t.id, t.a, t.b, t.c
                FROM test AS t);
    
  • 1

    好吧,问题是一个完整的非事件 . @a_horse_with_no_name在发布后的评论部分中已经回答了前两分钟(谢谢你)并且问题本身几乎是一个菜鸟错误 .

    现在,在等了几天之后,我觉得通过提供一个合理的答案来解决这个问题,无论多么明显 .

    我完全忘记了 SELECT 子查询中的 WHERE 子句 . 它应该写成如下:

    INSERT INTO test_copy(copy_position, id, a, b, c)
        (SELECT 666, t.id, t.a, t.b, t.c
            FROM test AS t WHERE t.id = 3);
    

    那就是这个问题 .

相关问题