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

时间:2015-02-02 17:27:46

标签: sql sql-server sql-function

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

-- 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 

毕业班只能分配到毕业年份。这两者的组合在gradu_class表中是唯一的。

我想在user表的gradu_year_id列上创建一个函数约束,以确保gradu_year_id与gradu_class表中的正确id同步,以便用户表中的记录556永远不会发生。

**请假设标准化不是解决方案,或者我不会问这个问题! :) **

3 个答案:

答案 0 :(得分:1)

而不是功能创建composite primary keyforeign key来解决您的问题

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

ALTER TABLE graduation_class
ADD PRIMARY KEY (graduation_class_id ,graduation_year_id)

现在在用户表

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

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

答案 1 :(得分:1)

正如其他答案所提到的,这种模式并不理想,但如果您需要在有机会清理之前在此模式中维护数据完整性,则函数约束将为您执行此操作。首先,我们将创建一个函数,该函数将graduation_class_idgraduation_year_id作为参数,并返回一个位值:

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值的graduation_class_id表上的值匹配,则此函数将返回true。接下来,我们将约束添加到您的user表中,确保check函数的结果返回true:

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)

答案 2 :(得分:0)

像这样:

alter table user
drop column graduation_year_id

如果您需要,请通过加入gradu_year表

来选择它