ここでわかるように、OrderInfo
とOrderNumber
には関係セットがあります。しかし、私はどんな種類かわかりません。 関係を設定することを望んでいたので、OrderNumber
を削除すると、OrderInfo
内の対応するレコードがカスケード削除されますが、許可されません。それは私にこの厄介なを与える '
iD列で削除をカスケードできません
エラーなので、カスケード削除を削除した後、適切に保存しました。キーとキーの意味がわかりませんが、無限へのキーは1対多であると知っていますか?
モデルはOrderNumber
とOrderInfo
の間の1対1の関係であるように見えます。OrderInfo.OrderID
はOrderInfo
主キーおよび外部キー参照としてOrderNumber.OrderID
。
エラーメッセージは、OrderInfo.OrderID
をIDENTITY
列として定義したことを示しています。 IDENTITY
であってはなりません。関連するOrderID
行を挿入するときに、関連するOrderNumber
行から割り当てられたOrderInfo
値を使用して、外部キーの関係を維持する必要があります。これにより、DELETE CASCADE
を指定できるようになります。
OrderInfo.OrderID
をOrderNumber.OrderID
を参照する外部キーにしたい場合は、INTEGER IDENTITY
ではなくINTEGER
として宣言する必要があります。 IDの場合、OrderID
への挿入後に取得した対応するOrderNumber
の実際の値をそれに割り当てることができませんでした。
つまり、次のようにテーブルを宣言する必要があります。
CREATE TABLE Customer
(
CustomerID integer IDENTITY(1,1) PRIMARY KEY,
FirstName varchar(100),
LastName varchar(100)
) ;
CREATE TABLE Consultants
(
ConsultantID integer IDENTITY(1,1) PRIMARY KEY,
EmployeeID integer /* REFERENCES Employees(EmployeeID) */
) ;
CREATE TABLE OrderNumber
(
OrderID integer IDENTITY(1,1) PRIMARY KEY,
CustomerID integer REFERENCES Customer(CustomerID) ON DELETE NO ACTION, /* Referenced CustomerID cannot be deleted */
ConsultantID integer REFERENCES Consultants(ConsultantID) ON DELETE NO ACTION /* Referenced ConsultantID cannot be deleted */
) ;
CREATE TABLE OrderInfo
(
OrderID integer NOT NULL REFERENCES OrderNumber(OrderID) ON DELETE CASCADE,
/* My assumption: one order can have several items
If that were not the case, the following column could be ommitted.
Otherwise, just put all the [OrderInfo] columns in [OrderNumber] table,
and just call it [Order].
*/
SomeOtherColumnSuchAsLineNumber integer NOT NULL,
/* The actual PK should be a composite */
PRIMARY KEY (OrderID, SomeOtherColumnSuchAsLineNumber),
/* Rest of columns */
Cost decimal(12,2),
Description varchar(max)
) ;
-- etc.
顧客、コンサルタント、および2つの注文を挿入し、それぞれ2つのOrderInfoを使用します(注文には複数のアイテムが含まれると想定し、それらを並べ替えるために追加の列を追加しました)。
INSERT INTO Customer(FirstName, LastName)
OUTPUT inserted.CustomerID
VALUES('John', 'Doe') ;
GO
| CustomerID | | ---------:| | 1 |
INSERT INTO Consultants(EmployeeID)
OUTPUT inserted.ConsultantID
VALUES (1), (2);
GO
| ConsultantID | | -----------:| | 1 | | 2 |
INSERT INTO OrderNumber(CustomerID, ConsultantID)
OUTPUT inserted.OrderID
VALUES (1,1), (1,2) ;
GO
| OrderID | | ------:| | 1 | | 2 |
INSERT INTO OrderInfo
(OrderID, SomeOtherColumnSuchAsLineNumber, Cost, Description)
VALUES
(1, 1, 100.00, 'Item costing 100.00'),
(1, 2, 99.99, 'Item costing 99.99'),
(2, 1, 200.00, 'Item costing 200.00'),
(2, 2, 199.99, 'Item costing 199.99') ;
GO
4行が影響を受けました
この時点で、OrderInfo
にfor行がある場合:
SELECT
* -- Don't do this in production, just in demo
FROM
OrderInfo
ORDER BY
OrderInfo.OrderID, OrderInfo.SomeOtherColumnSuchAsLineNumber ;
GO
OrderID | SomeOtherColumnSuchAsLineNumber |コスト|説明 ------:| ------------------------------:| :-- :------------------ 1 | 1 | 100.00 |アイテムの価格は100.00 1 | 2 | 99.99 |アイテムの価格99.99 2 | 1 | 200.00 |アイテムの価格は200.00 2 | 2 | 199.99 | 199.99円のアイテム
OrderNumber
から1行削除すると、変更はOrderInfo
に反映されます
DELETE FROM
OrderNumber
WHERE
OrderID = 2;
GO
1行が影響を受けました
-- We deleted from OrderNumber OrderID = 2, it won't appear here
SELECT
* -- Don't do this in production, just in demo
FROM
OrderInfo
ORDER BY
OrderInfo.OrderID, OrderInfo.SomeOtherColumnSuchAsLineNumber ;
GO
OrderID | SomeOtherColumnSuchAsLineNumber |コスト|説明 ------:| ------------------------------:| :----- | :------------------ 1 | 1 | 100.00 |アイテムの価格は100.00 1 | 2 | 99.99 |アイテムの価格は99.99
dbfiddleですべてを確認できます---(ここ
このエラーを回避する方法について心配する前に、おそらくこれは技術的な問題ではなく、論理的な問題であると考えてください。データモデルを見て、なぜ最初にOrderInfo
とOrderNumber
を分割しているのか疑問に思います。それらが本当に1対1である場合、それらを分割することによって何が得られますか? Cost
とDescription
がなく、これらの2つの列にNULL
sが含まれないように正規化している場合がありますか?すでに表示されているよりも多くのフィールドがないと仮定します– OrderID
、ConsultantID
、CustomerID
、OrderInfo
、およびOrderNumber
–次に、最も可能性が高い(つまり、全体的な要件についての詳細がわからない場合)これらのフィールドを単一のOrderInfo
に統合する方がはるかに良いでしょうテーブル、およびそれらのフィールドの1つ以上がNULL
を受け入れる必要がある場合は、そのようにします。
もちろん、論理エンティティを複数のテーブルに分割するのに有効な状況があります(例については、次のDBA.SEの質問に対する私の回答を参照してください: SQL Server 2014圧縮と最大行サイズ )。ただし、この状況は(今のところ)それらの1つではないようです。
コメントで、1対1の関係である他の同様の場所があると述べました
それらの両方が同じ列と同じ名前で
そして、どちらがIDENTITY
を持っているべきで、どれが持っていないべきかを決定する方法を疑問に思っていました。これは、これらのテーブルに戻って確認し、本当に分離する必要があるのか、それとも統合する必要があるのかを検討する良い機会だと思います。本当に別のテーブルとして保持する必要がある場合、関連するテーブルのセットがすべて同じ論理エンティティのプロパティである場合、1つだけ(メインテーブルまたはプライマリテーブルと見なされる方)にIDENTITY
(これは上記の私のリンクされた回答に示されているものです)。しかし、それらが別個のエンティティーである場合、それらはcanそれぞれに独自のIDENTITY
があります。
関連するメモで、Department
テーブルのPKがEmployeeID
であるのは奇妙です。代わりにDepartmentID
にする必要がありますか?
異なるテーブルの2つの同一の主キーをリンクすることに問題はありませんが、データ型がIDとして宣言されている場合に問題が発生します。
一部のフィールドをIDとして宣言すると、値は自動的にインクリメントされ、提供されている場合はシードによって決定されます。値が同期している場合でも、Danによって指摘されているように、SQLサーバーではこれを続行できません。
INTを使用すれば問題ありません。