![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
SQL запрос без раздела WHERE [D5, D7]
stelius © (2005-06-09 15:15:00)Народ, подскажите где можно посмотреть алгоритм какого-нить SQL парсера.
Проблема следующая: на вход подаеться текст скуль запроса а на выходе должен быть этот запрос, но без разделов WHERE, ORDER BY, HAVING и пр. (проще говоря только разделы SELECT и FROM, остально отсечь)
stelius (2005-06-12 13:15:00) [1]Во чего я нашел...
чтоб список фиелдог получить все оказываеццо проще =)
у компонента TQuery есть список FieldDefs, который достаточно обновить без открывания квери (Query1.FieldDefs.Update).
а для IBQuery еще проще, делаешь ему Prepare и список полей уже загужен.
Seg (2005-06-10 17:21:00) [2]А может подставить в конце запроса
rownum=1
и не парицца?
Danilka (2005-06-10 15:08:00) [3][36] evvcom © (10.06.05 14:19)
а вот мой вариант, предложеный в [35], должен справицца и правильно отработать. :))
Danilka (2005-06-10 15:06:00) [4][36] evvcom © (10.06.05 14:19)
давай, напиши функцию, которая это сделает и правильно отработает, например на этом запросе (далеко не самый замороченый, просто подобрал такой, который влезет в один пост) (писал не я, но работает у нас в конторе :)):
SELECT
ddd.doc,
ddd.firm,
ddd.doc_class,
ddd.doc_move_type,
ddd.doc_no,
ddd.doc_state,
ddd.doc_date,
ddd.doc_note,
ddd.registration_date,
taxation,
department,
(SELECT department_code FROM department WHERE department = ddd.department) department_code,
begin_date,
business_transaction,
doc_amount,
currency,
currency_date,
amount,
vat_amount,
cont,
DOC_CLASS$.doc_class_name,
DOC_STATE$.doc_state_name,
doc_payment_invoice,
doc_hack,
nvl(doc_amount,0)-nvl(doc_payment_invoice,0) + nvl(doc_hack,0) doc_rest,
lead_doc_contract,
gc.doc_class lead_doc_class_contract,
(SELECT doc_class_name FROM doc_class WHERE doc_class = gc.doc_class) lead_doc_class_name_contract,
gc.doc_no lead_doc_no_contract,
gc.doc_date lead_doc_date_contract,
bik,
rs,
lead_doc_invoice,
gi.doc_class lead_doc_class_invoice,
(SELECT doc_class_name FROM doc_class WHERE doc_class = gi.doc_class) lead_doc_class_name_invoice,
gi.doc_no lead_doc_no_invoice,
gi.doc_date lead_doc_date_invoice,
gi.doc_move_type lead_doc_move_type_invoice
FROM
doc_general gc,
doc_general gi,
(
SELECT
dd.doc,
firm,
doc_class,
doc_move_type,
doc_no,
doc_state,
doc_date,
doc_note,
registration_date,
taxation,
department,
dd.begin_date,
business_transaction,
doc_amount,
currency,
currency_date,
dd.amount,
vat_amount,
dd.cont,
dp.paid_amount doc_payment_invoice,
bik,
rs,
dp.adjust_amount doc_hack,
(SELECT l.lead_doc
FROM doc_link l, contract_general c
WHERE l.lead_doc = c.doc
AND NVL(c.contract_type,100) != 104
AND l.driven_doc = dd.doc) lead_doc_contract,
(SELECT l.lead_doc
FROM doc_link l, doc_association a
WHERE l.driven_doc = dd.doc
AND l.doc_association = a.doc_association
AND a.lead_doc_class IN (906, 1007)) lead_doc_invoice
FROM(
SELECT
DG$.doc,
DG$.firm,
DG$.doc_class,
DG$.doc_move_type,
DG$.doc_no,
DG$.doc_state,
DG$.doc_date,
DG$.doc_note,
DG$.registration_date,
DA$.taxation,
DA$.department,
DA$.begin_date,
DA$.business_transaction,
DA$.doc_amount,
DA$.currency,
DA$.currency_date,
DA$.amount,
BANK_PAYMENT$.vat_amount,
BANK_PAYMENT$.cont,
BANK_PAYMENT$.recipient_bank bik,
BANK_PAYMENT$.recipient_rs rs
FROM
vd$doc_general DG$,
doc_accounting DA$,
bank_payment BANK_PAYMENT$
WHERE DA$.doc = DG$.doc
AND BANK_PAYMENT$.doc = DG$.doc
AND DG$.doc_state = (SELECT DOC$ACC.get_ds_accept FROM DUAL)
AND DG$.doc_class = 950
UNION ALL
SELECT
DG$.doc,
DG$.firm,
DG$.doc_class,
DG$.doc_move_type,
DG$.doc_no,
DG$.doc_state,
DG$.doc_date,
DG$.doc_note,
DG$.registration_date,
DA$.taxation,
DA$.department,
DA$.begin_date,
DA$.business_transaction,
DA$.doc_amount,
DA$.currency,
DA$.currency_date,
DA$.amount,
CASH_ORDER$.vat_amount,
CASH_ORDER_CLIENT$.cont,
NULL bik,
NULL rs
FROM
vd$doc_general DG$,
doc_accounting DA$,
cash_order CASH_ORDER$,
cash_order_client CASH_ORDER_CLIENT$
WHERE DA$.doc = DG$.doc
AND CASH_ORDER$.doc = DG$.doc
AND CASH_ORDER_CLIENT$.doc = CASH_ORDER$.doc
AND DG$.doc_state = (SELECT DOC$ACC.get_ds_accept FROM DUAL)
AND DG$.doc_class = 907
UNION ALL
SELECT
DG$.doc,
DG$.firm,
DG$.doc_class,
DG$.doc_move_type,
DG$.doc_no,
DG$.doc_state,
DG$.doc_date,
DG$.doc_note,
DG$.registration_date,
DA$.taxation,
DA$.department,
DA$.begin_date,
DA$.business_transaction,
DA$.doc_amount,
DA$.currency,
DA$.currency_date,
DA$.amount,
0 vat_amount,
decode(doc_move_type, 0, SECURITIES_RD_ACT$.buyer, SECURITIES_RD_ACT$.seller) cont,
NULL bik,
NULL rs
FROM
vd$doc_general DG$,
doc_accounting DA$,
securities_rd_act SECURITIES_RD_ACT$
WHERE DA$.doc = DG$.doc
AND SECURITIES_RD_ACT$.doc = DG$.doc
AND DG$.doc_state = (SELECT DOC$ACC.get_ds_accept FROM DUAL)
AND DG$.doc_class = 911
)dd, doc_payment dp
WHERE dd.doc = dp.doc
)ddd,
doc_class DOC_CLASS$,
doc_state DOC_STATE$
WHERE ddd.lead_doc_contract = gc.doc(+) and
ddd.lead_doc_invoice = gi.doc(+) and
--ddd.doc = c.driven_doc(+) and
--ddd.doc = i.driven_doc(+) and
DOC_CLASS$.doc_class = ddd.doc_class and
DOC_STATE$.doc_state = ddd.doc_state and
EXISTS(SELECT 1
FROM V_DOC_ENTRY e
WHERE e.DOC = ddd.doc and
(e.NBR_DEBIT LIKE '60%' OR e.NBR_CREDIT LIKE '60%' OR
e.NBR_DEBIT LIKE '62%' OR e.NBR_CREDIT LIKE '62%'))
evvcom (2005-06-10 14:19:00) [5]А чего вы паритесь? Просто все условие в WHERE поменять на ложное независимо от того, есть в нем связки таблиц или нет. Причем во всех WHERE (если с подзапросами).
Danilka (2005-06-10 13:57:00) [6][33] Anatoly Podgoretsky © (10.06.05 13:51)
угу, мне тоже странным показалось его отсутствие, проверил - есть. но из самого аццесса запрос с top 0 - ругается.
Из дельфей ломиться в базу аццессовскую не пробовал, но, наверное, тоже будет ругаться.
Danilka (2005-06-10 13:53:00) [7][32] stelius © (10.06.05 13:33)
> На сколько знаю функции TOP или ее аналога в аксессе нет.
Вообще-то есть. Не поленился, сейчас проверил.
Однако, TOP 0 не проходит, в отличии от MSSQL, ругается, минимум TOP 1 :((
так что, вариант с топом не подойдет.
Тогда, думаю, прокатит такой алгоритм:
Просто читать запрос с конца, до тех пор, пока не встретится WHERE, AND или FROM. При этом, если встречается закрывающая скобка (какой-то подзапрос, или условие в скобке), то читать не анализируя до открытия этой скобки.
Как только встретился WHERE или AND - поиски прекращаем и добавляем в конец запроса строку "and 1=0"
Если встретился FROM, то добавляем в конец запроса "where 1=0".
Это упрощенно, могут быть какие-то нюансы. А может быть и нет нюансов. :))
Anatoly Podgoretsky (2005-06-10 13:51:00) [8]Плохо знаешь и справку презираешь
Предикаты ALL, DISTINCT, DISTINCTROW, TOP
Позволяют отобрать записи среди выбранных с помощью запроса на языке SQL.
stelius (2005-06-10 13:33:00) [9]2Anatoly Podgoretsky © (10.06.05 07:52) [20]
>Про то и речь, что анализ это не просто, а просто не возможен.
SQL парсер на сервере запрос же как-то анализирует... Или там принципиально другой анализ?
2Danilka © (10.06.05 09:57) [23]
На сколько знаю функции TOP или ее аналога в аксессе нет.
Sergey13 © (10.06.05 10:09) [25]
>Запрос без where тоже будет выполняться,
>только записей вернет несколько больше.
Я ж его не сразу выполнять буду, я ему свой WHERE припишу аля 1=0 :)
2All
Вариант с подзапросом отпадает, так как акцесс лениться это делать.
Danilka (2005-06-10 12:43:00) [10][29] jack128 © (10.06.05 12:18)
Запрос может быть очень ресурсоемким. Неохота сервер перегружать, а клиента заставлять ждать, когда нужен всего-лишь список полей.
Seg (2005-06-10 12:25:00) [11]Надо выполнить запрос, а потом в DataSet пройтись по полям. Кроме количества полей можно вытащить еще и названия этих полей.
jack128 (2005-06-10 12:18:00) [12]stelius © (09.06.05 17:36) [18]
Я б с удовольствием его выполнил, ток шоб он, панимаешь, данные не возвращал.
а какая тебе разница возвращает запрос данные или нет?? Если ты беспокоешься о временных затратах на фетч, то те должно помочь свойство CursorLocation
Danilka (2005-06-10 10:32:00) [13][27] Sergey13 © (10.06.05 10:24)
угу.
я думаю - он сначала план строит, а затем, с самого высокого уровня проверяет условия - если какое-то ложное, то сам запрос уже не отрабатывает.
у меня, кстати, тоже 8.1.7
Sergey13 (2005-06-10 10:24:00) [14]Вообще забавно.
Запрос
select * from (select * from Table_name) where 1=0
Выполняется за 0.00 секунд. Но в плане все равно фултаблескан как и у отдельно внутреннего подзапроса. 8-)
(Оракл 8.1.7)
Danilka (2005-06-10 10:15:00) [15][24] Anatoly Podgoretsky © (10.06.05 10:04)
Есть такой. Вьюха весом в 10 килобайт, отрабатывает 23 секунды, куча соединений с запросами/вьюхами, есть подзапросы.
Сделал селект с условием 1=0 - отработала за 0.00 секунд. :)
Под МССкулем, есть большая таблица, сделал запрос с условием '%абракадабра%' отработала за 5 секунд, добавил TOP 0 - открылась моментом.
Правда, под МССкулем у меня здесь ничего серьездного, в смысле, больших замороченых запросов нет.
Sergey13 (2005-06-10 10:09:00) [16]2[22] ЮЮ © (10.06.05 09:45)
>И что, типа внутренний подзапрос сервер выполнять не будет?
А где я это утверждал? Этого в вопросе не было. Запрос без where тоже будет выполняться, только записей вернет несколько больше. 8-)
Мой вариант не вернет ничего - только набор полей.
Anatoly Podgoretsky (2005-06-10 10:04:00) [17]Danilka © (10.06.05 09:57) [23]
Таки будет, только подкинь более сложный запрос, со сложным условием, без выполнения которого соединение просто не получится.
С неоптимальным планом, например like '%абракадабра%' и желательно во всех подуровнях. То есть когда результат получится только после линейного перебора каждого подзапроса.
Danilka (2005-06-10 09:57:00) [18]Аццес понимает TOP?
если да, то можно добавить после первого слова "select" фразу " top 0 ", примерно так:
select top 0 * from ...
[22] ЮЮ © (10.06.05 09:45)
зачем вериьть/неверить, просто попробуй. :)
на самом деле, таки, да, не будет.
ЮЮ (2005-06-10 09:45:00) [19]>Sergey13 © (10.06.05 09:20) [21]
И что, типа внутренний подзапрос сервер выполнять не будет? Просто сходу выдаст требуемый набор полей? Как-то с трудом верится.
Sergey13 (2005-06-10 09:20:00) [20]2[10] stelius © (09.06.05 17:05)
>Oracle и Access
Для Оракла мой вариант в [8] точно подойдет. Про Аксес не знаю.