Intentar modificar una restricción en PostgreSQL


He comprobado la documentación proporcionada por Oracle y he encontrado una manera de modificar una restricción sin dejar caer la tabla. El problema es que se equivoca al modificar, ya que no reconoce la palabra clave.

Usando EMS SQL Manager para PostgreSQL.

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

Pude evitarlo eliminando la restricción usando:

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;
Author: Brad Koch, 2011-11-30

4 answers

De acuerdo con el manual correcto (que es suministrado por PostgreSQL, no por Oracle), no hay restricción modify disponible en la instrucción ALTER TABLE:

Aquí está el enlace al manual correcto:

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

 28
Author: a_horse_with_no_name,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-30 17:49:07

No hay un comando ALTER para restricciones en Postgres. La forma más fácil de lograr esto es soltar la restricción y volver a añadirla con los parámetros deseados. Por supuesto, cualquier cambio de la restricción se ejecutará contra los datos de la tabla actual.

BEGIN;
ALTER TABLE t1 DROP CONSTRAINT ...
ALTER TABLE t1 ADD CONSTRAINT ...
COMMIT;
 61
Author: Chris Cashwell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-30 17:50:34

A partir de la versión 9.4, PostgreSQL soporta ALTER TABLE ... ALTER CONSTRAINT para claves foráneas.

Estas características "Allow constraint attributes to be altered, so the default setting of NOT DEFERRABLE can be altered to DEFERRABLE and back." Mirando su pregunta creo que es (algo así) lo que ha estado buscando.

Se puede encontrar información más detallada y un ejemplo here:
http://www.depesz.com/2013/06/30/waiting-for-9-4-alter-table-alter-constraint-for-fks/

 29
Author: mkurz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-27 20:00:29

ALTER CONSTRAINT requeriría conocer el nombre de la clave foránea, lo cual no siempre es conveniente.

Aquí está la función, donde necesita saber solo los nombres de tabla y columna. Uso:

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

Función:

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;

Tenga en cuenta: esta función no copiará los atributos de la clave foránea inicial. Solo toma nombre de tabla / nombre de columna extranjero, elimina la clave actual y reemplaza con una nueva.

 4
Author: Dan Key,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-03 09:25:13