使用带空值的默认约束?

时间:2016-11-11 00:41:57

标签: sql

如果即将到来的值是NULL,有没有办法插入默认值,这是我的约束:

ALter table Student
add Constraint DF_Name Default 'NOTAVAILABLE' For [Name]

当我运行时:

Insert into Student (Name,ClassId)values (NULL,1)

它仍会插入NULL而不是默认值。

2 个答案:

答案 0 :(得分:4)

如果我理解你,你想要这个:

INSERT INTO Student ( Foo, Bar, Name ) VALUES ( 'Baz', 'Qux', NULL )

实际执行此操作:

INSERT INTO Student ( Foo, Bar, Name ) VALUES ( 'Baz', 'Qux', 'NOTAVAILABLE' )

(请注意,我认为这是一个坏主意,因为NULL旨在表示“NOTAVAILABLE”值 - 您应该避免使用带内值来表示错误条件 - 尤其是避免使用字符串/文本值来表示状态值)

(这也是一个坏主意,因为检查"NOTAVAILABILE"比检查NULL值要贵得多 - 你的表和索引将占用更多空间并需要更长的时间来搜索和扫描)

但如果你真的想这样做......

CREATE TRIGGER OnInsertOverrideNameIfNull ON Student INSTEAD OF INSERT AS

    INSERT INTO Student ( Foo, Bar, Name )
    SELECT Foo, Bar, ISNULL( [Name], 'NOTAVAILABLE' ) FROM [inserted]

END

答案 1 :(得分:1)

我没有意识到在没有某种形式的解决方法的情况下显式插入null时应用默认值的方法。解决方法是:

使用触发器

(@ Dai的解决方案在这里更好;但是提供这个备用选项,因为这会使用你的DEFAULT约束。你是否宁愿在你的触发器逻辑中编写默认值,或者保持它作为约束是一种实现选择;它在功能上几乎没有区别。

create trigger trg_student_insert
on Student
instead of insert
as
begin

    insert into Student (Name, ClassId) 
    select i.name, i.ClassId
    from inserted i
    where name is not null

    insert into Student (ClassId) 
    select i.ClassId
    from inserted i
    where name is null

end

使用存储过程

与触发方法类似;再次,您可以选择在@name参数为null时从插入中遗漏名称字段,或者将默认值编码到存储过程中(这次我完成后者,为了变化)。登记/> 同样,您可以在insert语句中使用coalesce(@name,'NotAvailable')作为将值编码到过程中的替代形式。如果您的陈述简单如下,那可能会更清晰;但是如果你在存储过程中做了更多的事情,你可能希望尽早处理所有的违约行为。

注意:这不会直接影响到表的插入(即存储的proc比触发器更容易被绕过),但如果你的应用程序总是使用存储过程与数据库交互,那么这就是更干净方法

create procedure sp_StudentCRUD_Insert
(
    @name nvarchar(32) = null
    , @classId int
)
as
begin

    set nocount on

    if (@name is null) set @name = 'NotAvailable' 

    insert into Student (name, classId)
    values (@name, @classId)

    select scope_identity()

end

这将被称为如下:

  • exec sp_StudentCRUD_Insert @name='Mohamed', @classId = 1
  • exec sp_StudentCRUD_Insert @name=null, @classId = 2
  • exec sp_StudentCRUD_Insert @name=default, @classId = 3
  • exec sp_StudentCRUD_Insert @classId = 4

最后3个与使用@name的默认值具有相同的效果。

与所有事情一样,背景将推动哪种方法最有意义。