Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

SQL запрос без раздела WHERE [D5, D7]


Страницы:   1 2

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] точно подойдет. Про Аксес не знаю.


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо