Ошибка 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». Мое решение состояло в том, чтобы открыть базу данных и удалить/удалить таблицы с тем же именем.

Другие вопросы по тегам