У меня проблема, связанная с временной ссылкой на себя, хранимой процедурой и представлением.
Я использую хранимую процедуру для динамического создания 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, потому что у него никогда не должно быть возможности. Я не знаю, почему в этом случае это так.
Любая помощь будет принята с благодарностью.