我有两个表,并添加了外键约束。海螺-效果很好。现在,是否可以针对父表中的某些数据进一步限制这种关系?
基本上,我在父表中有动物,而对于子表,希望仅包含父数据为.... um ..哺乳动物的数据。
例如。
Animals ^^^^^^^ AnimalId INT PK NOT NULL IDENTITY AnimalType TINYINT NOT NULL -- 1: Mammal, 2:Reptile, etc.. Name Mammals ^^^^^^^ AnimalId INT PK FK NOT NULL NumberOfMammaryGlads TINYINT NOT NULL
因此,我希望确保AnimalId只能是Animals.AnimalType = 1类型
这可能吗??
我不想让某人尝试在子表中插入一些针对爬行动物的信息…
我以为我必须使用检查约束(在下面的前两个答案中得到了确认-欢呼!),但是我不确定如何使用(例如sql语法来引用Animals表)。
亚历克斯有一个很好的帖子(如下),它对一些建议进行了基准测试……非常好的阅读!
我运行了一个小型基准测试-在这种情况下,使用UDF的方法运行速度几乎慢了100倍。
这是Sql代码…
-设置一个具有128K行的辅助表编号:
CREATE TABLE dbo.Numbers(n INT NOT NULL PRIMARY KEY) GO DECLARE @i INT; SET @i = 1; INSERT INTO dbo.Numbers(n) SELECT 1; WHILE @i<128000 BEGIN INSERT INTO dbo.Numbers(n) SELECT n + @i FROM dbo.Numbers; SET @i = @i * 2; END; GO
-桌子
CREATE TABLE dbo.Animals (AnimalId INT NOT NULL IDENTITY PRIMARY KEY, AnimalType TINYINT NOT NULL, -- 1: Mammal, 2:Reptile, etc.. Name VARCHAR(30)) GO ALTER TABLE dbo.Animals ADD CONSTRAINT UNQ_Animals UNIQUE(AnimalId, AnimalType) GO CREATE FUNCTION dbo.GetAnimalType(@AnimalId INT) RETURNS TINYINT AS BEGIN DECLARE @ret TINYINT; SELECT @ret = AnimalType FROM dbo.Animals WHERE AnimalId = @AnimalId; RETURN @ret; END GO CREATE TABLE dbo.Mammals (AnimalId INT NOT NULL PRIMARY KEY, SomeOtherStuff VARCHAR(10), CONSTRAINT Chk_AnimalType_Mammal CHECK(dbo.GetAnimalType(AnimalId)=1) ); GO
-–用UDF填充:
INSERT INTO dbo.Animals (AnimalType, Name) SELECT 1, 'some name' FROM dbo.Numbers; GO SET STATISTICS IO ON SET STATISTICS TIME ON GO INSERT INTO dbo.Mammals (AnimalId,SomeOtherStuff) SELECT n, 'some info' FROM dbo.Numbers;
结果是:
SQL Server parse and compile time: CPU time = 0 ms, elapsed time = 2 ms. Table 'Mammals'. Scan count 0, logical reads 272135, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. Table 'Numbers'. Scan count 1, logical reads 441, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. SQL Server Execution Times: CPU time = 7750 ms, elapsed time = 7830 ms. (131072 row(s) affected)
-用FK填充:
CREATE TABLE dbo.Mammals2 (AnimalId INT NOT NULL PRIMARY KEY, AnimalType TINYINT NOT NULL, SomeOtherStuff VARCHAR(10), CONSTRAINT Chk_Mammals2_AnimalType_Mammal CHECK(AnimalType=1), CONSTRAINT FK_Mammals_Animals FOREIGN KEY(AnimalId, AnimalType) REFERENCES dbo.Animals(AnimalId, AnimalType) ); INSERT INTO dbo.Mammals2 (AnimalId,AnimalType,SomeOtherStuff) SELECT n, 1, 'some info' FROM dbo.Numbers;
SQL Server parse and compile time: CPU time = 93 ms, elapsed time = 100 ms. Table 'Animals'. Scan count 1, logical reads 132, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. Table 'Mammals2'. Scan count 0, logical reads 275381, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. Table 'Numbers'. Scan count 1, logical reads 441, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. SQL Server Execution Times: CPU time = 375 ms, elapsed time = 383 ms.
-没有任何完整性地填充:
CREATE TABLE dbo.Mammals3 (AnimalId INT NOT NULL PRIMARY KEY, SomeOtherStuff VARCHAR(10) ); INSERT INTO dbo.Mammals3 (AnimalId,SomeOtherStuff) SELECT n, 'some info' FROM dbo.Numbers;
结果是: SQL Server解析和编译时间:CPU时间= 1毫秒,经过的时间= 1毫秒。
SQL Server Execution Times: CPU time = 0 ms, elapsed time = 66 ms. Table 'Mammals3'. Scan count 0, logical reads 272135, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. Table 'Numbers'. Scan count 1, logical reads 441, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. SQL Server Execution Times: CPU time = 297 ms, elapsed time = 303 ms. (131072 row(s) affected)
FK在CPU时间中的开销= 375 ms-297 ms = 78 ms UDF在CPU时间中的开销= 7750 ms-297 ms = 7453 ms