Ошибка PostgreSQL: связь уже существует
Я пытаюсь создать таблицу, которая была удалена ранее.
Но когда я делаю CREATE TABLE A ..
, Я получаю ниже ошибки:
Отношение "А" уже существует.
Я подтвердил SELECT * FROM A
, но потом я получил еще одну ошибку:
Отношение "А" не существует.
Я уже пытался найти его в \dS+
список всех отношений, и его там нет.
Чтобы усложнить это, я проверил это, создав эту таблицу в другой базе данных, и я получил ту же ошибку. Я думаю, что это может быть ошибкой, когда эта таблица была удалена. Есть идеи?
Вот код: я использую сгенерированный код из Power SQL. У меня та же ошибка без использования последовательности. Это просто работает, когда я меняю имя, и в этом случае я не могу этого сделать.
CREATE SEQUENCE csd_relationship_csd_relationship_id_seq;
CREATE TABLE csd_relationship (
csd_relationship_id INTEGER NOT NULL DEFAULT nextval('csd_relationship_csd_relationship_id_seq'::regclass),
type_id INTEGER NOT NULL,
object_id INTEGER NOT NULL,
CONSTRAINT csd_relationship PRIMARY KEY (csd_relationship_id)
);
13 ответов
Я наконец обнаружил ошибку. Проблема в том, что имя ограничения первичного ключа совпадает с именем таблицы. Я не знаю, как postgres представляет ограничения, но я думаю, что ошибка "Отношение уже существует" была вызвана во время создания ограничения первичного ключа, потому что таблица уже была объявлена. Но из-за этой ошибки таблица не была создана в конце.
Здесь не должно быть одинарных кавычек 'A'
, Одинарные кавычки для строковых литералов: 'some value'
,
Либо используйте двойные кавычки, чтобы сохранить прописные буквы "A":
CREATE TABLE "A" ...
Или вообще не используйте кавычки:
CREATE TABLE A ...
который идентичен
CREATE TABLE a ...
потому что все идентификаторы без кавычек автоматически складываются в нижний регистр в PostgreSQL.
Вы можете полностью избежать проблем с именем индекса, используя более простой синтаксис:
CREATE TABLE csd_relationship (
csd_relationship_id serial PRIMARY KEY,
type_id integer NOT NULL,
object_id integer NOT NULL
);
Делает так же, как ваш исходный запрос, только он автоматически избегает конфликтов имен. Он автоматически выбирает следующий бесплатный идентификатор. Подробнее о серийном типе в руководстве.
Вы не можете создать таблицу с именем, идентичным существующей таблице или представлению в кластере. Чтобы изменить существующую таблицу, используйте ALTER TABLE
(ссылка), или чтобы удалить все данные, находящиеся в данный момент в таблице, и создать пустую таблицу с нужной схемой, выполните команду: DROP TABLE
до CREATE TABLE
,
Может быть, что последовательность, которую вы создаете, является виновником. В PostgreSQL последовательности реализованы в виде таблицы с определенным набором столбцов. Если у вас уже есть определенная последовательность, вы, вероятно, должны пропустить ее создание. К сожалению, в CREATE SEQUENCE
к IF NOT EXISTS
конструкция доступна в CREATE TABLE
, Судя по всему, в любом случае вы можете создавать свою схему безоговорочно, поэтому разумно использовать
DROP TABLE IF EXISTS csd_relationship;
DROP SEQUENCE IF EXISTS csd_relationship_csd_relationship_id_seq;
до обновления вашей остальной схемы; В случае, если это не очевидно, это удалит все данные в csd_relationship
стол, если есть
Другая причина, по которой вы можете получить такие ошибки, как "отношение уже существует", заключается в том, что DROP
Команда не выполнена правильно.
Одна из причин, по которой это может произойти, заключается в том, что если к базе данных подключены другие сеансы, которые необходимо закрыть в первую очередь.
В моем случае у меня была последовательность с тем же именем.
В моем случае, это было до тех пор, пока я не приостановил пакетный файл и не прокрутил немного вверх, это была не единственная ошибка, которую я получил. мой DROP
командование стало DROP
и поэтому таблица не опускалась во-первых (таким образом, отношение действительно все еще существовало). 
Я узнал, что это называется меткой порядка байтов (BOM). Открыв это в Notepad++, повторно сохраните файл SQL с установленной кодировкой UTM-8 без спецификации, и он будет работать нормально.
Вы можете запустить
CREATE TABLE
после того, как уже запустил его. Таким образом, вы можете создать таблицу во второй раз, а первая попытка уже создала ее.
Иногда такая ошибка возникает, когда вы создаете таблицы с разными пользователями базы данных и пытаетесь
SELECT
с другим пользователем. Вы можете предоставить все привилегии, используя запрос ниже.
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA schema_name TO username;
А также вы можете предоставить доступ для операторов DML
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA schema_name TO username;
В моем случае я мигрировал с 9,5 до 9,6. Итак, чтобы восстановить базу данных, я делал:
sudo -u postgres psql -d databse -f dump.sql
Конечно, это выполнялось на старой базе данных postgreSQL, где есть данные! Если ваш новый экземпляр находится на порту 5433, правильный путь:
sudo -u postgres psql -d databse -f dump.sql -p 5433
Проблема в том, что имя ограничения первичного ключа совпадает с именем таблицы.
Я не знаю, как postgres представляет ограничения, но я думаю, что ошибка «Связь уже существует» срабатывала во время создания ограничения первичного ключа, потому что таблица уже была объявлена. Но из-за этой ошибки таблица не была создана в конце.
дать другое имя для ограничения
Примечание. Перейдите на вкладку SQL и проверьте имя таблицы и ограничение.
Наслаждаться :)
Вы уже обнаружили, что корень проблемы заключался в том, что первичный ключ имел то же имя, что и таблица, но позвольте мне объяснить, почему это проблема.
Все первичные и уникальные ограничения реализуются с использованием уникальных индексов. В PostgreSQL этот индекс должен иметь то же имя, что и ограничение. Итак, ваша команда пытается создать индекс с именемcsd_relationship
, как и таблица.
Теперь в PostgreSQL таблицы, индексы, последовательности, представления и составные типы данных используют одно и то же пространство имен , то есть в одной схеме не может быть двух из них с одинаковым именем. Техническая причина в том, что метаданные всех этих объектов хранятся в таблице каталога, иpg_class
имеет уникальное ограничение на(relname, relnamespace)
, то есть сочетание имени таблицы и схемы.
моя ошибка:
cteate table xr_inbound_req(.......
CONSTRAINT table_name PRIMARY KEY (id)
)
при изменении на это:
cteate table xr_inbound_req(.......
CONSTRAINT pk_table_name PRIMARY KEY (id)
)
все ок,
добавьpk_
префикс
Я получил эту ошибку после запуска команды терминала «обновление базы данных dotnet ef». Мое решение состояло в том, чтобы открыть базу данных и удалить/удалить таблицы с тем же именем.