以下のフィールドを持つ2つのテーブルEmployee
とDepartment
があるとします。
従業員:
Fname、Minit、Lname、Ssn
Bdate、Address、Sex、Salary、Super_ssn、Dno
部門:
Dname
、Dnumber
、 Mgr_ssn、Mgr_start_date
Italics and code block
は、テーブルの主キーを表します。
上記の場合、Super_Ssnは従業員の[〜#〜] ssn [〜#〜]を参照しますが、Dnoは、部門のDnumberを参照します。それらのSQLを作成することは、最初に列を追加し、両方のテーブルが形成されたときに後で変更することにより、非常に簡単です。ただし、次のようなデータを挿入する場合:
insert into employee values('James','E','Borg','888665555','1937-11-10','asda','M',55000,NULL,1);
ERROR: insert or update on table "employee" violates foreign key constraint "dno_ref_dnum_dpt"
DETAIL: Key (dno)=(1) is not present in table "department".
そして
insert into sp0090.department values ('Headquarter',1,'888665555','1981-06-19');
ERROR: insert or update on table "department" violates foreign key constraint "department_mgr_ssn_fkey"
DETAIL: Key (mgr_ssn)=(888665555) is not present in table "employee".
外部キーの制約に違反しています。 Mgr_ssnをdepartmentに挿入するには、それがEmployeeに存在し、dnoinEmployeeそれはDepartmentに存在する必要があります。ただし、スキーマをそのまま維持してテーブルを埋める必要があります。この循環参照を解決するにはどうすればよいですか?ありがとう。
Postgresでは、循環参照のあるテーブルに挿入する鶏と卵の問題を回避する方法が2つあります。
a)制約の1つを据え置き、作成時にDEFERRABLE INITIALLY DEFERRED
として、または作成時にDEFERRABLE
として宣言し、必要に応じて据え置きます。
遅延可能な制約の使用例については、この質問の私の回答を参照してください:
SQLでの総参加制約による多対多の関係の実装。
b)単一のステートメントを使用して、CTEを変更し、2つ(またはそれ以上)のテーブルに挿入します。あなたのケースの例:
with
insert_emp as
( insert into employee
(Fname, Minit, Lname, Ssn, Bdate, Address, Sex, Salary, Super_ssn, Dno)
values
('James', 'E', 'Borg', '888665555', '1937-11-10', 'asda', 'M', 55000, NULL, 1)
returning
*
),
insert_dep
( insert into sp0090.department
(Dname, Dnumber, Mgr_ssn, Mgr_start_date)
values
('Headquarter', 1, '888665555', '1981-06-19')
returning
*
)
select *
from insert_emp as e
full join insert_dep as d
on e.dno = d.dnumber
and e.ssn = d.mgr_ssn ;
この状況を説明する古い記事があり、これは循環参照と呼ばれます。 2つのテーブルに行を挿入または削除すると、「鶏と卵」の問題が発生します。制約に違反することなく、どのテーブルを最初に挿入する必要がありますか?以下のこの記事を読んで、それが役立つかどうかを確認することをお勧めします。