Обновление ссылочных столбцов в Postgres
-
04-07-2019 - |
Вопрос
Когда есть один или несколько столбцов, которые ссылаются на другой, я борюсь за лучший способ обновить этот столбец при сохранении ссылочной целостности. Например, если у меня есть таблица меток и описаний и две записи:
Label | Description
------------------------------------
read | This item has been read
READ | You read this thing already
Теперь я не хочу этих дубликатов. Я хочу добавить в столбец ограничение, которое не допускает дублирования значений без учета регистра, как в примере. Однако у меня есть несколько строк из нескольких других таблиц, ссылающихся на «READ», которую я хочу удалить.
Я знаю, что Postgres знает, какие поля других строк ссылаются на это, потому что я не могу удалить его, пока они там есть. Итак, как я могу получить любое поле, ссылающееся на это, чтобы обновить до «чтения»? Это всего лишь пример, и у меня есть несколько мест, где я хочу это сделать. Другой пример - это на самом деле первичный ключ int для нескольких таблиц, где я хочу добавить новую таблицу в качестве своего рода «базовой таблицы», которую расширяют существующие, и поэтому им всем теперь понадобятся уникальные идентификаторы, что означает обновление те, которые у них есть.
Я открыт для рецептов функций, которые я могу добавить для этого, инструментов, которые я могу использовать, или чего-либо еще.
Решение
Если у вас есть много строк, ссылающихся на READ, вы можете изменить внешний ключ для каскадного обновления, обновить этот набор таблиц Label = 'read', где Label = 'READ', и все будет автоматически исправлено. После этого вы можете снова изменить ограничение, чтобы оно было таким, как было раньше.
Чтобы найти все таблицы, ссылающиеся на столбец, вы можете использовать
select TABLE_NAME,COLUMN_NAME,CONSTRAINT_NAME,
REFERENCED_TABLE_NAME,REFERENCED_COLUMN_NAME from
INFORMATION_SCHEMA.KEY_COLUMN_USAGE where
REFERENCED_TABLE_NAME = '<table>' AND REFERENCED_COLUMN_NAME = '<column>'
Другие советы
В будущем вы можете создать уникальный индекс для столбца " метка " ;, например:
CREATE UNIQUE INDEX index_name ON table ((lower(label)));
Или ознакомьтесь с руководством . Это поможет вам избежать этой ситуации в следующий раз.