SQL - 如何使用用户定义的函数来约束 2 个表之间的值
Posted
技术标签:
【中文标题】SQL - 如何使用用户定义的函数来约束 2 个表之间的值【英文标题】:SQL - How do you use a user defined function to constrain a value between 2 tables 【发布时间】:2019-11-19 12:52:24 【问题描述】:首先是相关代码:
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 限制在 subscription_start 和 subscription_end 之间客户。我好像搞不懂。
【问题讨论】:
请添加您正在使用的rdms。例如,在 Oracle 上,您不能使用引用另一个表的检查约束:“检查约束的条件可以引用表中的任何列,但不能引用其他表的列。” 您使用的是哪个DBMS 产品? “SQL”只是一种查询语言,而不是特定数据库产品的名称(!<
不是有效的 SQL 运算符)。请为您正在使用的数据库产品添加tag
我正在使用 Microsoft SQL Server Management Studio
Can a Check constraint relate to another table?的可能重复
虽然您可以绕道而行,但更好的问题是您认为应该这样做的原因。 “历史”这个名称表明该表并不是您模型的真正组成部分,而是用于捕获不断变化的信息(可能用于审计或取证目的)。
【参考方案1】:
检查约束无法根据其他表验证数据,docs 说(强调我的):
[ CONSTRAINT constraint_name ] ... CHECK [ NOT FOR REPLICATION ] ( logical_expression )
逻辑表达式
是用于 CHECK 约束的逻辑表达式,返回 TRUE 或 错误的。与 CHECK 约束一起使用的logical_expression 不能 引用另一个表,但可以引用同一个表中的其他列 同一行的表。表达式不能引用别名数据 输入。
话虽如此,您可以创建一个标量函数来验证您的日期,并在检查条件上使用该标量函数:
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)
这不是指向另一个表的直接链接,而是您可以用来验证日期的解决方法。请记住,如果您在观察日期插入之后更新customer
日期,日期将不一致。在这种情况下,确保完全一致的唯一方法是使用几个触发器。
【讨论】:
以上是关于SQL - 如何使用用户定义的函数来约束 2 个表之间的值的主要内容,如果未能解决你的问题,请参考以下文章