在奇怪的特定情况下,T-SQL Case语句失败

时间:2011-04-22 21:49:41

标签: tsql stored-procedures view casting case

我遇到了一个涉及自引用临时表,存储过程和视图的问题。

我使用存储过程动态生成sql,该sql将根据用户在网页上选择的过滤器返回结果。用户可以做的一件事就是根据它所处的排水来搜索湖泊。因此,如果搜索排水A,我们必须将所有孩子都包括在搜索中,因为湖泊只知道最直接的引流。

当搜索排水列表时,proc会创建以下

WITH DrainageHeirarchy AS
        (
        SELECT d.DrainageID, d.DrainageDesc, d.ParentDrainageID
        FROM Drainage d
        WHERE d.DrainageID IN (161)
        UNION ALL
        SELECT d.DrainageID, d.DrainageDesc, d.ParentDrainageID
        FROM Drainage d
        JOIN DrainageHeirarchy ON d.ParentDrainageID = DrainageHeirarchy.DrainageID
        )

*请注意,在这种情况下,161只是用户正在过滤的逗号分隔的逗号分隔列表。

现在,我们希望从包含湖泊数据的视图中提取信息。所以proc生成以下select语句。

select DISTINCT
    l.Year1stStocked
from dbo.vwlakeextended l
WHERE DrainageID IN (SELECT DrainageID FROM DrainageHeirarchy)

*请注意,为了简单起见,我删除了很多其他字段,以及where子句中的其他一些检查似乎没有引起任何问题。

用户选择排水161的情况是特殊的,因为它会导致错误。首先要理解这一点,我们必须看看视图dbo.vwlakeextended如何生成字段。它是通过以下方式实现的。

case when isnumeric(l.Year1stStocked)=0 or l.Year1stStocked is null
   then (select cast(min(s.stockyear) as varchar(255)) from stk.stocking s where replace(SiteCode, ' ', '') = replace(l.lakecode, ' ', ''))
   else case when isnull(               
                            (select min(s.stockyear)
                             from stk.stocking s
                             where replace(SiteCode, ' ', '') = replace(l.lakecode, ' ', ''))
                                     ,year(getdate())
                         ) < l.Year1stStocked
            then (select cast(min(s.stockyear) as varchar(255)) from stk.stocking s where replace(SiteCode, ' ', '') = replace(l.lakecode, ' ', ''))
            else l.Year1stStocked
        end
end as Year1stStocked,

有效的是,如果我们的源表中没有给出年份,那么从另一个表生成数字。源表使用varchar(255)来存储年份,或者在未知的情况下使用描述符(不是最佳的,但除了点之外)。

比较时间点发生错误的点&lt; l.Year1stStocked发生。有趣的是,这应该只发生在isnumeric(l.Year1stStocked)= 0或l.Year1stStocked为空的情况下,因此比较应该不是问题。

我已经检查了isnumeric()的问题,因为它传递了数字相关的字符(+, - ,$等),但它失败的字符串是'?',它在数据中,并且在isnumeric()

上返回0

为什么它真的让我失意

在这种情况下,临时表返回一个包含三个ID的列表:161,162和163。

如果我用这些id替换子查询,一切正常。 如果我用数字161替换DrainageID列,它可以正常工作。

在任何情况下,视图都不应该转换'?'到一个int,因为它应该永远不会有机会。我不知道为什么在这种情况下确实如此。

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

我想提出一个建议:

我不确定如何填充该描述符但是我会为任何空白字符(如char(11))解析该行的描述符字段,当传递给numeric()时会产生误报:< / p>

declare @v varchar(10);
set @v = CHAR(11);
select isnumeric(@v);
select @v;

这将排除可能通常不可见的任何其他原因。

CHAR(9),10,11,12&amp; 13等返回1