SQL Server Check条件约束可以与其他数据表相关吗?

ua4mk5z4  于 2022-11-21  发布在  其他
关注(0)|答案(6)|浏览(199)

假设我有一个名为ProjectTimeSpan的数据表(我没有这个数据表,只是举例而已!),其中包含数据行StartDateEndDate
我还有另一个名为SubProjectTimeSpan的表,其中也包含名为StartDateEndDate的列,我想在其中设置一个 *Check约束 *,使StartDate和EndDate不能设置为ProjectTimeSpan.StartDateProjectTimeSpan.EndDate“之外”的值
一种检查约束,它 * 知道 * 关于 * 另一个 * 表的值...
这可能吗?

but5z9lq

but5z9lq1#

作为对您对GSerg答案的评论的回应,下面是一个使用函数的示例检查约束:

alter table YourTable
add constraint chk_CheckFunction
check (dbo.CheckFunction() = 1)

您可以在其中定义如下函数:

create function dbo.CheckFunction()
returns int
as begin
    return (select 1)
end

允许函数引用其他表。

niwlg2el

niwlg2el2#

您可以创建一个user-defined function来执行检查并返回1或0,然后在其上创建一个check约束,并提供项目ID和日期作为参数。

8yoxcaq7

8yoxcaq73#

ProjectTimeSpan表的键与StartDateEndDate列组合成一个复合键,然后将此复合键用于SubProjectTimeSpan表中的外键引用。这样给予您就可以在SubProjectTimeSpan表中写入必要的行级CHECK约束条件,例如:

CREATE TABLE ProjectTimeSpan 
(
 project_ID INTEGER NOT NULL UNIQUE, -- key
 StartDate DATE NOT NULL, 
 EndDate DATE NOT NULL, 
 CHECK (StartDate < EndDate), 
 UNIQUE (project_ID, StartDate, EndDate) -- compound key
 -- other project columns here...
);

CREATE TABLE SubProjectTimeSpan 
(
 project_ID INTEGER NOT NULL, 
 StartDate DATE NOT NULL, 
 EndDate DATE NOT NULL, 
 FOREIGN KEY (project_ID, StartDate, EndDate)
    REFERENCES ProjectTimeSpan (project_ID, StartDate, EndDate)
    ON DELETE CASCADE
    ON UPDATE CASCADE, 
 sub_StartDate DATE NOT NULL, 
 sub_EndDate DATE NOT NULL, 
 CHECK (sub_StartDate < sub_EndDate),
 CHECK (StartDate <= sub_StartDate), -- sub project can't start before main project
 CHECK (sub_EndDate <= EndDate)      -- sub project can't end after main project
 -- other sub project columns here...
);
2eafrhcq

2eafrhcq4#

您当然 * 可以 * 做到这一点,正如许多答案所显示的那样。但是,您应该知道,SQL Server在使用UDF的CHECK CONSTRAINT方面似乎有问题:
https://dba.stackexchange.com/questions/12779/how-are-my-sql-server-constraints-being-bypassed

kknvjkwl

kknvjkwl5#

您需要在父表和子表上添加约束,因为子项目不能超出项目范围,但项目范围也不能移出所有子项目。
在这种情况下,您应该推迟对事务的上层(Web服务、应用程序)的约束检查,以确保在对两个表进行多次查询后,您的数据处于有效状态!

ljo96ir5

ljo96ir56#

这是绝对可能的,而且实际上非常简单。就像你的例子:

create or alter function dbo.Check_SubProjectTimeSpan_ProjectTimeSpan_Dates(
    @ProjectTimeSpanId int
  , @StartDate         date
  , @EndDate           date
)
returns bit
as
begin

if exists (select *
             from dbo.ProjectTimeSpan as pts
            where pts.Id        =  @ProjectTimeSpanId
              and pts.StartDate >= @StartDate
              and pts.EndDate   <= @EndDate)
begin
    return 1
end

return 0

end
go

alter table dbo.SubProjectTimeSpan add constraint
CK_SubProjectTimeSpan_ProjectTimeSpan_ProjectTimeSpanId_StartDate_EndDate
check (
    dbo.Check_SubProjectTimeSpan_ProjectTimeSpan_Dates(
        ProjectTimeSpanId, StartDate, EndDate) = 1
)

但请注意,这不会有特别好的表现。

相关问题