SQL 非规范化数据的函数约束

SQL Function Constraint for Denormalized Data

如何为非规范化数据创建函数约束?

-- graduation_class table
graduation_class_id | graduation_year_id
123                         1    
456                         2

-- user table
user_id |   graduation_class_id |   graduation_year_id
555             123                     1
556             123                     3  <--- bad data
557             456                     2 

一个毕业class只能指定一个标志毕业年份。两者的结合在graduation_classtable.

中是独一无二的

我想在用户 table 的 graduation_year_id 列上创建函数约束,以确保 graduation_year_id 与 [=20= 中的正确 ID 同步] table这样用户table中的记录556就永远不会发生了。

** 请假设规范化不是解决此问题的方法,否则我不会问这个问题! :) **

像这样:

alter table user
drop column graduation_year_id

如果您需要它,select 加入 graduation_year table

而不是函数创建一个 composite primary key 和一个 foreign key 来解决你的问题

graduation_class中的graduation_class_id ,graduation_year_id设为复合primary key

ALTER TABLE graduation_class
ADD PRIMARY KEY (graduation_class_id ,graduation_year_id)

现在在用户table

中添加foreign key
ALTER TABLE user
ADD FOREIGN KEY (graduation_class_id ,graduation_year_id)
REFERENCES graduation_class(graduation_class_id ,graduation_year_id)

这将确保您只添加添加到 user 的行 table 已经存在于 graduation_class table

如其他答案所述,此架构并不理想,但如果您需要在有机会清理内容之前维护此架构中的数据完整性,函数约束将为您完成此操作。首先,我们将创建一个函数,将 graduation_class_idgraduation_year_id 作为参数,并且 return 是一个位值:

create function dbo.fn_check_graduation_year_id
    (
    @graduation_class_id int,
    @graduation_year_id int
    )
    returns bit
as
    begin
        declare @return bit = 1
        if @graduation_year_id != (select top 1 graduation_year_id
                                   from graduation_class
                                   where graduation_class_id = @graduation_class_id)
            set @return = 0
        return @return
    end

如果 graduation_year_id 与给定 graduation_class_id 值的 graduation_class table 上的值匹配,则此函数将 return 为真。接下来,我们将约束添加到您的 user table,确保检查函数的结果 returns 为真:

alter table [user] with nocheck add constraint ck_graduation_year_id
    check (dbo.fn_check_graduation_year_id(graduation_class_id,graduation_year_id) = 1)