質問
私はPostgresqlのデータベースにしたいと思い少数のカスケードを削除.しかし、テーブルな設定の削除カスケードの規則です。がんに削除いPostgresqlカスケードまでは一回しか出来ないのですか?ものと同等の
DELETE FROM some_table CASCADE;
の答えを この古い問題 うような解は存在しますが、きっかけになるかもしれないと思いこの問いを明示的にされる方もいるでしょう。
解決
No.いかだそのdeleteステートメントを表したいカスケード.
DELETE FROM some_child_table WHERE some_fk_field IN (SELECT some_id FROM some_Table);
DELETE FROM some_table;
他のヒント
望 DELETE FROM some_table CASCADE;
ること"すべて削除し列からテーブル some_table
"利用でき TRUNCATE
の代わりに DELETE
や CASCADE
常に対応します。しかし、利用したい場合は選択的に削除する where
節 TRUNCATE
ではでは十分ではありません。
大切に使う -この 下のすべての行がすべてのテーブル る外部キー制約 some_table
すべてのテーブルとしての制約は、これらのテーブル等
Postgresの支援 CASCADE
と コマンドで切り詰め:
TRUNCATE some_table CASCADE;
手際よくこする取引(できるロールバック)は完全に分離したその他の兼職の状況取引数その他の注意.読みのドキュメントします。
私は、(再帰的機能を削除列に基づきその有効なタイプを利用します。書いたことがたかったわけではありませんを制約としての"削除カスケード".たかったのを抹消することができるものと複雑なセットのデータとしてDBA)ができない私のプログラマーがカスケードの削除せずに考える影響.まだ試験はこの機能であるバグではないでくださいってみればDBは、このライブラリの目的は次(つまり、外できます。また、キーのすべてにすることができる代表される文字列形式で記述できるようになっていることにしました。その結果が、先ほど任天堂さんの機能も控えめにとにかく、値データも多くのカスケードの制約です。基本的にはこの関数に渡されるスキーマ、テーブル名は、次の値(文字列形式)で開始するには見外部キーがテーブルを確認しますデータが存在しない--の場合は、再帰的に呼itsselfは見つかります。この配列のデータは削除の対象から除外されるのを防ぐの無限ルです。ぜひ試してください出の流れを教えてくださいお勧めしていません。注意:ちょっと遅くなります。黒ざくろさん、難しい話ではこのように:select delete_cascade('public','my_table','1');
create or replace function delete_cascade(p_schema varchar, p_table varchar, p_key varchar, p_recursion varchar[] default null)
returns integer as $$
declare
rx record;
rd record;
v_sql varchar;
v_recursion_key varchar;
recnum integer;
v_primary_key varchar;
v_rows integer;
begin
recnum := 0;
select ccu.column_name into v_primary_key
from
information_schema.table_constraints tc
join information_schema.constraint_column_usage AS ccu ON ccu.constraint_name = tc.constraint_name and ccu.constraint_schema=tc.constraint_schema
and tc.constraint_type='PRIMARY KEY'
and tc.table_name=p_table
and tc.table_schema=p_schema;
for rx in (
select kcu.table_name as foreign_table_name,
kcu.column_name as foreign_column_name,
kcu.table_schema foreign_table_schema,
kcu2.column_name as foreign_table_primary_key
from information_schema.constraint_column_usage ccu
join information_schema.table_constraints tc on tc.constraint_name=ccu.constraint_name and tc.constraint_catalog=ccu.constraint_catalog and ccu.constraint_schema=ccu.constraint_schema
join information_schema.key_column_usage kcu on kcu.constraint_name=ccu.constraint_name and kcu.constraint_catalog=ccu.constraint_catalog and kcu.constraint_schema=ccu.constraint_schema
join information_schema.table_constraints tc2 on tc2.table_name=kcu.table_name and tc2.table_schema=kcu.table_schema
join information_schema.key_column_usage kcu2 on kcu2.constraint_name=tc2.constraint_name and kcu2.constraint_catalog=tc2.constraint_catalog and kcu2.constraint_schema=tc2.constraint_schema
where ccu.table_name=p_table and ccu.table_schema=p_schema
and TC.CONSTRAINT_TYPE='FOREIGN KEY'
and tc2.constraint_type='PRIMARY KEY'
)
loop
v_sql := 'select '||rx.foreign_table_primary_key||' as key from '||rx.foreign_table_schema||'.'||rx.foreign_table_name||'
where '||rx.foreign_column_name||'='||quote_literal(p_key)||' for update';
--raise notice '%',v_sql;
--found a foreign key, now find the primary keys for any data that exists in any of those tables.
for rd in execute v_sql
loop
v_recursion_key=rx.foreign_table_schema||'.'||rx.foreign_table_name||'.'||rx.foreign_column_name||'='||rd.key;
if (v_recursion_key = any (p_recursion)) then
--raise notice 'Avoiding infinite loop';
else
--raise notice 'Recursing to %,%',rx.foreign_table_name, rd.key;
recnum:= recnum +delete_cascade(rx.foreign_table_schema::varchar, rx.foreign_table_name::varchar, rd.key::varchar, p_recursion||v_recursion_key);
end if;
end loop;
end loop;
begin
--actually delete original record.
v_sql := 'delete from '||p_schema||'.'||p_table||' where '||v_primary_key||'='||quote_literal(p_key);
execute v_sql;
get diagnostics v_rows= row_count;
--raise notice 'Deleting %.% %=%',p_schema,p_table,v_primary_key,p_key;
recnum:= recnum +v_rows;
exception when others then recnum=0;
end;
return recnum;
end;
$$
language PLPGSQL;
がわかれば、正しく対応することができるでしょうめいしたいものの落下による外部キー制約を追加する新しい一(カスケード)、おもとの復元を制限する外部キー制約
例えば:
testing=# create table a (id integer primary key);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "a_pkey" for table "a"
CREATE TABLE
testing=# create table b (id integer references a);
CREATE TABLE
-- put some data in the table
testing=# insert into a values(1);
INSERT 0 1
testing=# insert into a values(2);
INSERT 0 1
testing=# insert into b values(2);
INSERT 0 1
testing=# insert into b values(1);
INSERT 0 1
-- restricting works
testing=# delete from a where id=1;
ERROR: update or delete on table "a" violates foreign key constraint "b_id_fkey" on table "b"
DETAIL: Key (id)=(1) is still referenced from table "b".
-- find the name of the constraint
testing=# \d b;
Table "public.b"
Column | Type | Modifiers
--------+---------+-----------
id | integer |
Foreign-key constraints:
"b_id_fkey" FOREIGN KEY (id) REFERENCES a(id)
-- drop the constraint
testing=# alter table b drop constraint b_a_id_fkey;
ALTER TABLE
-- create a cascading one
testing=# alter table b add FOREIGN KEY (id) references a(id) on delete cascade;
ALTER TABLE
testing=# delete from a where id=1;
DELETE 1
testing=# select * from a;
id
----
2
(1 row)
testing=# select * from b;
id
----
2
(1 row)
-- it works, do your stuff.
-- [stuff]
-- recreate the previous state
testing=# \d b;
Table "public.b"
Column | Type | Modifiers
--------+---------+-----------
id | integer |
Foreign-key constraints:
"b_id_fkey" FOREIGN KEY (id) REFERENCES a(id) ON DELETE CASCADE
testing=# alter table b drop constraint b_id_fkey;
ALTER TABLE
testing=# alter table b add FOREIGN KEY (id) references a(id) on delete restrict;
ALTER TABLE
もちろん、必要旨れるというような入手続きのためには、メインの目的としておりません。
できないのでコメントpalehorse答えはもちろん自分なりの答えです。Palehorse logickが、効率が悪いとビッグデータのセット。
DELETE FROM some_child_table sct WHERE exists (SELECT FROM some_Table st
where sct.some_fk_fiel=st.some_id );
DELETE FROM some_table;
では迅速い上のインデックス列のデータセットは大きくそして少数の記録です。
利用できる自動化するこの定義ができるの外部キー制約と ON DELETE CASCADE
.
私の見積もり マニュアルの外部キー制約:
CASCADE
指定した場合は、参照列を削除すると、row(s) 参照すべきは自動的に削除されました。
またジョー-アイキャッチのようなもの答えrewroteを使ってこの IN
オペレーターサブを選択しく =
の機能をより速くなっている(Hubbitusの提案):
create or replace function delete_cascade(p_schema varchar, p_table varchar, p_keys varchar, p_subquery varchar default null, p_foreign_keys varchar[] default array[]::varchar[])
returns integer as $$
declare
rx record;
rd record;
v_sql varchar;
v_subquery varchar;
v_primary_key varchar;
v_foreign_key varchar;
v_rows integer;
recnum integer;
begin
recnum := 0;
select ccu.column_name into v_primary_key
from
information_schema.table_constraints tc
join information_schema.constraint_column_usage AS ccu ON ccu.constraint_name = tc.constraint_name and ccu.constraint_schema=tc.constraint_schema
and tc.constraint_type='PRIMARY KEY'
and tc.table_name=p_table
and tc.table_schema=p_schema;
for rx in (
select kcu.table_name as foreign_table_name,
kcu.column_name as foreign_column_name,
kcu.table_schema foreign_table_schema,
kcu2.column_name as foreign_table_primary_key
from information_schema.constraint_column_usage ccu
join information_schema.table_constraints tc on tc.constraint_name=ccu.constraint_name and tc.constraint_catalog=ccu.constraint_catalog and ccu.constraint_schema=ccu.constraint_schema
join information_schema.key_column_usage kcu on kcu.constraint_name=ccu.constraint_name and kcu.constraint_catalog=ccu.constraint_catalog and kcu.constraint_schema=ccu.constraint_schema
join information_schema.table_constraints tc2 on tc2.table_name=kcu.table_name and tc2.table_schema=kcu.table_schema
join information_schema.key_column_usage kcu2 on kcu2.constraint_name=tc2.constraint_name and kcu2.constraint_catalog=tc2.constraint_catalog and kcu2.constraint_schema=tc2.constraint_schema
where ccu.table_name=p_table and ccu.table_schema=p_schema
and TC.CONSTRAINT_TYPE='FOREIGN KEY'
and tc2.constraint_type='PRIMARY KEY'
)
loop
v_foreign_key := rx.foreign_table_schema||'.'||rx.foreign_table_name||'.'||rx.foreign_column_name;
v_subquery := 'select "'||rx.foreign_table_primary_key||'" as key from '||rx.foreign_table_schema||'."'||rx.foreign_table_name||'"
where "'||rx.foreign_column_name||'"in('||coalesce(p_keys, p_subquery)||') for update';
if p_foreign_keys @> ARRAY[v_foreign_key] then
--raise notice 'circular recursion detected';
else
p_foreign_keys := array_append(p_foreign_keys, v_foreign_key);
recnum:= recnum + delete_cascade(rx.foreign_table_schema, rx.foreign_table_name, null, v_subquery, p_foreign_keys);
p_foreign_keys := array_remove(p_foreign_keys, v_foreign_key);
end if;
end loop;
begin
if (coalesce(p_keys, p_subquery) <> '') then
v_sql := 'delete from '||p_schema||'."'||p_table||'" where "'||v_primary_key||'"in('||coalesce(p_keys, p_subquery)||')';
--raise notice '%',v_sql;
execute v_sql;
get diagnostics v_rows = row_count;
recnum := recnum + v_rows;
end if;
exception when others then recnum=0;
end;
return recnum;
end;
$$
language PLPGSQL;
の削除とカスケードオプションのみに適用されるテーブルは外部キー定義されています。う場合は削除でとはできませんので、することは外部キー制約は、カスケードの原因となりましを削除し違反されています。
を削除したい場合には、関連する行する必要がありますを定義する外部キーです。また、覚えていない限り、明示的に指導で開始のお取引は、変更したときのデフォルトでい自動コミットできる非常に時間がかかる。