如果即将到来的值是NULL
,有没有办法插入默认值,这是我的约束:
ALter table Student
add Constraint DF_Name Default 'NOTAVAILABLE' For [Name]
当我运行时:
Insert into Student (Name,ClassId)values (NULL,1)
它仍会插入NULL
而不是默认值。
答案 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的默认值具有相同的效果。
与所有事情一样,背景将推动哪种方法最有意义。