9

Sale と Product の 2 つのテーブルがあります。Sale には Product を参照する外部キー制約があります。外部キーが作成されWITH NOCHECK、作成後すぐに無効になりました。外部キー制約を有効にして信頼したい。有効にすると機能しますが、信頼することはできません。

StackOverflow とさまざまなブログに関する同様の質問は、実行すると とになるALTER TABLE T WITH CHECK CHECK CONSTRAINT Cはずですが、私にとっては常に 1 です。私は何を間違っていますか?is_disabled=0is_not_trusted=0is_not_trusted

SQL Fiddle にサンプル コードを載せようとしましたが、"DBCC" コマンドが気に入らなかったので、以下に示します。

-- "_Scratch" is just a sandbox DB that I use for testing stuff.
USE _Scratch

CREATE TABLE dbo.Product
(
  ProductKeyId INT PRIMARY KEY NOT NULL,
  Description VARCHAR(40) NOT NULL
)

CREATE TABLE dbo.Sale
(
  ProductKeyId INT NOT NULL,
  SaleTime DATETIME NOT NULL,
  Value MONEY NOT NULL
)

ALTER TABLE dbo.Sale WITH NOCHECK
  ADD CONSTRAINT FK_Product_ProductKeyId FOREIGN KEY (ProductKeyId)
  REFERENCES dbo.Product (ProductKeyId) NOT FOR REPLICATION;

ALTER TABLE dbo.Sale NOCHECK CONSTRAINT FK_Product_ProductKeyId

INSERT INTO dbo.Product VALUES (1, 'Food')
INSERT INTO dbo.Sale VALUES (1, GETDATE(), 1.00)

-- Check the disabled/trusted state
SELECT name, is_disabled, is_not_trusted
FROM sys.foreign_keys
WHERE name = 'FK_Product_ProductKeyId'

  -- name                     is_disabled  is_not_trusted
  -- FK_Product_ProductKeyId  1            1

-- Check the FK_Product_ProductKeyId constraint
DBCC CHECKCONSTRAINTS('FK_Product_ProductKeyId')

  -- DBCC execution completed.
  -- If DBCC printed error messages, contact your system administrator.

-- Check all constraints on Sale table
DBCC CHECKCONSTRAINTS('Sale')

  -- DBCC execution completed.
  -- If DBCC printed error messages, contact your system administrator.

-- Add the constraint and check existing data
ALTER TABLE Sale WITH CHECK CHECK CONSTRAINT FK_Product_ProductKeyId

-- Check the disabled/trusted state
SELECT name, is_disabled, is_not_trusted
FROM sys.foreign_keys
WHERE name = 'FK_Product_ProductKeyId'

  -- name                     is_disabled  is_not_trusted
  -- FK_Product_ProductKeyId  0            1

-- Check the FK_Product_ProductKeyId constraint
DBCC CHECKCONSTRAINTS('FK_Product_ProductKeyId')

  -- DBCC execution completed.
  -- If DBCC printed error messages, contact your system administrator.

-- Check all constraints on Sale table
DBCC CHECKCONSTRAINTS('Sale')

  -- DBCC execution completed.
  -- If DBCC printed error messages, contact your system administrator.
4

1 に答える 1

18

あなたの例に基づいて、私も試しました:

  • 外部キーを削除して再作成します。
  • テーブルを削除して再作成します。

次に、コマンドで次のことに気付きました。

NOT FOR REPLICATION

NOT FOR REPLICATION で制約が作成された場合、常に信頼されないようです。

Books Onlineからの引用:

場合によっては、レプリケーション トポロジでのユーザー アクティビティをエージェント アクティビティとは異なる方法で処理することが望ましい場合があります。たとえば、パブリッシャーでユーザーによって行が挿入され、その挿入がテーブルのチェック制約を満たす場合、サブスクライバーでレプリケーション エージェントによって行が挿入されるときに、同じ制約を適用する必要がない場合があります。NOT FOR REPLICATION オプションを使用すると、レプリケーション エージェントが操作を実行するときに、次のデータベース オブジェクトが異なる方法で処理されるように指定できます。

外部キー制約

レプリケーション エージェントが挿入、更新、または削除操作を実行する場合、外部キー制約は適用されません。

このIS_NOT_TRUSTED設定は、 の影響を受けるレプリケーションにのみ関連してIS_NOT_FOR_REPLICATIONいるようです。作業しているサーバーに制約が適用されている限り、問題ないはずです。だから私は先に進み、それを確認しました:

SELECT name, is_disabled, is_not_trusted
FROM sys.foreign_keys
WHERE name = 'FK_Product_ProductKeyId'

name                    is_disabled is_not_trusted
FK_Product_ProductKeyId 0            1

INSERT INTO dbo.Sale VALUES (2, GETDATE(), 1.00)

Msg 547, Level 16, State 0, Line 1
The INSERT statement conflicted with the FOREIGN KEY constraint "FK_Product_ProductKeyId". The conflict occurred in database "_Scratch", table "dbo.Product", column 'ProductKeyId'.
The statement has been terminated.

IS_NOT_TRUSTED = 0それでも安心して見たい場合は、外部キーを .xml なしで再作成してくださいNOT FOR REPLICATION

疑問に思っている方のために、CHECK 制約に対しても同じ効果があることを確認しました。

于 2013-05-01T06:26:20.990 に答える