Оператор T-SQL Case не выполняется в странно специфических обстоятельствах - PullRequest
0 голосов
/ 23 апреля 2011

У меня проблема, связанная с временной ссылкой на себя, хранимой процедурой и представлением.

Я использую хранимую процедуру для динамического создания SQL, который будет возвращать результаты на основе фильтров, выбранных пользователем на веб-странице. Единственное, что может сделать пользователь, - это найти озеро в зависимости от того, в каком канале он находится. Итак, если ищется дренаж А, мы должны включить в поиск и всех его детей, так как озеро знает только его самое непосредственное дренаж.

При поиске в списке дренажей процедура создает следующее

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) для хранения года или дескриптор в случае, если он неизвестен (не оптимально, но, кроме точки).

Точка, в которой возникает ошибка, когда происходит сравнение

Я проверил проблемы с isnumeric () в том смысле, что он пропускает связанные с ним числовые символы (+, -, $ и т. Д.), Но строка, в которой он терпит неудачу, это «?», Которая находится в данных, возвращает 0 в isnumeric ()

Почему это действительно мешает мне

В этом случае временная таблица возвращает список из трех идентификаторов: 161 162 и 163.

Если я заменю подзапрос этими идентификаторами, все будет работать нормально. Если я заменю столбец DrainageID номером 161, он будет работать нормально.

В любом случае в представлении не должно быть проблем с преобразованием '?' к int, потому что у него никогда не должно быть возможности. Я не знаю, почему в этом случае это так.

Любая помощь будет принята с благодарностью.

1 Ответ

0 голосов
/ 23 апреля 2011

Я хотел бы сделать предложение:

Я не уверен, как этот дескриптор может быть заполнен, но я бы проанализировал поле дескриптора для этой строки для любых символов пробела, таких как char (11)который при передаче в numeric () приводит к ложному положительному результату:

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

Это исключит любые другие причины, которые обычно не видны.

CHAR (9), 10,11, 12 и 13 и т. Д. Возвращают 1

...