Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.01.15;
Скачать: CL | DM;

Вниз

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;
Скачать: CL | DM;

Наверх




Память: 0.55 MB
Время: 0.052 c
4-1131051531
Pasha L
2005-11-03 23:58
2006.01.15
Найти окно из процесса


2-1135608198
Кальян
2005-12-26 17:43
2006.01.15
Школьное Рисование


2-1135454569
mixa
2005-12-24 23:02
2006.01.15
пустая папка


1-1134324968
markers
2005-12-11 21:16
2006.01.15
Tlabel и WordWrap


11-1116581578
CLX
2005-05-20 13:32
2006.01.15
Проблема с KOLOLERichEdit