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

Вниз

SQL выражение в ADO вызывает исключение в msvcrt.dll   Найти похожие ветки 

 
ЮЮ ©   (2007-11-19 12:24) [40]

> Нет именно.
>
> a.ParamCheck:=false;
> a.CommandText:=a.Parameters.ParseSQL(текст_запроса,true)
>
> a.Parameters.ParseSQL(текст_запроса,true);


Тогда третья строка, пожалуй, лишняя - ведь всё это уже выполнено во аторой.


 
ЮЮ ©   (2007-11-19 12:25) [41]

> Тогда третья строка, пожалуй, лишняя - ведь всё это уже
> выполнено во аторой.

Мда, поспешил. a.CommandText:= очистит a.Parameters


 
oxffff ©   (2007-11-19 12:26) [42]


> ЮЮ ©   (19.11.07 12:24) [40]


После второй строки  a.Parameters.Count=0.


 
Anatoly Podgoretsky ©   (2007-11-19 12:27) [43]

> oxffff  (19.11.2007 12:20:39)  [39]

Это странное слово - собака друг человека.
В данной строке должен быть запрос, а вот следующая строка как раз и занимается парсингом и созданием параметров, и то иногда не сможет исправиться. Кроме этого можно параметр создать и в ДизайнТайм, для фиксированых запросов.


 
oxffff ©   (2007-11-19 12:36) [44]


> Anatoly Podgoretsky ©   (19.11.07 12:27) [43]


Если сделать, на чем настаиваете вы, а именно

a.CommandText:=текст_запроса
a.Parameters.ParseSQL(текст_запроса,true);
..
a.open;

тогда ошибка следующая
Incorrect systax near :

при Adodataset.open


 
oxffff ©   (2007-11-19 12:40) [45]


> Кроме этого можно параметр создать и в ДизайнТайм, для фиксированых
> запросов.


В том то и дело, что запросы у меня формируются на лету.
И количество параметров меняется в зависимости от условий.
Генератор запроса сам ищет нужный параметр в классе формы и заполняет его на лету.
Таким образом я здесь вообще не принимаю участия, за исключением написания этой логики.


 
Сусл ©   (2007-11-19 12:54) [46]


>  [37] Anatoly Podgoretsky ©   (19.11.07 11:33)
> > Сусл  (19.11.2007 11:26:35)  [35]
>
> И выяснеешь у сервера, а в каком виде он например принимает
> даты.
> Про оптимизацию я вообще молчу, про нее можешь забыть.


грусновато, Анатолий, от тебя это слышать.
1. конкретный сервер всегда имеет универсальный формат даты, которые понимается всегда. есть он и у mssql.
2. ты смотрел профайлером как вызывается например AdoCommand? Это приводит к вызову sp_executesql. никто мне не запрещает пользоваться его параметрами самому. оптимизация (я так понимаю повторное использование плана запроса) в этом случае будет работать прекрасно.
а для оптимизации существенно важднее при использовании sp_executesql не забывать давать fully qualified всем таблицами и запросам (документированная, кстати, фича).


 
Anatoly Podgoretsky ©   (2007-11-19 13:13) [47]

Вот пример из одного очень древнего проекта
CommonCommand.CommandText := "DELETE FROM AuditDocuments WHERE OperationTime<:D";
CommonCommand.Parameters.ParseSQL(CommonCommand.CommandText, True);
CommonCommand.Parameters.ParamByName("D").Value := Now - 30;
CommonCommand.Execute;

ParamCheck = False


 
oxffff ©   (2007-11-19 13:29) [48]


> Anatoly Podgoretsky ©   (19.11.07 13:13) [47]


А у меня пример из сегодняшнего проекта. :)
Только у меня TadoDataset у которого нет Execute.
+запрос для возврат набора данных.


 
Anatoly Podgoretsky ©   (2007-11-19 13:30) [49]


> грусновато, Анатолий, от тебя это слышать.

Почему же грустно, это же обусловлено принципом работы сервера
Например

WHERE DT="20071119"

и

WHERE DT="20071120"

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

WHERE DT=:DT

при любых DT как минимум компилирование будет только один раз, но также сработает и статистика, в результате если 19 числа запрос выполнялся за 30 секунд, то 20 возможно уже за 10 секунд.


 
Anatoly Podgoretsky ©   (2007-11-19 13:34) [50]

> oxffff  (19.11.2007 13:29:48)  [48]

Не обращай ты внимание на Execute, это первый попавшийся пример. Для dataset тоже самое, только Open
Правда я эту технику использовал только на БДЕ, там эта проблема с параметрами наблюдалась, а на АДО я ни разу не наткнулся. Но я помню эту технологию на случай возникновение проблем.


 
oxffff ©   (2007-11-19 14:05) [51]


> Anatoly Podgoretsky ©   (19.11.07 13:34) [50]


Да я еще на одни такие грабли наткнулся. Но уже в Delphi реализации.
Грабли следующие

Запустите следующий код

var a:TADODataSet;
     b:string;
begin
inherited;
a:=TADODataSet.Create(nil);
b:=b+"select * from abc where a=:param1";
a.Parameters.ParseSQL(b,true);
showmessage(b);

и посмотрите чему равно b


 
Anatoly Podgoretsky ©   (2007-11-19 14:09) [52]

> oxffff  (19.11.2007 14:05:51)  [51]

Зачем в угадайку играть?
Но меня здесь смучает b+, зачем?


 
oxffff ©   (2007-11-19 14:13) [53]


> Anatoly Podgoretsky ©   (19.11.07 14:09) [52]
> > oxffff  (19.11.2007 14:05:51)  [51]
>
> Зачем в угадайку играть?
> Но меня здесь смучает b+, зачем?


А затем чтобы счетчик был не FFFFFFFF.


 
oxffff ©   (2007-11-19 14:16) [54]

b:="select * from abc where a=:param1";
a.Parameters.ParseSQL(b,true);
showmessage(b);

на экране select * from abc where a=:param1

А если

b:=b+"select * from abc where a=:param1";
a.Parameters.ParseSQL(b,true);
showmessage(b);

на экране select * from abc where a=?


 
Сусл ©   (2007-11-19 14:20) [55]


>  [49] Anatoly Podgoretsky ©   (19.11.07 13:30)
>
> WHERE DT=:DT
> при любых DT как минимум компилирование будет только один
> раз, но также сработает и статистика, в результате если
> 19 числа запрос выполнялся за 30 секунд, то 20 возможно
> уже за 10 секунд.


ты эта, невнимательно мой пост прочел.


 
Anatoly Podgoretsky ©   (2007-11-19 14:23) [56]

Что то с оптимизацией и со ссылками в строках. Второй вариант работает не правильно. Что именно не пойму, но это последствие b+ и то что функция ParseSQLиспользуется как процедура.
Во втором варианте есть побочное использование b, результат почему то помещенно в нее.
Сейчас проверю на своем компиляторе.


 
Anatoly Podgoretsky ©   (2007-11-19 14:25) [57]


> ты эта, невнимательно мой пост прочел.

Разве нет, если не понял, то доведи свою мысль. Мой ответ касается MS SQL и как подготавливаются запросы, если в запросе будет изменен хотя бы один символ, то он будет перекомпилирован, со статистикой 0 и неизвестным планом.


 
oxffff ©   (2007-11-19 14:26) [58]


> Anatoly Podgoretsky ©   (19.11.07 14:23) [56]


А вы посмотрите реализацию ParseSQL.
И все станет ясно.
Я на эти грабли 2 часа убил.


 
sniknik ©   (2007-11-19 14:27) [59]

> А если
а если сделать правильно?
...
b:= a.Parameters.ParseSQL(b,true);
...
(параметр b, не var чтобы расчитывать на возврат)


 
oxffff ©   (2007-11-19 14:30) [60]


> sniknik ©   (19.11.07 14:27) [59]


Вы что-то не поняли.

b:=b+"select * from abc where a=:param1";
a.Parameters.ParseSQL(b,true);
showmessage(b);

на экране будет select * from abc where a=?
А не "select * from abc where a=:param1


 
Anatoly Podgoretsky ©   (2007-11-19 14:33) [61]

Проверил.
В Д7 ошибка есть, и не зависит присваивается ли результат функции переменной.

В Д10 ошибка устранена.


 
Anatoly Podgoretsky ©   (2007-11-19 14:35) [62]


> sniknik ©   (19.11.07 14:27) [59]

Строки это очень хитрая вещь, могут быть любые сюрпризы, тем более когда в таком странном виде.


 
oxffff ©   (2007-11-19 14:37) [63]


> Anatoly Podgoretsky ©   (19.11.07 14:33) [61]


Во во, И я о том же. Сидел и думал почему, когда я делаю так

Dataset.ParamCheck:=false;
Dataset.CommandText:=Dataset.Parameters.ParseSQL(SQL,true);
Dataset.Parameters.ParseSQL(SQL,true);

showmessage(Dataset.Parameters.ParseSQL(SQL,true)) дает 0. :)

Пришлось поправить на

Dataset.ParamCheck:=false;
Dataset.CommandText:=Dataset.Parameters.ParseSQL(DupeString(SQL,1),true);
Dataset.Parameters.ParseSQL(SQL,true);


 
oxffff ©   (2007-11-19 14:38) [64]


> showmessage(Dataset.Parameters.ParseSQL(SQL,true)) дает
> 0. :)


showmessage(inttostr(Dataset.Parameters.count));


 
oxffff ©   (2007-11-19 14:42) [65]


> sniknik ©   (19.11.07 14:27) [59]
> > А если
> а если сделать правильно?
> ...
> b:= a.Parameters.ParseSQL(b,true);
> ...
> (параметр b, не var чтобы расчитывать на возврат)


Запустите

a:=TADODataSet.Create(nil);
a.Connection:=ADOConnection;
b:=b+"select * from abc where a=:param1";
c:=a.Parameters.ParseSQL(b,true);
if pointer(b)=pointer(c) then showmessage("Idential Ref");


 
sniknik ©   (2007-11-19 14:58) [66]

> Запустите
я понял что ты хочеш сказать с первого раза...

но учитывая

Anatoly Podgoretsky ©   (19.11.07 14:35) [62]
> Строки это очень хитрая вещь

+ отсутствие var для параметра, + что строка это всетаки указатель и работа в процедуре идет с ней по адресу (value:= PChar(...)) + непонятное(бессмысленное) компилятору действие

=
> а если сделать правильно?
и получать выражение (если оно нужно) оттуда где оно гарантируется.


 
oxffff ©   (2007-11-19 15:12) [67]


> sniknik ©   (19.11.07 14:58) [66]


Строки не хитрее нас с вами.
Что значит гарантируется?
Если передается параметр по значению.
То его значение не должно меняться.
Это правило.

>и получать выражение (если оно нужно) оттуда где оно гарантируется.

мне нужен результат и неизмененоое значение входного параметра.

А то что эта функция производят прямое взаимодействие со строкой и нарушает семантику типа. То это БАГ.


 
Anatoly Podgoretsky ©   (2007-11-19 15:26) [68]

> oxffff  (19.11.2007 15:12:07)  [67]

Это баг, но привел к нему ты, кострукцией B := B + Text
Баг устранен в следующей версии Дельфи.


 
oxffff ©   (2007-11-19 15:34) [69]


> Anatoly Podgoretsky ©   (19.11.07 15:26) [68]


Что значит я привел?

То есть вы хотите сказать, что это нормально?
А правильно вас понял?


 
Сусл ©   (2007-11-19 15:34) [70]


>  [57] Anatoly Podgoretsky ©   (19.11.07 14:25)
>
> > ты эта, невнимательно мой пост прочел.
>
> Разве нет, если не понял, то доведи свою мысль. Мой ответ
> касается MS SQL и как подготавливаются запросы, если в запросе
> будет изменен хотя бы один символ, то он будет перекомпилирован,
> со статистикой 0 и неизвестным планом.


запрос все равно в большинстве случаев выливается в вызов sp_executesql
так тебе никто не мешает самому пользоваться ентой штукой.
вот о чем речь.


 
oxffff ©   (2007-11-19 15:36) [71]


> Это баг, но привел к нему ты, кострукцией B := B + Text


Да какая конструкция. Эта конструкция нужна для того, чтобы выявить бажную ситуацию. И сделано для того, чтобы строка была в куче, а сегменте данных. Я же вам написал

oxffff ©   (19.11.07 14:13) [53]
oxffff ©   (19.11.07 14:30) [60]


 
oxffff ©   (2007-11-19 15:39) [72]

oxffff ©   (19.11.07 15:36) [71]

Точнее
 oxffff ©   (19.11.07 14:16) [53]
 oxffff ©   (19.11.07 14:16) [54]


 
Anatoly Podgoretsky ©   (2007-11-19 15:39) [73]

> oxffff  (19.11.2007 15:34:09)  [69]

Нет, я так не говорил, это не нормально, как ошибка, так и код.
Твое объяснение насчет ссылок меня не убедило.


 
Anatoly Podgoretsky ©   (2007-11-19 15:40) [74]

> oxffff  (19.11.2007 15:36:11)  [71]

Я возможно не понимаю истинной цели данной операции.


 
Anatoly Podgoretsky ©   (2007-11-19 15:43) [75]

> Сусл  (19.11.2007 15:34:10)  [70]

Можно много чего, но я предпочту стандартный механизм. Но если ты обеспечишь изменение запроса, что бы получилось where a=? и сумеешь передать параметры, тогда да, но тогда это ничем не будет отличаться от стандартного пути + некоторый геморой.
А как выполняются запросы в MS SQL неплохо описано в BOL, я попытался рассказать на рабоче-крестьянском. Ведь если я даже и стремлюсь переубедить тебя, то не очень настойчиво.


 
oxffff ©   (2007-11-19 16:09) [76]


> Anatoly Podgoretsky ©   (19.11.07 15:40) [74]
> > oxffff  (19.11.2007 15:36:11)  [71]
>
> Я возможно не понимаю истинной цели данной операции.


> Anatoly Podgoretsky ©   (19.11.07 15:40) [74]


Потому что для строкового литерала(который размещен в сегменте данных будет создана копия при  Result := SQL (первая строка ParseSQL)

А для не строкового литерала будет просто увеличен счетчик.

См. реализацию LStrLAsg


 
oxffff ©   (2007-11-19 16:11) [77]


> oxffff ©   (19.11.07 16:09) [76]


А далее идет прямое обращение со строкой приводя ее к pchar, тем самым нарушая семантику типа.
Отсюда грабли.

Теперь понятно??


 
Anatoly Podgoretsky ©   (2007-11-19 16:15) [78]

> oxffff  (19.11.2007 16:09:16)  [76]

Это то понятно, а вот цель нет.


 
sniknik ©   (2007-11-19 16:21) [79]

> Теперь понятно??
а вот теперь мне не понятно, получается ты специально "сбил настройки", в полном уме и трезвой памяти, а после удивляешься "ой, а тут получается разный результат", получая этот результат оттуда откуда не должен...
зачем?


 
oxffff ©   (2007-11-19 16:30) [80]

Anatoly Podgoretsky ©   (19.11.07 16:15) [78]
sniknik ©   (19.11.07 16:21) [79]

Начнем по порядку.
1. Баг1 не некорректная обработка параметров провайдером.

--> Решение

Dataset.ParamCheck:=false;
Dataset.CommandText:=Dataset.Parameters.ParseSQL(SQL,true);
Dataset.Parameters.ParseSQL(SQL,true);

Но поскольку у меня вместо SQL был вызов процедуры которая возвращает WideString. А поскольку в двух вызовах создается две копии string. Поэтому одна на другую не влияет.

Далее.

Я делаю так

SQL:=                            <- здесь это уже string
Dataset.ParamCheck:=false;
Dataset.CommandText:=Dataset.Parameters.ParseSQL(SQL,true);
Dataset.Parameters.ParseSQL(SQL,true);

и нарываюсь на другие грабли уже в delphi.
По скольку если строка в куче, то параметров после вызова
Dataset.CommandText:=Dataset.Parameters.ParseSQL(SQL,true);
уже нет.
По скольку они заменены на ? напрямую во входном параметре.

А после вызов Dataset.Parameters.ParseSQL(SQL,true);

не создает параметров. По скольку в строке уже их нет.

Чего не понятно то?



Страницы: 1 2 3 4 вся ветка

Текущий архив: 2008.04.13;
Скачать: CL | DM;

Наверх




Память: 0.64 MB
Время: 0.011 c
15-1204064466
GanibalLector
2008-02-27 01:21
2008.04.13
Модем Siemens MC35i


15-1204011180
Small Donkey
2008-02-26 10:33
2008.04.13
Интернет радио


3-1195555156
AlexeyMir
2007-11-20 13:39
2008.04.13
Добавление записи в IBQuery+IBUpdateSQL


2-1205477844
FIL-23
2008-03-14 09:57
2008.04.13
как в database запихнуть jpg ?


15-1204040112
@!!ex
2008-02-26 18:35
2008.04.13
Почему данные не уходят через WinSock.Send?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский