检查一个变量是否为空

时间:2011-04-07 09:05:17

标签: sql-server tsql

在我的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'

6 个答案:

答案 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'