2016-02-10 2 views
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.

+4

Вы выбираете (константу) значение '3' для ** каждой ** строки в' test' как значение для столбца 'id' в целевой таблице. Поскольку исходная таблица содержит более одной строки, вы пытаетесь вставить значение '3' несколько раз в' test_copy', которое вам не разрешено делать, потому что 'id' определяется как первичный ключ –

+0

Христос всемогущий ... Я забыл предложение WHERE.Это должна быть самая глупая ошибка, которую я когда-либо делал, по сравнению с суммой всей работы, потраченной впустую, чтобы найти фактический источник проблемы. Этот вопрос не должен быть здесь. Тем не менее, спасибо. Если вы сделаете этот комментарий в ответ, я сразу приму его (поскольку это был первый «ответ» в моих глазах) и исчезнуть в бездне стыда. ура – Tomalla

ответ

0

Ну, вопрос был полным без событий , На первые две минуты ответили @a_horse_with_no_name в разделе комментариев после его публикации (спасибо вам), и сама проблема была почти ошибкой новобранец.

Теперь, после ожидания нескольких дней, я чувствую, что готов закрыть вопрос, предоставив законный ответ, каким бы очевидным он ни был.

Я полностью забыл о статье WHERE в моем подзапросе SELECT. Вместо этого следует написать следующее:

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

И это было бы по этому вопросу.

1

Вам необходимо создать новый идентификатор для каждой записи.

Вместо

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

, которые используют всегда идентификатор 3 для каждой записи, присутствующей в тесте.

Попробуйте использовать следующий код, если идентификатор типа автоинкремент.

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

В этом случае вы теряете исходный идентификатор. Если вам необходимо его поддерживать исходный идентификатор вам нужно изменить структуру таблицы с чем-то вроде следующего:

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); 
Смежные вопросы