Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2006.06.18;
Скачать: [xml.tar.bz2];

Вниз

Наступил на очередные грабли   Найти похожие ветки 

 
paul_k ©   (2006-05-30 13:47) [0]

Есть БД MSSQL 2000, SP 4
есть запрос
TmpSql:=TADOQuery.Create(nil);
TmpSql.Connection:=dm.ac_main;
dm.ac_main.Open;


текст запроса формируется в процесе исполнения.
TmpSql.SQL.Clear;
       TmpSql.SQL.Add("INSERT INTO tal_log_data(ip, log_date, log_time, metod, url, srv_resp, traf, referer, srv_name, br_full_str, br_type, br_version, site_name, file_ext)");
       TmpSql.SQL.Add("values(");
       TmpSql.SQL.Add(""""+StringGrid1.Cells[0,i]+""",");
       TmpSql.SQL.Add("convert(datetime,"""+StringGrid1.Cells[1,i]+""",106),");
              TmpSql.SQL.Add("convert(datetime,"""+StringGrid1.Cells[2,i]+""",108),");
       TmpSql.SQL.Add(""""+StringGrid1.Cells[3,i]+""",");
       TmpSql.SQL.Add(""""+StringGrid1.Cells[4,i]+""",");
       TmpSql.SQL.Add(StringGrid1.Cells[6,i]+",");
       TmpSql.SQL.Add(StringGrid1.Cells[7,i]+",");
       TmpSql.SQL.Add(""""+StringGrid1.Cells[8,i]+""",");
       TmpSql.SQL.Add(""""+StringGrid1.Cells[9,i]+""",");
       TmpSql.SQL.Add(""""+StringGrid1.Cells[10,i]+""",");
       TmpSql.SQL.Add(""""+StringGrid1.Cells[11,i]+""",");
       TmpSql.SQL.Add(""""+StringGrid1.Cells[12,i]+""",");
       TmpSql.SQL.Add(""""+StringGrid1.Cells[19,i]+""",");
       TmpSql.SQL.Add(""""+StringGrid1.Cells[20,i]+"""");
       TmpSql.SQL.Add(")");

с завидной регулярностью получаю
Parameter object is improperly defined. Inconsistent or incomplete information was provided
При этом из Аналайзера запрос выполняется на ура.
Текст запроса
INSERT INTO tal_log_data(ip, log_date, log_time, metod, url, srv_resp, traf, referer, srv_name, br_full_str, br_type, br_version, site_name, file_ext)
values(
"72.36.182.34",
convert(datetime,"30 Apr 2006",106),
convert(datetime,"14:29:57",108),
"GET",
"/link/\"http://vymp.ru\"",
404,
12957,
"-",
"",
"Goku/1.16 (Goku; http://goku.ru/bot.htm; bot@goku.ru)",
"Goku",
"1.16",
"flat-design.ru",
""
)

Собственно вопрос - в чем грабли себе закопал?


 
Johnmen ©   (2006-05-30 14:01) [1]

Вот и надо использовать упомянутые параметры. В запросе....


 
evvcom ©   (2006-05-30 14:04) [2]

Блин, любители динамических граблей!


 
paul_k ©   (2006-05-30 14:12) [3]

> [1] Johnmen ©   (30.05.06 14:01)

А что это изменит?
ну кину на форму запрос передам ей эту радость в качестве параметров а что изменится то?
кстати убрал кавычки в
  "/link/\"http://vymp.ru\"",
эта абшибка исчезла.
Но все равно не понятно Аналайзер запрос кушает а дельвя - нет

> [2] evvcom ©   (30.05.06 14:04)
> Блин, любители динамических граблей!

ты это, не мудри ты пальцем покажи


 
Johnmen ©   (2006-05-30 14:15) [4]


> paul_k ©   (30.05.06 14:12) [3]
> > [1] Johnmen ©   (30.05.06 14:01)
> А что это изменит?


Всё и радикально!
Кстати, ошибка у тебя была из-за наличия : в склеиваемых строках. Да ещё и кавычки, как содержимое...


 
evvcom ©   (2006-05-30 14:17) [5]


> ты пальцем покажи

ну а через параметры не пробовал? И без постоянной перезаписи SQL. Он же, наверное, не меняется?


 
paul_k ©   (2006-05-30 14:24) [6]

> [4] Johnmen ©   (30.05.06 14:15)

двоеточия остались...  Ошибка не вылазит.
а что таки изменится? скорость работы вырастет?
Запрос все равно выносится в ХП. вместо insert ставится exec sp_add


> [5] evvcom ©   (30.05.06 14:17)

ещё раз повторю ты не мудри.. толком поясни да?
Запрос, кстати, меняется.


 
ЮЮ ©   (2006-05-31 05:04) [7]

Если пользоваться параметрами принципиально не желаешь, то отключи ParamCheck у TmpSql, ибо когда в тексте запроса встречается символ : он интерпретируется как параметр


 
paul_k ©   (2006-05-31 14:47) [8]

С двоеточием понял, спасибо.
Вот только не понял как в строке
select * from XXX where YYY="Z:D"
это двоеточие внутри кавычек вылезет как параметр.
Ибо не наступал пока на эти грабли.

Остался вопрос о "любви и нелюбви" параметров.
В результате весь этот инсерт завернут в процедуру.
слеедовательно вопрос как и почему грамотнее писать
1. AdoStoredProc и параметры?
2. TAdoQuery прописывать строку exec proc_name @field1 = :param1... и заполнять параметры при необходимости?
3. TAdoQuery и перед вызовом ExecSql формировать строку exec proc_name @field1 = value1...?


 
ЮЮ ©   (2006-06-01 03:32) [9]


> это двоеточие внутри кавычек вылезет как параметр.

В том случае, если ParamCheck is True.

Лучше, ИМХО, 2.
Кроме того, я предпочитаю синтаксис
 exec proc_name(:param1, ... , :paramN)

Когда запрос оформлен параметрически, нет нужды заботиться о том, есть ли кавычки, пробелы, двоеточия и прочая лабуда в ЗНАЧЕНИИ параметра. Запрос будет всегда синтаксически правилен, в отличии от динамического фомирования запроса твоим методом, где, если что-то не учтешь, можешь получить синтаксически неверный текст запроса


 
sniknik ©   (2006-06-01 09:34) [10]

вот так и возникают перекосы сознания... на один простейший инсерт процедуру??? только потому что ктото сказал волшебное слово параметры, а автор их ни с чем более не ассоциирует как с процедурами...
идиотское решение. имхо.

простой параметрический запрос, выполненный в ADOCommand (инсерт не возвращает рекордсет) это все что сдесь надо. абсолютно незачем лепить процедуру...

как то дали программу на переделку, типа поправить чтото, в ужас пришол, на 100 таблиц 1500 процедур, и столько же вьюшек (все под одну роль, понятно бы если бы делилось хоть както), и это при том что реально использовалось 5-10 таблиц... все остальное "ну это пока не работает, делал с прицелом на развитие"... (которое пошло по другому пути), нафига процедур столько? "ну это же правильно! (/круто)", ага правильно, в процедуре единственный простой запрос select * from xxxx, который после выполнения фильтруется... брррр.
и все потому, что вначале ему сказали - "процедура это круто", а почему не сказали.


 
paul_k ©   (2006-06-01 09:39) [11]

Так, с синтаксисом все понятно..
Я перешел к динамическому формированию запросов с той точки зрения что кладешь в мемо sql.text и смотришь, что за байду наформировал. Удобно при отладке. Удобно в лог текст запроса при ошибке писать. С парамтрами у меня такое не проходит.
Да минус - давить всяческие кавычки апострофы  и прочую "радость".

Если запрос один .а надо "передергивать" его много раз - практика показала что параметры ещё и быстрее работает. (А почему, мне туготдуму пока не осилить понятия "что в какой момент кешируется". А хотелось бы это понять..)
А вот насколько это касается работы с ХП?
И как вообще можно ускорить сей процесс?
И почему он ускорится или затормозится?


 
paul_k ©   (2006-06-01 09:45) [12]

> [10] sniknik ©   (01.06.06 09:34)


> простой параметрический запрос, выполненный в ADOCommand
> (инсерт не возвращает рекордсет) это все что сдесь надо.
> абсолютно незачем лепить процедуру...

Со всем уважением, молодой человек, а Вы ТЗ мое читали? С политикой партии установленной здесь знакомы? Или от того тестового кусочка отталкиваетесь?

> и все потому, что вначале ему сказали - "процедура это круто",
> а почему не сказали.

А разве это не выходит за рамки обсуждения темы "почему параметры это круто"


 
evvcom ©   (2006-06-01 10:15) [13]


> Я перешел к динамическому формированию запросов с той точки
> зрения что кладешь в мемо sql.text и смотришь, что за байду
> наформировал.

Отлаживать запросы удобнее в стандартных для MSSQL Enterprise Manager или Query Analyzer, ИМХО. А уже отлаженный запрос с параметрами загонять на клиента. Если проблема в том, что надо узнать в рантайм какие значения для параметров передаются, можно в BeforeOpen поместить вызов диалога с текстом запроса и значениями параметров. Можно пойти и дальше. Написать наследника от используемого DataSet со свойством Debug (если такого наследника нет или не удастся найти), который и будет показывать этот диалог независимо от наличия обработчиков, но в зависимости от флага Debug.


 
ЮЮ ©   (2006-06-01 10:16) [14]


> и смотришь, что за байду наформировал.  Удобно при отладке.

Путаешь причину и следствие. Параметрический запрос имел бы один и тот же вид. Однажды отлаженный он бы оставался верным и смотреть на него не надо.

Наконец, с таким же успехом можно получить SQL.Text параметрического запроса. Заменить : на @, определить типы и знасения параметров и выволнить в QA. Хотя лучше делать наоборот. Добиться правильных результатов в QA, а затем переносить в код программы.


> - практика показала что параметры ещё и быстрее работает.
>  (А почему, мне туготдуму пока не осилить понятия "что в
> какой момент кешируется". А хотелось бы это понять..)


Запрос на сервер поступает ОДНОГО И ТОГО ЖЕ, только с РАЗНЫМИ ПАРАМЕТРАМИ, поэтому выполняется ОН ЖЕ, уже однажды разобранный сервером. В случае динамического формирования серверу передаются всякий раз разные запросы, которые он каждый раз заново разбирает.


 
paul_k ©   (2006-06-01 11:16) [15]

> [14] ЮЮ ©   (01.06.06 10:16)

Так как все делается через процедуры писал
try
 Query.ExecSql
except
 on e : exeption do begin
     write log(E.Message,Query.Sql.Text)
 end
Оченно удобно потом понимать что у юзера отвалилось и почему.
постоянно в процессе тестовой эксплуатации мониторить профайлером напрягает. Отсюда "любовь к динамике"
Опять же если создавать запрос полностью динамически то меньше букв надо писать.


 
paul_k ©   (2006-06-01 11:21) [16]

> [13] evvcom ©   (01.06.06 10:15)


> Отлаживать запросы удобнее в стандартных для MSSQL Enterprise
> Manager или Query Analyzer, ИМХО.

Абсолютно согласен.
Но вот как поведет себя процедура с различными наборами прав юзера зачастую вылазит только в процессе эксплуатации. может что-то в концерватории у меня править надо?
и как применить тогда BeforeOpen  после возникновения ошибки?
писать в лог список параметров ещё раз?


 
sniknik ©   (2006-06-01 11:51) [17]

paul_k ©   (01.06.06 09:45) [12]
> а Вы ТЗ мое читали?
а зачем? я вижу использовался запрос (представлен в [0]), политика партии и ТЗ сочли приемлемым и его и метод, после по ходу обсуждения он переделывается в процедуру, и начинаются выяснения как ее лучше выполнять...

ну так вот такому простому запросу в процедуре не место! (кстати и тогда сказал и сейчас повторю. ИМХО. не согласен скажи свое)
обьясню почему не место. если бы у тебя был обший метод выполнения (одни и теже данные ложатся), а вот месторасположение/логика предобработки данных могло отличатся, вот тут без процедуры не обойтись (если по хорошему), тогда ты бы мог без перекомпиляции программы логикой процедуры менять поведение вставки, что и куда ложить, при смене места/прав/т.д.
у тебя же (один представленный запрос без экивоков на ТЗ), запрос простейший без какогото логического ветвления, ссылок на права, ложится все в одно неменяемое место, а вот способы вызова меняются (в программе имею ввиду). т.е. при изменениях их, мало того перекомпиляция программы требуется но еще и правка запроса(/сов т.к. одним не обойдешся раз уж начал)... намеренно создаем себе сложности...

> А разве это не выходит за рамки обсуждения темы "почему параметры это круто"
параметры это не круто, это стандартизированный способ обмена данными. а вот процедуры вставляют зачастую из какихто абстрактных понятий о крутизне/х.з. еще от чего незнания, дурости, т.д..


 
evvcom ©   (2006-06-01 11:56) [18]


> Опять же если создавать запрос полностью динамически то
> меньше букв надо писать.

Несогласен. Запрос, написанный в designtime с параметрами, весит меньше. При этом он более нагладен, удобочитаем и пр.

> и как применить тогда BeforeOpen  после возникновения ошибки?
> писать в лог список параметров ещё раз?

Удобнее написать наследника и использовать его. В наследнике реализовать запись в лог. Тогда в пользовательском коде уже не надо будет даже try except использовать. И... в except все же после записи в лог пользователю надо бы сообщить об ошибке, т.е. raise.


 
MsGuns ©   (2006-06-01 12:04) [19]

>paul_k ©   (01.06.06 09:45) [12]
>Со всем уважением, молодой человек, а Вы ТЗ мое читали? С политикой партии установленной здесь знакомы? Или от того тестового кусочка отталкиваетесь?

Этот "молодой человек", "все уважение" к которому прямо-таки торчит из Вашего поста, один из самых реально крутых Мастеров на этом сайте в области ADO+MS SQL. И говорит он совершенно правильно. Вместо того, чтобы корректно объяснить ему (и не только ему) причины создания подобных ХП, Вы вежливо хамите.


 
saxon   (2006-06-01 12:05) [20]


> процедуры вставляют зачастую из какихто абстрактных понятий
> о крутизне/х.з. еще от чего незнания, дурости, т.д..

Однако можно заметить еще и такие факторы:
- Единый подход.
- Всетаки с процедурой выполняеться немного быстрее (не всегда но в общем случае).
- При разработке программы которая может работать с разными SQL серверами. (Писали такую программу, для Access, SQL Server. Не спрашивайте почему именно такой набор - заказчик так возжелал :). Через процедуры оказалось надежнее и быстрее и ...)
- ...


 
sniknik ©   (2006-06-01 12:06) [21]

запись а лог полных запросов тоже не нужна...
вернее она конечно нужна, на уровне тестрования, в рабочем варианте это только тормоз. а тестить можно различными вариантами, тем же profiler-ом, получиш все как есть хоть используя параметры хоть нет, запись лога там есть. или (если нужен клиентский поток запросов) переподключаеш программу по ODBC DSN в котором настраиваеш логирование, опять независимо от параметров... после отладки естественно переключать на OLE DB провадера.
(опять сложностей себе ишем... стандартные средства видимо не подходят, свое создаем, дополнительных глюков в программу тащим (парадокс, для выявления глюков вставляем глюки... ;о)))


 
paul_k ©   (2006-06-01 12:55) [22]

> [19] MsGuns ©   (01.06.06 12:04)

Простите за отклонение от темы

Извините, разве это хамство?
Если на просьбу разъяснить почему это работает так а не иначе


> Собственно вопрос - в чем грабли себе закопал?

получаю отыdет вида

> вот так и возникают перекосы сознания... на один простейший
> инсерт процедуру???

- то не важно кем является сей молодой человек.

> Вместо того, чтобы корректно объяснить ему (и не только
> ему) причины создания подобных ХП,

ВНИМАНИЕ ПОВТОРЮ ВОПРОС ИЗНАЧАЛЬНЫЙ
Ошибка возникла  вот в этом месте

> "/link/\"http://vymp.ru\"",

потом ткнув пальцем в небо удалил из строки двойные кавычки
"/link/\http://vymp.ru\"
Ошибки нет
ВОПРОС - ПОЧЕМУ , в чем грабли?

Вариант первый - двоеточие интерпритируется как параметр.
непонятно тогда почему в строке
"/link/\http://vymp.ru\" они не интерпритируются а в строке  
"/link/\"http://vymp.ru\"" - интерпритируются.
Вот об этом собственно и спич.
А не о том почему я использую тот или иной способ обращения к базе.


 
sniknik ©   (2006-06-01 13:41) [23]

понятно "отвечайте точно, и по сушеству, не обращая внимания на то, что несу бред", вот как это называется.

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


 
paul_k ©   (2006-06-01 14:36) [24]

> чего же тут непонятного? парсер так работает, не различает

Спасибо, уяснил, учту.

А теперь перейдем к

> понятно "отвечайте точно, и по сушеству, не обращая внимания
> на то, что несу бред", вот как это называется.


Есть стандартный процесс, проверяющий имеет ли пользователь доступ к типу документа, экземпляру документа имеет ли он право на создание этого типа документа и так далее.
Есть "политика партии" запрещающая пользователю все, кроме исполнения ХП.

Вы уверены, что обойтись можно без ХП?
Вы уверены, что для илюстрации непонятной мне "работы парсера", необходимо все это приводить в посте? Или достаточно краткой илюстрации "граблей"?


 
sniknik ©   (2006-06-01 16:33) [25]

> Есть "политика партии" запрещающая пользователю все, кроме исполнения ХП.
это ты сейчас придумал? в [0] партия запросы не запрещала. ответы ориентированы на то что озвучено и приведено, а не на подумано и изменено.

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

> Вы уверены, что для илюстрации непонятной мне "работы парсера", необходимо все это приводить в посте? Или
> достаточно краткой илюстрации "граблей"?
что все? непонял фразу совершенно. вообще, отвечающим в основном непонятно, что именно непонятно спрашивающим...  поэтому без гаданий отвечают на прямо поставленные вопросы, вопрос про парсер прозвучал в [22] ответ в [23]. кто ж знал до этого, что интересует именно его работа, а не как избавиться/правильно т.е. "грабли" кода в [0]? на что кстати ответ был в [1], заменил на параметры, все, нет "граблей".
или у тебя другой "перевод" фразы
> Собственно вопрос - в чем грабли себе закопал?
?


 
paul_k ©   (2006-06-01 16:54) [26]

> [25] sniknik ©   (01.06.06 16:33)

Ну ну.. много юзеру с логином SA и правами администратора.
Нормальные юзеры то под пабликом

> уже сказал, в этом случае, показаном, а не придуманном,
> не только можно но и нужно, он лишний.

А указать сразу то же что и в посте 23 религия не позволила. Надо обхамить, ветку снести сюда и так далее..

> вопрос про парсер прозвучал в [22]

Ае показалось в 0....

> с завидной регулярностью получаю
> Parameter object is improperly defined. Inconsistent or
> incomplete information was provided


> Текст запроса
> INSERT INTO tal_log_data(ip, log_date, log_time, metod,
> url, srv_resp, traf, referer, srv_name, br_full_str, br_type,
> br_version, site_name, file_ext)
> values(
> "72.36.182.34",
> convert(datetime,"30 Apr 2006",106),
> convert(datetime,"14:29:57",108),
> "GET",
> "/link/\"http://vymp.ru\"",



Но если Вы не внимательно читаете то может не стоит хотя бы делать далеко идущие выводы о способах разработки

Большое спасибо за абсолютно точный и абсолютно бесполезный ответ указанный в [23].


 
sniknik ©   (2006-06-01 18:43) [27]

> А указать сразу то же что и в посте 23 религия не позволила.
до [22] "немного" другая интерпретация вопроса, такая же, с которой ответили [1], [4] т.е. в этом я не оригинален. понял также, как и написано.

> Надо обхамить, ветку снести сюда и так далее..
ветку сюда снес не я... вродебы, не помню, но это неважно если бя увидел ветку в базах с таким названием то тоже снес бы.
хамства не вижу.

> ... не стоит хотя бы делать далеко идущие выводы о способах разработки
я еще и не то могу. н основании используемых TADOQuery для запросов, StringGrid-ов для данных, "красоты" кода...
но не стоит думаю. вообще обидишся.

> Большое спасибо за абсолютно точный и абсолютно бесполезный ответ указанный в [23].
вот. теперь он оказывается бесполезный, а зачем было его так добиваться? давали же решение без обьяснений (как знали) надо было им и удовольствоваться.


 
paul_k ©   (2006-06-02 15:39) [28]

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

Бесполезный, да потому что пришлось таки использовать нелюбимые параметры.



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

Форум: "Начинающим";
Текущий архив: 2006.06.18;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.56 MB
Время: 0.019 c
4-1142933233
StudentVNN
2006-03-21 12:27
2006.06.18
Неработает завершение сеанса ExitWindowsEx(EWX_LOGOFF, 0)


2-1148957631
verybadbug
2006-05-30 06:53
2006.06.18
загрузка данных в webbrowser


2-1149153692
novice
2006-06-01 13:21
2006.06.18
Как открыть форму?


1-1145037989
Wog
2006-04-14 22:06
2006.06.18
Кнопка произвольной формы


2-1149014525
Blari
2006-05-30 22:42
2006.06.18
Перетаскивание в ListBox





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский