我遇到了一个涉及自引用临时表,存储过程和视图的问题。
我使用存储过程动态生成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,因为它应该永远不会有机会。我不知道为什么在这种情况下确实如此。
非常感谢任何帮助。
答案 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