11

不能在 T-SQL 的 case 语句中引发错误吗?我总是遇到 SQL 案例语句的问题:/

    begin try
    declare @i int 
    --set @i = (select COUNT(1) from table_name)

    select Item_Num =
        CASE (select COUNT(1) from table_name)
            when 1 then (select Item_Num from table_name)
            when 0 then (raiserror('No records in database', 0, 0))
            ELSE (raiserror('Multiple records in database', 0, 0))
        END
    from table_name

    end try
    begin catch
        declare @errormsg nvarchar(1024),
                @severity int,
                @errorstate int;

        select @errormsg = error_message(),
                @severity = error_severity(),
                @errorstate = error_state();

        raiserror(@errormsg, @severity, @errorstate);
    end catch
4

4 回答 4

4

将 Case/When 视为对单个数据进行操作。如果你这样想,你的很多问题就会迎刃而解。

If/Then 用于控制逻辑的流动。

像这样的东西应该适合你。

declare @i int 
set @i = (select COUNT(1) from table_name)

If @i = 1
  Begin
    Print "1 row"
  End
Else If @i = 0
  Begin
    Print "no rows"
  End
Else
  Begin
    Print "too many rows"
  End
于 2014-05-14T18:50:48.773 回答
3

您可以通过将错误字符串转换为 int 从 case 表达式引发错误。

select case (select count(*) from mytable)
  when 1 then 100 
  when 2 then 200
  else convert(int, 'ERROR')
end

这会给出一条错误消息,例如

Conversion failed when converting the varchar value 'ERROR' to data type int.

这与您将获得的一样好。

并非所有失败的转换都会在错误消息中提供输入字符串。例如,不能转换为日期时间。因此,如果您的 case 表达式返回一个日期时间,您仍然必须通过字符串到整数的转换来触发错误:

select case (select count(*) from mytable)
  when 1 then getdate()
  else convert(datetime, convert(int, 'ERROR'))
end

更糟的是:如果你要返回一个日期,你不能明确地将它从 int 转换,所以你必须求助于

convert(date, convert(char(1), convert(int, 'ERROR')))

这非常可怕,但在我看来,唯一比干净代码更重要的是信息丰富的错误消息,所以我接受它。

于 2020-04-08T20:06:39.660 回答
1

正如我在评论中所说,我认为简单地创建一个您在CASE语句范围之外检查的标志会更容易。类似于以下内容:

--- code before the TRY...
BEGIN TRY
    DECLARE @i int 

    -- declare a variable to act as a flag
    DECLARE @my_flag as int

    -- than change your statement to simply fill the value of the flag 
    CASE (SELECT COUNT(1) FROM table_name)
         WHEN 1 THEN SET @my_flag = 1
         WHEN 0 THEN SET @my_flag = 0
         ELSE SET @my_flag = -1
     END

    IF (NOT @my_flag in (-1, 0))
    BEGIN
        SET @Item_Num = (SELECT Item_Num FROM table_name) -- consider a filter here
      END 
     ELSE
    BEGIN
        IF (-1 = @my_flag) RAISERROR('too many records', 0, 0)
        IF (0 = @my_flag) RAISERROR('no records', 0, 0) 
      END
END TRY
BEGIN CATCH 
    --- rest of the code goes here.... 
于 2014-05-14T15:57:18.573 回答
0
    With #TempTable as 
    (
       Select * from ...    
       -- record set that determines if I should error out
    )  
    SELECT CASE WHEN COUNT(1) > 0 
     THEN 'Multiple records in database' 
     ELSE 0 
    END AS [Value]
    FROM #TempTable

如果您尝试使用 TSQL 出错,则数据类型不匹配将终止该方法。在我的情况下工作,因为这是一个繁重的过程,我需要知道正确转移。如果我的记录集 >1,那么我知道我应该失败。如果您在 .NET 环境中使用 SSIS 或多种方法,则很有用

于 2017-11-29T00:20:19.430 回答