带有Case语句的SQL Cast TinyInt

时间:2015-05-11 11:35:56

标签: sql-server

我正在编写一个汇总一些常见数据的查询。基本上,我试图确定资源何时被使用。

不幸的是,我的查询返回了一个错误:

  

将表达式转换为数据类型tinyint的算术溢出错误。

insert into Utilization
select resource
       ,timesegment
       ,case when min(uc.casemain_id) is null then 0 else count(uc.casemain_id) end as InUse
from ...
group by resource, timesegment

错误发生在InUse上,目标列是一个小int。我已独立运行查询,并且计数的最小值和最大值为0和4。

select min(InUse), max(InUse)
from (... the query above ...)
  

返回:0,4

有关为何发生这种情况的任何建议?

更新

导致错误的组合示例:

CREATE TABLE Usage(
    [Resource] [varchar](50) NULL,
    [TimeSegment] [datetime] NULL,
    [InUse] [tinyint] NULL
);

CREATE TABLE TimeMap(
    [TimeSegment] [datetime] NULL,
    [Resource] [varchar](50) NULL,
    [Case] [varchar](50) null,
    [Usage] [tinyint] NULL
);

CREATE PROCEDURE [dbo].[BuildTimeUsageMap] AS
BEGIN
    truncate table Utilization;
    insert into Utilization
    select resource
           ,timesegment
           ,count(uc.casemain_id) as InUse
    from   timemap
    group by resource, timesegment
END;

exec BuildTimeUsageMap;

我已将select语句更改为简化(将count(*)更改为count(uc.casemain_id)确实返回非空值的计数,谢谢@ughai)。此外,我已通过将InUse的数据类型更改为smallint来解决此问题。

将数据类型更改为smallint会导致问题消失,但这并不能解释为什么它首先不起作用。

select min(InUse), max(InUse) from Usage
  

结果:0,4

这两者都应该适合tinyint

3 个答案:

答案 0 :(得分:2)

我相信你违反了SQL Server的illogical errors(它以不同的顺序对SQL语句的logical processing order执行某些操作,并且这会引发以前不会产生的错误它遵循逻辑顺序。)

在这种情况下,您唯一真正的选择是将查询拆分为多个查询。请注意,子查询/ CTE不足以保证优化器不会充分移动以引起这些错误。

所以我会:

a)使用比真实表更宽松的类型约束创建临时表(即使用intbigint而不是tinyint)并填充它。此查询应该是执行任何聚合和任何过滤器的查询。

b)(可选)运行查询,专门针对超出范围的值并针对任何找到的内容提出特定的错误消息

c)INSERT从临时表到真实表。

答案 1 :(得分:0)

假设InUse是TINYINT,查询中可能有超过255条记录,因此溢出是COUNT(uc.casemain_id)返回高于255的值.MIN和MAX不计算记录 - 查询中的最高和最低值。用COUNT(1)替换第二个查询,保持相同的组,以确认行数超过TINYINT最大值。

答案 2 :(得分:0)

试试这个:

And I logout