SQL-如何使用用户定义的函数在2个表之间限制值

问题描述 投票:1回答:1

首先是相关代码:

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_startsubscription_end之间。我似乎无法弄清楚。

sql sql-server constraints user-defined-functions
1个回答
0
投票

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)

另一种替代方法是使用触发器,但我认为该功能更简单。

© www.soinside.com 2019 - 2024. All rights reserved.