Попытка изменить ограничение в PostgreSQL - PullRequest
47 голосов
/ 30 ноября 2011

Я проверил документацию, предоставленную Oracle, и нашел способ изменить ограничение, не удаляя таблицу.Проблема в том, что при изменении он выдает ошибку, поскольку не распознает ключевое слово.

Использование EMS SQL Manager для PostgreSQL.

Alter table public.public_insurer_credit MODIFY CONSTRAINT public_insurer_credit_fk1
    deferrable, initially deferred;

Мне удалось обойти его, сняв ограничение с помощью:

ALTER TABLE "public"."public_insurer_credit"
  DROP CONSTRAINT "public_insurer_credit_fk1" RESTRICT;

ALTER TABLE "public"."public_insurer_credit"
  ADD CONSTRAINT "public_insurer_credit_fk1" FOREIGN KEY ("branch_id", "order_id", "public_insurer_id")
    REFERENCES "public"."order_public_insurer"("branch_id", "order_id", "public_insurer_id")
    ON UPDATE CASCADE
    ON DELETE NO ACTION
    DEFERRABLE 
    INITIALLY DEFERRED;

Ответы [ 4 ]

78 голосов
/ 30 ноября 2011

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

BEGIN;
ALTER TABLE t1 DROP CONSTRAINT ...
ALTER TABLE t1 ADD CONSTRAINT ...
COMMIT;
32 голосов
/ 30 ноября 2011

Согласно правильному руководству (которое поставляется PostgreSQL, не Oracle), в выражении ALTER TABLE нет ограничения на изменение:

Вот ссылка на правильное руководство:

http://www.postgresql.org/docs/current/static/sql-altertable.html

31 голосов
/ 28 августа 2013

Начиная с версии 9.4, PostgreSQL поддерживает ALTER TABLE ... ALTER CONSTRAINT для внешних ключей.

Эта функция будет "Allow constraint attributes to be altered, so the default setting of NOT DEFERRABLE can be altered to DEFERRABLE and back." Глядя на ваш вопрос, я думаю, что это (вроде) то, что вы искали.

Более подробную информацию и пример можно найти здесь:
http://www.depesz.com/2013/06/30/waiting-for-9-4-alter-table-alter-constraint-for-fks/

5 голосов
/ 03 октября 2015

ALTER CONSTRAINT потребует знания имени внешнего ключа, что не всегда удобно.

Вот функция, в которой вам нужно знать только имена таблиц и столбцов.Использование:

select replace_foreign_key('user_rates_posts', 'post_id', 'ON DELETE CASCADE');

Функция:

CREATE OR REPLACE FUNCTION 
    replace_foreign_key(f_table VARCHAR, f_column VARCHAR, new_options VARCHAR) 
RETURNS VARCHAR
AS $$
DECLARE constraint_name varchar;
DECLARE reftable varchar;
DECLARE refcolumn varchar;
BEGIN

SELECT tc.constraint_name, ccu.table_name AS foreign_table_name, ccu.column_name AS foreign_column_name 
FROM 
    information_schema.table_constraints AS tc 
    JOIN information_schema.key_column_usage AS kcu
      ON tc.constraint_name = kcu.constraint_name
    JOIN information_schema.constraint_column_usage AS ccu
      ON ccu.constraint_name = tc.constraint_name
WHERE constraint_type = 'FOREIGN KEY' 
   AND tc.table_name= f_table AND kcu.column_name= f_column
INTO constraint_name, reftable, refcolumn;

EXECUTE 'alter table ' || f_table || ' drop constraint ' || constraint_name || 
', ADD CONSTRAINT ' || constraint_name || ' FOREIGN KEY (' || f_column || ') ' ||
' REFERENCES ' || reftable || '(' || refcolumn || ') ' || new_options || ';';

RETURN 'Constraint replaced: ' || constraint_name || ' (' || f_table || '.' || f_column ||
 ' -> ' || reftable || '.' || refcolumn || '); New options: ' || new_options;

END;
$$ LANGUAGE plpgsql;

Помните: эта функция не будет копировать атрибуты исходного внешнего ключа.Он берет только внешнее имя таблицы / имя столбца, удаляет текущий ключ и заменяет новым.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...