postgresql constraints cascade cascading-deletes postgresql-8.4

postgresql - ¿Cómo agregar restricciones de "on delete cascade"?



constraints cascading-deletes (2)

Estoy bastante seguro de que no puede simplemente agregar on delete cascade a una restricción de clave externa existente. Primero debe soltar la restricción y luego agregar la versión correcta. En SQL estándar, creo que la forma más fácil de hacerlo es

  • comenzar una transacción,
  • soltar la clave externa,
  • agregar una clave foránea on delete cascade , y finalmente
  • comprometer la transacción

Repita para cada tecla externa que quiera cambiar.

Pero PostgreSQL tiene una extensión no estándar que le permite usar múltiples cláusulas de restricción en una sola instrucción SQL. Por ejemplo

alter table public.pref_scores drop constraint pref_scores_gid_fkey, add constraint pref_scores_gid_fkey foreign key (gid) references pref_games(gid) on delete cascade;

Si no conoce el nombre de la restricción de clave externa que desea eliminar, puede buscarla en pgAdminIII (simplemente haga clic en el nombre de la tabla y mire el DDL, o expanda la jerarquía hasta que vea "Restricciones"), o puede consultar el esquema de información .

select * from information_schema.key_column_usage where position_in_unique_constraint is not null

En PostgreSQL 8, ¿es posible agregar "on delete cascades" a las dos claves foráneas en la siguiente tabla sin descartar este último?

# /d pref_scores Table "public.pref_scores" Column | Type | Modifiers ---------+-----------------------+----------- id | character varying(32) | gid | integer | money | integer | not null quit | boolean | last_ip | inet | Foreign-key constraints: "pref_scores_gid_fkey" FOREIGN KEY (gid) REFERENCES pref_games(gid) "pref_scores_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id)

Ambas tablas referenciadas están debajo - aquí:

# /d pref_games Table "public.pref_games" Column | Type | Modifiers ----------+-----------------------------+---------------------------------------------------------- gid | integer | not null default nextval(''pref_games_gid_seq''::regclass) rounds | integer | not null finished | timestamp without time zone | default now() Indexes: "pref_games_pkey" PRIMARY KEY, btree (gid) Referenced by: TABLE "pref_scores" CONSTRAINT "pref_scores_gid_fkey" FOREIGN KEY (gid) REFERENCES pref_games(gid)

Y aquí:

# /d pref_users Table "public.pref_users" Column | Type | Modifiers ------------+-----------------------------+--------------- id | character varying(32) | not null first_name | character varying(64) | last_name | character varying(64) | female | boolean | avatar | character varying(128) | city | character varying(64) | login | timestamp without time zone | default now() last_ip | inet | logout | timestamp without time zone | vip | timestamp without time zone | mail | character varying(254) | Indexes: "pref_users_pkey" PRIMARY KEY, btree (id) Referenced by: TABLE "pref_cards" CONSTRAINT "pref_cards_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) TABLE "pref_catch" CONSTRAINT "pref_catch_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) TABLE "pref_chat" CONSTRAINT "pref_chat_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) TABLE "pref_game" CONSTRAINT "pref_game_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) TABLE "pref_hand" CONSTRAINT "pref_hand_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) TABLE "pref_luck" CONSTRAINT "pref_luck_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) TABLE "pref_match" CONSTRAINT "pref_match_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) TABLE "pref_misere" CONSTRAINT "pref_misere_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) TABLE "pref_money" CONSTRAINT "pref_money_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) TABLE "pref_pass" CONSTRAINT "pref_pass_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) TABLE "pref_payment" CONSTRAINT "pref_payment_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) TABLE "pref_rep" CONSTRAINT "pref_rep_author_fkey" FOREIGN KEY (author) REFERENCES pref_users(id) TABLE "pref_rep" CONSTRAINT "pref_rep_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) TABLE "pref_scores" CONSTRAINT "pref_scores_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id) TABLE "pref_status" CONSTRAINT "pref_status_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id)

Y también me pregunto si tiene sentido agregar 2 índices a la tabla anterior.

ACTUALIZACIÓN: Gracias, y también tengo el consejo en la lista de correo, que podría administrarlo en 1 estado y así no necesitaría una transacción:

ALTER TABLE public.pref_scores DROP CONSTRAINT pref_scores_gid_fkey, ADD CONSTRAINT pref_scores_gid_fkey FOREIGN KEY (gid) REFERENCES pref_games(gid) ON DELETE CASCADE;


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 que esta función no copiará los atributos de la clave externa inicial. Solo toma el nombre de la tabla / nombre de columna foránea, descarta la clave actual y la reemplaza por una nueva.