Ho due tavoli, vendita e prodotto. La vendita ha un vincolo di chiave esterna che fa riferimento al prodotto. La chiave esterna è stata creata WITH NOCHECK
e immediatamente disabilitata dopo la creazione. Voglio abilitare e fidarmi del vincolo di chiave esterna. Abilitarlo funziona ma non riesco a farci affidamento.Come rendere affidabili i vincoli di chiave esterna?
domande simili su StackOverflow e vari blog indicano che l'esecuzione ALTER TABLE T WITH CHECK CHECK CONSTRAINT C
dovrebbe tradursi in is_disabled=0
e is_not_trusted=0
, ma is_not_trusted
è sempre 1 per me. Che cosa sto facendo di sbagliato?
ho provato a mettere il codice di esempio su SQL Fiddle ma non piaceva i comandi "DBCC", ecco che è:
-- "_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.
Louie, grazie per aver dedicato del tempo per fare i test, questa è un'ottima risposta, vorrei poterti dare più di un upvote :) Stavo cercando di ottenere i vincoli attendibili perché ho letto da qualche parte quelli non fidati può influire sul rendimento di alcune query. Ho ereditato il database e non lo replichiamo, ma tutto sembra essere "NOT FOR REPLICATION", che potrebbe essere un caso di "generalità speculativa". – WileCau
@WileCau In realtà si ottiene un miglioramento nel tempo di esecuzione quando gli FK sono contrassegnati come non attendibili. Non sto affatto incoraggiando questa pratica. Tuttavia, è molto utile lo spostamento di grandi quantità di dati, ad esempio da staging sql a production sql. controlla qui per maggiori informazioni http://sqlblog.com/blogs/hugo_kornelis/archive/2007/03/29/can-you-trust-your-constraints.aspx – harsimranb
@ Pathachiever11, hai ragione, il motivo per cui i vincoli sono stati disabilitati era perché alcune tabelle erano inizialmente popolate da un altro database coerente noto in modo da rallentare la migrazione dei dati. Dopo la migrazione iniziale, i vincoli avrebbero dovuto essere riabilitati per applicare la coerenza sui nuovi dati, ma sono stati dimenticati. – WileCau