在我的sql-server 2008数据库的触发器中,我需要检查一个变量是否为空。这段代码可以满足我的需要,但可以用更少的行来完成,更具可读性吗?
DECLARE @string varchar
DECLARE @float float
DECLARE @bit bit
DECLARE @int int
Set @string=NULL -- Exactly one of these variables needs to be set
Set @float=NULL --
Set @bit=NULL --
Set @int=NULL --
IF( (@string is not null AND COALESCE(@float, @bit, @int) IS NULL)
OR (@float is not null AND COALESCE(@string, @bit, @int) IS NULL)
OR (@bit is not null AND COALESCE(@string, @float, @int) IS NULL)
OR (@int is not null AND COALESCE(@string, @float, @bit) IS NULL)
)
print ' ok'
ELSE
print ' not ok'
答案 0 :(得分:4)
SELECT CASE WHEN COUNT(c) =1 THEN 'Y' ELSE 'N' END
FROM
(VALUES (CAST(@string AS SQL_VARIANT)),(@float),(@bit),(@int)) T (c)
答案 1 :(得分:2)
我不一定确定它更具可读性(虽然我猜你是否将它抽象为可能的函数)但是
if((case when @string is null then 0 else 1 end +
case when @float is null then 0 else 1 end +
case when @bit is null then 0 else 1 end +
case when @int is null then 0 else 1 end) = 1)
....
更灵活一点?
答案 2 :(得分:2)
我想我知道你正在创建的设置类型。在这种情况下,我通常将数据结构定义为:
CREATE TABLE DataItems (
DataItemID int IDENTITY(1,1) not null,
Name varchar(10) not null,
TypeRequired varchar(6) not null,
constraint PK_DataItems PRIMARY KEY (DataItemID),
constraint CK_TypeRequired CHECK (TypeRequired in ('STRING','FLOAT','BIT','INT'),
constraint UQ_DataItems_TypeCheck UNIQUE (DataItemID,TypeRequired)
)
请注意,我已将DataItemID,TypeRequired
设为超级密钥,因此我可以在外键约束中引用它。
现在,在收集数据的表格中:
CREATE TABLE Answers (
AnswerID int IDENTITY(1,1) not null,
/* Other columns to FK to e.g. Client, Users, Session, whatever */
DataItemID int not null,
Type varchar(6) not null,
StringValue varchar(max) null,
FloatValue float null,
BitValue bit null,
IntValue int null,
constraint PK_Answers PRIMARY KEY (AnswerID),
constraint FK_Answers_DataItems FOREIGN KEY (DataItemID) references DataItems (DataItemID),
constraint FK_Answers_DataItems_TypeCheck FOREIGN KEY (DataItemID,Type) references DataItems (DataItemID,TypeRequired),
constraint CK_Answers_TypeCheck CHECK (
(FloatValue is null or TypeRequired = 'FLOAT') and
(StringValue is null or TypeRequired = 'STRING') and
(BitValue is null or TypeRequired = 'BIT') and
(IntValue is null or TypeRequired = 'INT')),
constraint CK_Answers_NotNUll CHECK (
FloatValue is not null or StringValue is not null or BitValue is not null or IntValue is not null)
)
第二个外键约束确保类型列与数据项的已定义类型匹配,并且检查约束对确保只有一列(和右列)不为空。
如果您需要隐藏用户的“类型”列,那么我建议重命名上表(例如_Answers
)创建带有插入触发器的视图:
CREATE VIEW Answers
WITH SCHEMABINDING
AS
SELECT
AnswerID,
DataItemID,
StringValue,
FloatValue,
BitValue,
IntValue
FROM
dbo._Answers
CREATE TRIGGER T_Answers_I
ON Answers
INSTEAD OF INSERT
AS
INSERT INTO _Answers (DataItemID,Type,StringValue,FloatValue,BitValue,IntValue)
SELECT i.DataItemID,di.Type,i.StringValue,i.FloatValue,i.BitValue,i.IntValue
FROM inserted i inner join DataItems di on i.DataItemID = di.DataItemID
答案 3 :(得分:1)
我找到了另一种解决方案,但它不是更少的线路。它使用按位XOR运算符。我不确定我是否喜欢它 - 但它确实意味着每个变量只被检查一次而不是每行,所以它可能满足你的可读性要求:
DECLARE @string varchar
DECLARE @float float
DECLARE @bit bit
DECLARE @int int
SET @string=NULL -- Exactly one of these variables needs to be set
SET @float=NULL --
SET @bit=NULL --
SET @int=NULL --
if ((case when @string is null then 1 else 0 end)
^ (case when @float is null then 1 else 0 end)
^ (case when @bit is null then 1 else 0 end)
^ (case when @int is null then 1 else 0 end)) = 1
print 'ok'
else
print 'not ok'
评论?批评?还不确定CASE
语句的效率如何。
答案 4 :(得分:1)
我以为我很聪明,但只有4个变量中没有一个能够具有完全相同的值时才会有效,所以在很多情况下它都没用。无论如何我会发布它:
IF(
(COALESCE(@string,@float, @bit, @int) IS NULL)
OR (COALESCE(@string, @float, @bit, @int) != COALESCE(@int, @bit, @float, @string))
)
print 'not ok'
ELSE print 'ok'
COALESCE从左到右逐渐消失直到它达到NOT NULL值,所以如果你反转顺序,如果你有多个var,你会得到不同的结果。 set(除非varibles可以同时具有相同的值)
答案 5 :(得分:1)
我们不能通过这个检查:
IF ISNULL(@string, '') <> ''
OR ISNULL(@float, 0) <> 0
OR @bit IS NOT NULL
OR ISNULL(@int, 0) <> 0
PRINT 'There is atleast one value'
ELSE
PRINT 'ALL ARE NULL'