2011-11-30 19 views
32

He revisado la documentación proporcionada por Oracle y encontré una forma de modificar una restricción sin soltar la tabla. El problema es que se equivoca al modificar ya que no reconoce la palabra clave.Intentando modificar una restricción en PostgreSQL

Usando EMS SQL Manager para PostgreSQL.

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

I fue capaz de trabajar alrededor de ella por dejar caer 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; 
+9

¿Por qué está revisando la documentación de Oracle (y etiquetando esta pregunta con 'plsql') cuando usa PostgreSQL? ¿Cuál es el error exacto (qué palabra clave no se reconoce)? – Bruno

+0

ERROR: error de sintaxis en o cerca de "Modificar" LINE 1: ALTER TABLE public.public_insurer_credit MODIFICAR CONSTRAINT p ... ^ (0.359 seg) – MISMajorDeveloperAnyways

+7

Comprobación docs Oracle para Postgres, y luego culpar Postgres. Épico. –

Respuesta

23

Según el manual correcta (que es suministrado por PostgreSQL, no por Oracle), no hay Modificar limitación disponible en la sentencia ALTER TABLE:

Aquí está el enlace al manual correcta:

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

+0

Gracias por el enlace a la documentación adecuada. Recibí la documentación Oracle PL/SQL de nuestro DBA. Figuras – MISMajorDeveloperAnyways

+2

Oracle y Oracle PL/SQL son cosas completamente diferentes. La única razón posible por la que lo hicieron es porque está utilizando * Advanced Server * de EnterpriseDB que tiene soporte para PL/SQL de Oracle (y otras características de compatibilidad de Oracle). Pero entonces deberían haberle dado el manual de EnterpriseDB, no el manual de Oracle. –

+1

¿Alguien puede explicar por qué esta respuesta obtuvo un voto a favor? –

52

No hay ningún comando ALTER para las restricciones en Postgres. La forma más fácil de lograr esto es soltar la restricción y volver a agregarla 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; 
+14

+1 por hacerlo en una transacción. –

+5

Cuidado: si entiendo correctamente, las instrucciones DDL tienen un bloqueo AccessExclusive en la tabla, por lo que si estos comandos toman mucho tiempo, su sitio se detendrá hasta que se completen los comandos. La [página de documentación] (http://www.postgresql.org/docs/current/static/sql-altertable.html) tiene más detalles, que incluyen cómo especificar un índice explícitamente en lugar de tener uno generado automáticamente. –

25

partir de la versión 9.4, PostgreSQL soporta ALTER TABLE ... ALTER CONSTRAINT de claves externas.

Esta característica será "Allow constraint attributes to be altered, so the default setting of NOT DEFERRABLE can be altered to DEFERRABLE and back." En cuanto a su pregunta, creo que es (algo así) lo que ha estado buscando.

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

+2

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

+1

Tenga en cuenta que los documentos 9.4 dicen '¡Actualmente solo se pueden modificar las restricciones de clave externa! –

+0

@MichaelHerrmann Ya mencioné esto en mi respuesta. – mkurz

2

ALTER CONSTREÑIMIENTO requeriría conocer el nombre de clave externa, que no siempre es conveniente.

Aquí está la función, donde solo necesita conocer los nombres de tablas y columnas. 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á atributos de clave externa inicial. Solo toma el nombre de la tabla/nombre de columna foránea, coloca la clave actual y reemplaza por una nueva.

+0

Solución muy interesante – tom10271

Cuestiones relacionadas