-
Уважаемые мастера! Кто-нибудь сталкивался с такой проблемой: запрос
Select * from dn Where ((select val from READ_DSI(dn.doc,dn.num,99692)) not between 0 and 60)
исполняется без ошибок, результат выдается правильный, а запрос
Select * from dn Where ((select val from READ_DSI(dn.doc,dn.num,99692)) between 0 and 60)
сообщает:
Unsuccessful execution caused by an unavailable resource. Unsupported field type specified in BETWEEN predicate.
Вся разница есть или нет "not" перед "between" !!!
Что бы это могло значить и как с этим бороться? Писать отдельно сравнение на первую границу а топом на вторую как-то топорно выглядит.
На всякий случай текст READ_DSI:
CREATE PROCEDURE READ_DSI ( doc integer, num integer, atr integer) returns ( val integer) as begin select val from dsi where doc=:doc and num=:num and atr=:atr into :val; suspend; end
-
> Unsuccessful execution caused by an unavailable resource. > Unsupported field type specified in BETWEEN predicate. вернуло значение не поддерживаемого типа, null например, или наоборот рекордсет, а можно только одиночное значение. > Что бы это могло значить и как с этим бороться? не знаю как это в синтаксисе Firebird, но попробуй примерно так
....
begin
select first 1 val from dsi
where doc=:doc and num=:num and atr=:atr into :val;
if val is null
begin
set val = -1
end
suspend;
end
-
Правильно ли я понял, что BETWEEN не работает со значениями null ?
-
Так я сделать не могу, поскольку процедура должна правильно возвращать null, если значения не будет найдено. Гипотеза о том, что between не работает с null не подтвердилась проверкой.
-
Кроме того, в DSI на DOC,NUM,ATR стоит Primary_Key, так что "first 1" тут лишний
-
Поднял все записи запросом Select
(select val from READ_DSI(dn.doc,dn.num,99692)) "val"
,dn.*
from dn
Where
((select val from READ_DSI(dn.doc,dn.num,99692)) >= 0) and
((select val from READ_DSI(dn.doc,dn.num,99692)) <= 60) который является полным логическим аналогом неработающего запроса (см.первый пост) и убедился, что все VAL имеют значение не null
-
> Правильно ли я понял, что BETWEEN не работает со значениями null ? кто ж его знает как там у вас в Firebird-е (в mssql работает), но ошибка именно о не поддерживаемом типе, а что еще может возвращать твоя процедура неверного?
> Гипотеза о том, что between не работает с null не подтвердилась проверкой. явно заданное null (выражение с которым на этапе компиляции вычисляется) проверял или возвращаемое процедурой?
> Кроме того, в DSI на DOC,NUM,ATR стоит Primary_Key, так что "first 1" тут лишний позновато про Primary_Key, это надо было в первом посте, тогда в ответе было бы только одно действие...
а вообще довольно глупая реализация с процедурой в одно действие... легко обойтись без нее простым запросом на объединение.
-
> который является полным логическим аналогом неработающего запроса (см.первый пост) и убедился, что все VAL имеют значение не null для проверки нужен не аналог, а те значения которые у тебя в нем отсеиваются условием. т.е. убери условие вообще, есть хоть один null?
-
> легко обойтись без нее простым запросом на объединение. SELECT dn.* FROM dn
INNER JOIN dsi ON dn.doc=dsi.doc AND dn.num=dsi.num
WHERE dsi.atr=99692 AND dsi.val between 0 and 60 делов то. и работать это будет быстрее чем с процедурой.
-
Запрос Select dn.* from dn
Where dn.doc=350
and exists (select val from READ_DSI(dn.doc,dn.num,353)) выдал 16 записей. Во всех записях val <> null . Значения val в пределах от 1 до 23. Запрос Select dn.* from dn
Where dn.doc=350
and not exists (select val from READ_DSI(dn.doc,dn.num,353)) не выдал ни одной записи. Т.е. данные корректны. Запрос Select dn.* from dn Where dn.doc=350 and ((select val from READ_DSI(dn.doc,dn.num,353)) between 0 and 60) опять выдал глюк Unsuccessful execution caused by an unavailable resource.
Unsupported field type specified in BETWEEN predicate а запрос Select dn.* from dn
Where dn.doc=350
and ((select val from READ_DSI(dn.doc,dn.num,353)) not between 0 and 60) проработал нормально, выдав пустую таблицу. Запрос Select dn.* from dn
Where dn.doc=350
and ((select val from READ_DSI(dn.doc,dn.num,353)) not between 0 and 2) проработал нормально, выдав таблицу из 10 записей. Если же заменить between на условие по двум границам, все запросы проходят на ура и работают правильно. Таким образом, похоже, что это глюк FireBird, связанный с неправильной работой оператора between Что касается очевидного упрощения кода, то тут не все так просто, поскольку это лишь кусочек большого проекта, в котором запросы динамически формируются, типы поднимаемых полей заранее не известны и призодится писать группу процедур с похожими именами для поднятия данных разных типов (в том числе и нестандартных) из разных таблиц с помощью специального конструктора запроса.
-
-
Оттуда же View that uses select expressions from selectable stored procedure fails to execute with error: Unsuccessful execution caused by an unavailable resource. Unsupported field type specified in BETWEEN predicate.
for select from view that uses BETWEEN predicate applied to select expression. See attached script for reproducible test case. It executes correctly when equivalent construct X >= val1 and X <= val2 is used.
-
> Т.е. данные корректны. проверять нужно не итоговые данные, а те которые были в условии до получения этих корректных данных. непонятно? сравниваем "0" = 0 → неверный тип, 0 = 1 → правильное условие но не подходящее. тебе говорят что у тебя в условиях бывают с неверным типом, а ты проверив другим способом говоришь, вот у меня же значения 0 и оно корректно! и кучу примеров одного и того же условия разными способами приводишь, а просили тебя проверить вообще без условий.... > т.е. убери условие вообще, есть хоть один null? вот этот запрос, без условий Select (select val from READ_DSI(dn.doc,dn.num,99692)) "val"
from dn
-
Виталий Панасенко(дом) (28.03.10 13:48) [11]> It executes correctly when equivalent construct X >= val1 and X <= val2 is used. тогда ему придется вызывать процедуру 2 раза... тогда уж лучше проверить работоспособность такого Where not ((select val from READ_DSI(dn.doc,dn.num,99692)) not between 0 and 60)
-
> а просили тебя проверить вообще без условий.... чтобы получить все значения которые попадут на вход тому условию которое не справляется, и посмотреть есть ли среди них не валидные.
-
[13] тогда уж лучше проверить работоспособность такого Where not ((select val from READ_DSI(dn.doc,dn.num,99692)) not between 0 and 60)Пробовал, тот же глюк. Двойное отрицание, по-видимому, оптимизируется до отсутствия отрицаний. [14] а просили тебя проверить вообще без условий.... чтобы получить все значения которые попадут на вход тому условию которое не справляется, и посмотреть есть ли среди них не валидные. запрос Select (select val from READ_DSI(dn.doc,dn.num,99692)) "val"
from dn вернул 15802 пустых записей и 16 записей с правильными данными. Получается, что для between значение null недопустимо, а для not between допустимо. Что странно, но представимо. Однако сделал еще следующие проверки. Запрос Select
(select val from READ_DSI(dn.doc,dn.num,353)) "val"
,dn.* from dn
Where dn.doc=350 вернул 16 записей, все значения val не null из перечня (0,1,3) Запрос Select
(select val from READ_DSI(dn.doc,dn.num,353)) "val"
,dn.* from dn
Where dn.doc=350
and ((select val from READ_DSI(dn.doc,dn.num,353)) between 0 and 1) породил уже упомянутый глюк! Так что либо гипотеза о недопуастимости null должна быть отвергнута, либо среда FireBird второе условие исполняет раньше первого, что странно, поскольку на doc в dn имеется индекс.
-
> породил уже упомянутый глюк! естественно, т.к. при and, проверяются все условия, должно совпадать и то и то. а если or, то достаточно первого при true и все одно "свалится" при false. > Так что либо гипотеза о недопуастимости null должна быть отвергнута остается в силе... вот так "сработает" ...
Where dn.doc<>350
and ((select val from READ_DSI(dn.doc,dn.num,353)) between 0 and 1) т.к. тут первое будет false и дальнейшая проверка необязательна при "неправильных" вторых значеняих, и true и обязательна при "правильных". p.s. единственное показательное было бы проверить изменив процедуру так как показано в [1]. но ты как то странно обходишь все правильные проверки, и делаешь выводы по ничего не значащим тестам (проверяющим "рядом").
-
> вот так "сработает" хотя, может и не сработать. порядок выполнения условий определяется, насколько помню, самим сервером.
-
[16] p.s. единственное показательное было бы проверить изменив процедуру так как показано в [1]В dsi могут быть любые численные значения, в том числе и -1, поэтому и нельзя переделывать процедуру. Всем спасибо, помогли.
-
> поэтому и нельзя переделывать процедуру. значит нельзя проверить... странно.
|