首先是相关代码:
create table customer(
customer_mail_address varchar(255) not null,
subscription_start date not null,
subscription_end date, check (subscription_end !< subcription start)
constraint pk_customer primary key (customer_mail_address)
)
create table watchhistory(
customer_mail_address varchar(255) not null,
watch_date date not null,
constraint pk_watchhistory primary key (movie_id, customer_mail_address, watch_date)
)
alter table watchhistory
add constraint fk_watchhistory_ref_customer foreign key (customer_mail_address)
references customer (customer_mail_address)
on update cascade
on delete no action
go
所以我想使用UDF将watchhistory中的watch_date约束在customer中的subscription_start和subscription_end之间。我似乎无法弄清楚。
docs说(检查重点),检查约束无法针对其他表验证数据:
[ CONSTRAINT constraint_name ] { ... CHECK [ NOT FOR REPLICATION ] ( logical_expression ) }
逻辑表达式
是在CHECK约束中使用的逻辑表达式,并返回TRUE或假。与CHECK约束一起使用的逻辑表达式不能引用另一张表,但可以引用同一列中的其他列同一行的表格。表达式无法引用别名数据类型。
话虽如此,您可以创建一个用于验证日期的标量函数,然后在检查条件上使用该标量函数:
CREATE FUNCTION dbo.ufnValidateWatchDate (
@WatchDate DATE,
@CustomerMailAddress VARCHAR(255))
RETURNS BIT
AS
BEGIN
IF EXISTS (
SELECT
'supplied watch date is between subscription start and end'
FROM
customer AS C
WHERE
C.customer_mail_address = @CustomerMailAddress AND
@WatchDate BETWEEN C.subscription_start AND C.subscription_end)
BEGIN
RETURN 1
END
RETURN 0
END
现在添加您的检查约束,以确认该函数的结果为1:
ALTER TABLE watchhistory
ADD CONSTRAINT CHK_watchhistory_ValidWatchDate
CHECK (dbo.ufnValidateWatchDate(watch_date, customer_mail_address) = 1)
另一种替代方法是使用触发器,但我认为该功能更简单。