строки, нарушающие уникальные ограничения

У меня есть база данных postgres 8.3.4. Таблица имен существует с уникальным ограничением на тройку UNIQ (имя, идентификатор, возраст). Каким-то образом в базу данных было добавлено несколько строк, которые нарушают это ограничение.

У меня вопрос, как это возможно? Разве база данных не должна была выдать ошибку при добавлении первой строки, которая нарушала бы ограничение?

имя: текст
id: целое число не нуль (fk в таблицу идентификаторов)
возраст: целое число


person Finslicer    schedule 22.04.2012    source источник
comment
PostgreSQL 8.3 больше не поддерживается. Если по какой-то непонятной причине вы не можете выполнить обновление до текущей версии (9.x), вам следует хотя бы обновить до последней версии 8.3, то есть 8.3.18.   -  person a_horse_with_no_name    schedule 23.04.2012
comment
Вы уверены, что имена совпадают? Вы контролировали конечное белое пространство? Кроме того, как многие люди уже прокомментировали, было бы разумно перейти на текущую версию PostgreSQL: postgresql.org/support/versioning   -  person Andrew    schedule 24.04.2012


Ответы (2)


Мое предположение заключается в том, что вы упускаете из виду тот факт, что NULL значения никогда не равны UNIQUE.
Если вы введете (NULL, 1, 20) для (name, id, age) несколько раз, вы не получите однозначного нарушения. Два NULL значения никогда не считаются «одинаковыми».

Вы можете установить все задействованные столбцы NOT NULL (после замены значений NULL фиктивными значениями).

Или вы можете реализовать дополнительные частичные индексы , чтобы закрыть NULL (после очистки "дубликатов" с NULL). Например, если вам нужно покрыть столбец name для NULL:

CREATE UNIQUE INDEX tbl_id_age_name_null_idx ON my_table (id, age)
WHERE name IS NULL;

Затем вы можете иметь ('pete', 1, 20) и ('jane', 1, 20) и (NULL, 1, 20) для (name, id, age) в своей таблице, но ни один из них во второй раз . Недавно я написал более подробную оценку этого случая на dba.SE.

Кстати: вам следует подумать об обновлении вашей версии PostgreSQL. Желательно к актуальной версии 9.1. Или хотя бы до последней версии 8.3.18. Было внесено множество исправлений.

person Erwin Brandstetter    schedule 22.04.2012
comment
все три столбца защищены ненулевым ограничением - person Finslicer; 23.04.2012
comment
@Finslicer: Возможно, вы захотите отредактировать свой вопрос. Информация там не отражает то, что вы здесь комментируете. - person Erwin Brandstetter; 23.04.2012

Это вряд ли возможно.

Скорее всего, у вас есть лишние пробелы в именах или что-то в этом роде.

Выложите, пожалуйста, точное определение таблицы.

Также запустите этот запрос:

SELECT  q2.*
FROM    (
        SELECT  name, id, age
        FROM    mytable
        GROUP BY
                name, id, age
        HAVING  COUNT(*) > 1
        ) q
JOIN    mytable q2
ON      (q2.name, q2.id, q2.age) IS NOT DISTINCT FROM (q.name, q.id, q.age)

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

person Quassnoi    schedule 22.04.2012