Форум: "Базы";
Текущий архив: 2006.01.15;
Скачать: [xml.tar.bz2];
ВнизADOQuery + ClientDataSet. Ошибка при пустом параметре Найти похожие ветки
← →
Vlad © (2005-11-15 17:54) [0]БД - MS-SQL
В ADOQuery пишу простейший запрос:select * from MyTable where MyStringField = :param
Параметру задаю тип String, нужную длину и т.п.
в коде программы:AdoQuery.Parameters[0].Value := ""; // задаю пустую строку
AdoQuery.Open;
Все работает как надо.
Теперь беру ClientDataSet и через провайдера подключаю его к моему ADOQuery. У ClientDataSet так же прописываю параметр и задаю ему тип String и нужную длину.
в коде программы пишу:
ClientDataSet.Params[0].Value := "";
ClientDataSet.Open;
Так вот, если параметру присвоить пустое значение, то на Open вываливается exception: "The text, ntext ot image data can not be compared or sorted, except wher using IS NULL or LIKE operator".
Если непустое - то все ОК.
Смотрю профайлером, какой запрос посылается на сервер.
Профайлер говорит что тип моего параметра почему-то "text", значение - ""
а в случае непустого параметра - тип varchar, как и должно быть.
Так же, если использовать ADOQuery, без всяких ClientDataSet-ов, то пустой параметр тоже проходит нормально, и подставляется как varchar
Вобщем, понятно что кто-то (толи ClientDataSet, толи DataSetProvider) неправильно интерпретирует тип параметра, в случае, если ему присвоить "". Но непонятно как это побороть.
Приходила в голову идея в sql запросе явно преобразовывать параметр к varchar, но это если не докопаюсь до истины...
Поделитесь, если у кого нибудь возникнут какие-то мысли по поводу данной проблемы.
Спасибо.
← →
Ega23 © (2005-11-15 18:06) [1]Попробуй у строки длину поставь. 50, например.
← →
Vlad © (2005-11-15 18:09) [2]
> Ega23 © (15.11.05 18:06) [1]
> Попробуй у строки длину поставь. 50, например.
В смысле у параметра? Сколько не ставь, хоть 50 хоть 150 - бесполезно :-(
← →
Ega23 © (2005-11-15 18:13) [3]
> В смысле у параметра? Сколько не ставь, хоть 50 хоть 150
> - бесполезно :-(
А зачем ты, кстати, ClientDataSet"у параметр прописываешь?
← →
Vlad © (2005-11-15 18:19) [4]
> Ega23 © (15.11.05 18:13) [3]
Если быть точнее, руками я его не прописываю, а делаю Fetch params в дизайн-тайме. При этом он сам у себя прописывает параметр, соответствующий параметру у ADOQuery.
Я просто контролирую чтобы тип и размер совпадал с тем, который у ADOQuery (бывает, иногда не совпадает)
← →
ivb2001 (2005-11-15 20:57) [5]Для SQL паскакалевские двойные кавырки - пустой звук. Я с этим в InterBase напарился вдоволь. Попробуйте чиста канкретно присвоить NIL(вот только забыл как это правильно будет EmptyVar то ли VarEmpty ибо Parms[].value имеет тип Variant) Вобщем идея, думается, понятна
← →
Vlad © (2005-11-15 21:04) [6]
> ivb2001 (15.11.05 20:57) [5]
> Попробуйте чиста канкретно присвоить NIL
Вероятно, имелось ввиду null?
Ну да, можно и так, только в результате и в sql запрос подставится null, а мне нужно подставить туда пустую строку :-)
И еще, не понимаю как связаны "паскалевские" кавычки и SQL ? :-)
← →
sniknik © (2005-11-15 21:48) [7]> select * from MyTable where MyStringField = :param
....
> ClientDataSet.Params[0].Value := "";
> ClientDataSet.Open;
> Так вот, если параметру присвоить пустое значение, ...
т.е. нужно сравнить с пустой строкой? попробуй такClientDataSet.Params[0].Value := #32;
← →
Desdechado © (2005-11-15 22:49) [8]может, стоит присваивать не Value, а AsString ?
← →
Johnmen © (2005-11-15 23:39) [9]Да-да, Desdechado © похоже прав.
Params.ParamByName("xxx").AsString
>sniknik © (15.11.05 21:48) [7]
>ClientDataSet.Params[0].Value := #32;
Это же пробел...:)
← →
sniknik © (2005-11-15 23:56) [10]> Это же пробел...:)
а то я не знаю. просто напиши здесь пробел в скобочках " " практически не отличается от "", а так видиш заметно.
← →
Vlad © (2005-11-16 08:29) [11]
> Desdechado © (15.11.05 22:49) [8]
> может, стоит присваивать не Value, а AsString ?
Нет, не в этом дело. И Value и AsString дают одинаковый результат (ошибку), если присваивать параметру пустую строку.
Причем, если работать напрямую с ADOQuery, то с его параметром проходит нормально хоть пустой хоть непустой параметр.
А вот ClientDataSet-овскому параметру присвоить пустое значение, то получается такая вот фигня... Провайдер почему-то решил, что пустая строка имеет тип text, а не varchar, и в запрос подставляет ее как тип text, из-за чего видимо и вылазит ошибка.
> sniknik © (15.11.05 23:56) [10]
С пробелом-то все работает. Но это не пустая строка :-)
← →
sniknik © (2005-11-16 08:58) [12]> С пробелом-то все работает. Но это не пустая строка :-)
а ты всетаки попробуй.
← →
Vlad © (2005-11-16 09:04) [13]Я кстати пытался посмотреть как все-таки провайдер формирует sql запрос, но исходников нету. Видимо все это зашито в midaslib, а pas-файла нету, только dcu
← →
Vlad © (2005-11-16 09:05) [14]
> sniknik © (16.11.05 08:58) [12]
> > С пробелом-то все работает. Но это не пустая строка :-
> )
> а ты всетаки попробуй.
Пробовал. Запрос формируется нормально, параметр имеет тип varchar как нужно. Ошибок нет. Но и данных нет :-)
← →
Johnmen © (2005-11-16 09:32) [15]
> Vlad © (15.11.05 17:54)
> БД - MS-SQL
> В ADOQuery пишу простейший запрос:
> select * from MyTable where MyStringField = :param
А если такselect * from MyTable where MyStringField =CAST(:param AS VARCHAR(X))
← →
Vlad © (2005-11-16 09:36) [16]
> Johnmen © (16.11.05 09:32) [15]
Угу. Это первое, что пришло мне в голову. Так работает.
Непонятно почему без этого не работает :-)
← →
Johnmen © (2005-11-16 09:44) [17]
> Vlad © (16.11.05 09:36) [16]
> Непонятно почему без этого не работает :-)
Ну это то понятно
>"The text, ntext ot image data can not be compared or sorted, except wher
>using IS NULL or LIKE operator".
Непонятно, почему это...
:)
Кстати, а какой тип в дизайне у параметра CDS?
← →
Vlad © (2005-11-16 09:57) [18]
> Кстати, а какой тип в дизайне у параметра CDS?
ftString
а вот что выдает профайлер, если присвоить пустое значение параметру:exec sp_executesql N"select * from personalaccount where personalaccount_id = @P1", N"@P1 text", ""
(Возникает вышеуказанная ошибка)
и вот что при непустом:exec sp_executesql N"select * from personalaccount where personalaccount_id = @P1", N"@P1 varchar(4)", "AFKN"
(Ошибки нет)
в обоих случаях в CDS тип параметра ftString. Менял только строчку кода
в первом случае писалClientDataSet.Params[0].AsString := "";
во второмClientDataSet.Params[0].AsString := "AFKN";
← →
Johnmen © (2005-11-16 10:13) [19]Посмотри ещё
Params[x].Text в рантайме
и
Params -> Value -> Type в дизайне
← →
Vlad © (2005-11-16 10:30) [20]
> Params[x].Text в рантайме
пустая строка
> Params -> Value -> Type в дизайне
string
← →
Johnmen © (2005-11-16 11:52) [21]Я, кажить, понял в чём дело...
Глянь в DBClient.pas реализацию TCustomClientDataSet.SetOptionalParam
Очень интересно со строковым типом...:)
← →
Vlad © (2005-11-16 12:12) [22]
> Johnmen © (16.11.05 11:52) [21]
Ты про OleStr, там где происходит попытка преобразования к TSQLTimeStamp?
И, кстати, а причем тут опциональные параметры, я ж их не задаю...
← →
Vlad © (2005-11-16 12:45) [23]
> Johnmen © (16.11.05 11:52) [21]
Я кажется понял, что ты имел ввиду...ParamType := ParamTypeMap[VarType(Value) and varTypeMask];
для того чтобы получилось dsfldZSTRING нужно чтобы параметр был типа OleStr
кстати, если VarType(Value) вернет varString получится полная фигня :-)
Но опять же встает вопрос - как опциональные параметры применить к моей ситуации? :-)
← →
Johnmen © (2005-11-16 13:22) [24]Что-то ДельфиМастера подглюкивают...:)
Писал пост, он ушёл в аут. Повторяться лень.
>Vlad © (16.11.05 12:45) [23]
Я имел в в виду строкиParamLen := Length(S) + 1;
иParamType := ParamType shl dsSizeBitsLen or ParamLen;
Опциональные параметры м.б. и непричём. Важно, что какие-то манипуляции с типом происходят на основании данных параметра.
← →
Vlad © (2005-11-16 13:35) [25]
> Johnmen © (16.11.05 13:22) [24]
> ParamLen := Length(S) + 1;
ну здесь то все понятно: устанавливают длину параметра равной длине переменной + 1 (видимо для завершающего #0)
> ParamType := ParamType shl dsSizeBitsLen or ParamLen;
Вот тут не очень понятно... С какой-то целью меняется тип параметра в завис. от его размера
но фишка в другом: TCustomClientDataSet.SetOptionalParam не выполняется вообще (дебаггером проверял).
А вот то место где считываются параметры (которые TParams, а не опциональные) и где они подставляются в запрос - я так и не нашел :-(
← →
Johnmen © (2005-11-16 13:49) [26]>Vlad © (16.11.05 13:35) [25]
Я бы вывел в Watches тип интересующего параметра и пошёл бы дебаггером, чтобы найти то место, где тип переопределяется...
← →
Vlad © (2005-11-16 15:04) [27]
> Johnmen © (16.11.05 13:49) [26]
Прошелся ради интереса. Тип нигде не переопределяется.
DataSetProvider считывает параметры у ClientDataSet и подставляет их в ADOQuery (подставляет правильно, я проверил). Больше никаких манипуляций с параметрами не проводилось.
Затем провайдер открывает ADOQuery, и там, вглубине метода Open возникает исключение в строчке Recordset.Open (вызов метода COM-объекта).
При всем при этом никаких изменений в параметрах не происходило вплоть до возникновения exception-a. Тип и значения были верными.
← →
Johnmen © (2005-11-16 15:52) [28]>Vlad © (16.11.05 15:04) [27]
...
Ещё есть смутные идеи... Но озвучивать не буду :)
PS
попробуйClientDataSet.Params[0].Value := #0;
← →
Vlad © (2005-11-16 16:37) [29]
> ClientDataSet.Params[0].Value := #0;
Так сработало :-)
Но так придется каждый раз в программе производить подмену пустой строки на #0., ну впринципе тоже выход :-)
Страницы: 1 вся ветка
Форум: "Базы";
Текущий архив: 2006.01.15;
Скачать: [xml.tar.bz2];
Память: 0.52 MB
Время: 0.014 c