我有一个数据库,可以记录Microsoft SQL Server 2012 Express中奶牛的育种信息。显然,一头母牛出生后才能繁殖,并且在她的一生中可能多次繁殖;我需要在我的数据库中强制执行这些约束。我目前根据下图安排了一个架构:
DataID
是所有动物的主要钥匙。我试图实现Table-Per-Type继承,因此[Animals].[Master]
和[Animals].[Females]
之间的一对一关系。由于每个女性可能会多次繁殖,因此我在[Animals].[Females]
和[Breedings].[Breedings]
我的问题是:如何执行适用于所有女性的规则BirthDate
< Breedings.Date
吗
我基本上需要类似下面的psudocode(我实际上已将其置于CHECK约束的“表达式”框中并收到验证错误):
[Animals].[Master].[BirthDate] < [Breedings].[Breedings].[Date]
INNER JOIN [Animals].[Master] ON
[Breedings].[Breedings].[DataID] = [Animals].[Master].[DataID]
我也尝试使用正确的连接创建视图,但发现CHECK约束不能在视图中使用。
那么,有没有人知道如何强制执行这些约束?
编辑 - 我尝试了使用触发器的建议,但无法正确制定触发器语法。这是我的代码:
USE [CowInventory];
GO
CREATE TRIGGER [Breedings].[iCheckBreedingDateAfterBirthDate]
ON [Breedings].[Breedings]
FOR INSERT
AS
BEGIN
DECLARE @CowID UniqueIdentifier
SELECT @CowID = DataID FROM inserted;
DECLARE @CowBirthDate Date
SELECT @CowBirthDate = BirthDate FROM [Animals].[Master] WHERE [Master].[DataID] = @CowID
DECLARE @BreedingDate Date
SELECT @BreedingDate = Date FROM inserted;
IF(@CowBirthDate > @BreedingDate)
BEGIN
THROW;
END
END
根据我的一本书( SQL Server 2012 Step by Step ),这种语法应该完美无缺。但是,SQL Server在THROW
和最后END
下给了我粉红色的行,说明Incorrect syntax near 'THROW'. Expecting CONVERSATION, DIALOG, DISTRIBUTED, or TRANSACTION.
和Incorrect syntax near 'END'. Expecting CONVERSATION.
我插入了这些关键字,但它们没有任何改变。
答案 0 :(得分:3)
我不会使用触发器。使用检查约束。更清洁。请记住,检查约束可以调用函数。编写一个函数,在另一个表中进行检查。然后从检查约束中调用该函数。这是实现多表检查约束的最佳方法。
答案 1 :(得分:1)
您可以在Breedings表上创建触发器以检查此规则。触发器是一个特殊的存储过程,它在某些表上的INSERT \ UPDATE \ DELETE上自动执行。因此,您可以编写一个触发器来检查插入Breedings中的所有新行,如果有一行其中Date少于适当的BirthDate,则抛出错误。对于UPDATE也是如此,如果更改了Date列,请检查相应的动物的BirthDate并相应地抛出错误。 DELETE在这件事上是安全的。
对于涉及其他表的规则,CHECK不太好。一般建议是仅将它们用于一个表内的基本检查。
后期编辑
试试这个触发器主体
...
BEGIN
if exists
(
SELECT 1
FROM inserted i
join Animals.Females f
on i.DataID = f.DataID
join Animals.Master m
on f.DataID = m.DataID
WHERE
m.BirthDate > i.Date
)
RAISERROR("Trigger iCheckBreedingDateAfterBirthDate - Breedings.Date is wrong", 18, 0)
END
GO