web-dev-qa-db-ja.com

データの挿入は外部キー制約に違反しています

以下のフィールドを持つ2つのテーブルEmployeeDepartmentがあるとします。

従業員:

Fname、Minit、Lname、SsnBdate、Address、Sex、Salary、Super_ssn、Dno

部門:

DnameDnumber、 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_ssndepartmentに挿入するには、それがEmployeeに存在し、dnoinEmployeeそれはDepartmentに存在する必要があります。ただし、スキーマをそのまま維持してテーブルを埋める必要があります。この循環参照を解決するにはどうすればよいですか?ありがとう。

6
Pant

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 ;
5
ypercubeᵀᴹ

この状況を説明する古い記事があり、これは循環参照と呼ばれます。 2つのテーブルに行を挿入または削除すると、「鶏と卵」の問題が発生します。制約に違反することなく、どのテーブルを最初に挿入する必要がありますか?以下のこの記事を読んで、それが役立つかどうかを確認することをお勧めします。

SQL By Design:循環参照

1
James Rhoat