Person
テーブルがあり、created_by
テーブル自体のプライマリIDを参照する列。したがって、別の従業員をデータベースに追加するのは従業員である可能性があります。正常に動作します。
ただし、People
は自分自身を追加することもできます(サインアップ)。したがって、created_by
列は、id
列の自動インクリメント値でなければなりません。しかし、その値は明らかに挿入後まで利用できません。
したがって、(a)値をチェックしないように参照を作成する、(b)最初にデフォルト値を追加する、または(c)列をNULL可能にすることができます。すべてのオプションが私には悪いようです。
MySQLの方言はこれを持っています:
SET FOREIGN_KEY_CHECKS = 0;
INSERT INTO EMPLOYEE VALUES('12345','67890'),('67890','12345');
SET FOREIGN_KEY_CHECKS = 1;
...しかし、SQL ServerのT-SQLに似たものを見つけることができませんでした。
主キーにIDを使用しているようです。主キーに柔軟性が必要な場合は、シーケンスを使用することをお勧めします。それはこのようなものになります。
CREATE SEQUENCE SQ_temp AS INT INCREMENT BY 1 START WITH 1
CREATE TABLE Users
( ID INT PRIMARY KEY DEFAULT NEXT VALUE FOR SQ_temp
, UserName VARCHAR(30)
, createdBy INT REFERENCES Users (ID)
)
INSERT INTO dbo.Users
(
ID
, UserName
, createdBy
)
VALUES
(NEXT VALUE FOR SQ_temp,'User1', NEXT VALUE FOR SQ_temp)
, (NEXT VALUE FOR SQ_temp,'User2', NEXT VALUE FOR SQ_temp)
, (NEXT VALUE FOR SQ_temp,'User3', NEXT VALUE FOR SQ_temp)
SELECT *
FROM dbo.Users AS u
自己参照エントリをSQLサーバーに挿入する
タイトルごとの一般的な質問については、次のような簡単な挿入で直接循環参照を追加できます
_INSERT node
(id , name , parent_id)
VALUES (123, 'Test', 123 )
_
すべての新しいデータを考慮して制約が適用されるためです。ステートメントが完了した後にFXが参照する値が存在する限り、すべて順調です。これは、リンクリストに複数の値を挿入するのと同じです。
_INSERT node
(id , name , parent_id)
VALUES (101, 'Test1', 100 )
, (102, 'Test2', 101 )
, (103, 'Test3', 102 )
_
または間接循環参照:
_INSERT node
(id , name , parent_id)
VALUES (201, 'Test5', 203 )
, (202, 'Test6', 201 )
, (203, 'Test7', 202 )
_
したがって、created_by列の値は、id列の自動インクリメントされた値である必要があります
挿入する前に生成されたものがわからないため、これは問題を引き起こします。実際、信頼できる方法で知ることはできません。個々の行を挿入する場合、SCOPE_IDENTITY()
を使用して新しい行をすぐに更新できます。
_INSERT node
(name )
VALUES ('Test')
-- and now make the circular reference
UPDATE node
SET parent_id = SCOPE_IDENTITY()
WHERE id = SCOPE_IDENTITY()
_
上記の例で、_parent_id
_が必須の列である場合(DEFAULT
なしで_NOT NULL
_と宣言されている)、ダミーの一時的な有効を指定する必要があります次のように、最初のINSERT
ステートメントから除外するのではなく、値:
_INSERT node
(name , parent_id)
VALUES ('Test', 0 )
-- and now make the circular reference
UPDATE node
SET parent_id = SCOPE_IDENTITY()
WHERE id = SCOPE_IDENTITY()
_
複数の行の挿入を処理する場合(説明する可能性は低いが、他の場所では一般的です)、OUTPUT
句を使用して、各行に作成されたIDを読み取り、さらに参照できます。現在の質問ではやり過ぎなので、ここでは説明しません。 https://docs.Microsoft.com/en-us/sql/t-sql/queries/output-clause-transact-)を参照してください。 sql 詳細については。
したがって、created_by列の値は、id列の自動インクリメントされた値である必要があります
2012年以降であれば、SQL ServerのSEQUENCE
を使用してこれを実行できることがわかります。これは、上記の複数ステートメントのオプションよりも優れたソリューションです。実際の例については、SQLing4everの回答を参照してください。 2012年より前はこの機能は利用できなかったため、SQL Serverの古いインスタンスをサポートする必要がある場合は、この回答のメソッドにフォールバックする必要があります。