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

Вниз

SQL запрос без раздела WHERE   Найти похожие ветки 

 
stelius ©   (2005-06-09 15:15) [0]

Народ, подскажите где можно посмотреть алгоритм какого-нить SQL парсера.

Проблема следующая: на вход подаеться текст скуль запроса а на выходе должен быть этот запрос, но без разделов WHERE, ORDER BY, HAVING и пр. (проще говоря только разделы SELECT и FROM, остально отсечь)


 
Sergey13 ©   (2005-06-09 15:23) [1]

2stelius ©   (09.06.05 15:15)
На первый взгляд можно отсекать по последнему вхождению без скобок (подзапросы).


 
Anatoly Podgoretsky ©   (2005-06-09 15:29) [2]

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

Только как быть с JOIN ведь это по сути тоже самое что и Where


 
stud ©   (2005-06-09 15:47) [3]

а как подается запрос?
если запрос подавать в виде списка строк
select ....
from....
where ....

то можно удалять строку, которая содержит where


 
stelius ©   (2005-06-09 16:21) [4]

2stud ©   (09.06.05 15:47) [3]
Запрос подаеться как бог на душу положит =)
Чел может и построчно написать, может и в одну строку, а может еще как отфармотировать по своему разумению.. =(

Возможно я просто не там копаю...

Изначально задача - найти список полей которые возвращает запрос. Вот решил взять указанный скуль и выполнить его, но чтоб он данные не возвращал. Затем уж из кверика выдернуть список полей.


 
Johnmen ©   (2005-06-09 16:28) [5]

>stelius ©   (09.06.05 16:21) [4]

Список полей находится между SELECT и FROM.
:)


 
stelius ©   (2005-06-09 16:41) [6]

2Johnmen ©   (09.06.05 16:28) [5]
ценю твой юмор... а если указана звездочка?

Попутно вопрос...
Как можно посмотреть код, который выплняет UpdateSQL, при нажатии кнопки Get Table Fields в design time.


 
Danilka ©   (2005-06-09 16:52) [7]

[6] stelius ©   (09.06.05 16:41)
Какая СУБД?


 
Sergey13 ©   (2005-06-09 16:55) [8]

Если поддерживается запрос из запроса достаточно

select * from
(исходный запрос)
Where 1=0


 
Johnmen ©   (2005-06-09 16:59) [9]

>stelius ©   (09.06.05 16:41) [6]
>ценю твой юмор... а если указана звездочка?

Дык...:)
Я твой тоже заценил. По поводу типа СУБД.
:)))


 
stelius ©   (2005-06-09 17:05) [10]

2Danilka ©   (09.06.05 16:52) [7]
Oracle и Access


 
Anatoly Podgoretsky ©   (2005-06-09 17:06) [11]

Звезжчка означает все поля.
По другому список полей равен *


 
jack128 ©   (2005-06-09 17:14) [12]

Sergey13 ©   (09.06.05 16:55) [8]
Если поддерживается запрос из запроса достаточно


А если не поддерживает, то достаточно выполнить сам запрос.


 
Johnmen ©   (2005-06-09 17:17) [13]

>stelius ©   (09.06.05 17:05) [10]

Делай разбор того, что идёт посте FROM, с целью найти "хвост" этого перечисления. Ничего сложного здесь нет. Все случаи известны и поддаются однозначному парсированию. (а как же иначе? :))


 
MOA ©   (2005-06-09 17:18) [14]

DECLARE @P1 Integer, @Str nvarchar(2000)
SET @P1=-1
SET @Str= N"Текст Вашего запроса"
EXEC sp_prepare @P1 OUTPUT, NULL, @Str,1

Вернёт Вам пустой набор данных со всеми полями. Варианты понятны (например, не @Str, а :Par) Пусть поработает парсер сервера ;).
Удачи!


 
stelius ©   (2005-06-09 17:18) [15]

2Anatoly Podgoretsky ©   (09.06.05 17:06) [11]
да этт понятно... я ж это просто как один из примерог указал.
тут же куча вариантог:

select t1.*,
      t2.ID,
      t2.NAME
 from TABLE1 t1, TABLE2 t2
where t1.ID = t2.TABLE1_ID



select t1.ID,
      t1.NAME,
     (select count(*) from TABLE2 t2 where t2.TABLE1_ID = t1.ID ) TABLE2_COUNT
 from TABLE1 t1


и прочее...

ИМХО анализировать сие не многим проще (если вообще проще), чем анализировать структуру сложного запроса на предмет отсечения не нужных разделог (сие обсуждаеццо =) ).


 
Johnmen ©   (2005-06-09 17:21) [16]

>MOA ©   (09.06.05 17:18) [14]

Это так в Оракле ? Или в Аксессе ?

>stelius ©   (09.06.05 17:18) [15]

"Выполни запрос, Ксанф" ( почти по Эзопу :) )


 
MOA ©   (2005-06-09 17:22) [17]

А, чёрт! показалось, что речь про MSSQL. Прошу прощения - померещилось ;).


 
stelius ©   (2005-06-09 17:36) [18]

Я б с удовольствием его выполнил, ток шоб он, панимаешь, данные не возвращал. Мне ж токма список полей нужен...
Только вот какая фишка: с подзапросами все нормуль, када оракла, а вот акцец, лениться сие делать. Конечно можно просто добавить в раздел WHERE строку " and (1=0)", но здесь задача сводиться к вычленению из общего текста запроса этого самого раздела WHERE, этт собсно сабж.

Все таки подскажите что-нить на счет stelius ©   (09.06.05 16:41) [6].
Или где посмотреть код процедуры, которую выпольняет компонент TQuery когда указываешь "Add all fields" - он же решает подобную задачу.


 
ЮЮ ©   (2005-06-10 02:40) [19]

А не проще все-таки выполнить запрос, который чел написал именно с этой целью, а затем уж смотреть поля. Надеюсь твои манипуляции с полученным НД будут не "тяжелее", чем выполнение запроса.


 
Anatoly Podgoretsky ©   (2005-06-10 07:52) [20]

stelius ©   (09.06.05 17:18) [15]
Про то и речь, что анализ это не просто, а просто не возможен. Надо поступать как сказали - пустой запрос и коллекция полей у тебя на клиенте, вот его тоже не просто будет получить.
TQuery поступает просто - получает набор как есть, ничего не анализируя и не изменяя.


 
Sergey13 ©   (2005-06-10 09:20) [21]

2[10] stelius ©   (09.06.05 17:05)
>Oracle и Access
Для Оракла мой вариант в [8] точно подойдет. Про Аксес не знаю.


 
ЮЮ ©   (2005-06-10 09:45) [22]

>Sergey13 ©   (10.06.05 09:20) [21]

И что, типа внутренний подзапрос сервер выполнять не будет? Просто сходу выдаст требуемый набор полей? Как-то с трудом верится.


 
Danilka ©   (2005-06-10 09:57) [23]

Аццес понимает TOP?
если да, то можно добавить после первого слова "select" фразу " top 0 ", примерно так:
select top 0 * from ...

[22] ЮЮ ©   (10.06.05 09:45)
зачем вериьть/неверить, просто попробуй. :)
на самом деле, таки, да, не будет.


 
Anatoly Podgoretsky ©   (2005-06-10 10:04) [24]

Danilka ©   (10.06.05 09:57) [23]
Таки будет, только подкинь более сложный запрос, со сложным условием, без выполнения которого соединение просто не получится.
С неоптимальным планом, например like "%абракадабра%" и желательно во всех подуровнях. То есть когда результат получится только после линейного перебора каждого подзапроса.


 
Sergey13 ©   (2005-06-10 10:09) [25]

2[22] ЮЮ ©   (10.06.05 09:45)
>И что, типа внутренний подзапрос сервер выполнять не будет?
А где я это утверждал? Этого в вопросе не было. Запрос без where тоже будет выполняться, только записей вернет несколько больше. 8-)
Мой вариант не вернет ничего - только набор полей.


 
Danilka ©   (2005-06-10 10:15) [26]

[24] Anatoly Podgoretsky ©   (10.06.05 10:04)
Есть такой. Вьюха весом в 10 килобайт, отрабатывает 23 секунды, куча соединений с запросами/вьюхами, есть подзапросы.
Сделал селект с условием 1=0 - отработала за 0.00 секунд. :)

Под МССкулем, есть большая таблица, сделал запрос с условием "%абракадабра%" отработала за 5 секунд, добавил TOP 0 - открылась моментом.
Правда, под МССкулем у меня здесь ничего серьездного, в смысле, больших замороченых запросов нет.


 
Sergey13 ©   (2005-06-10 10:24) [27]

Вообще забавно.
Запрос
select * from (select * from Table_name) where 1=0
Выполняется за 0.00 секунд. Но в плане все равно фултаблескан как и у отдельно внутреннего подзапроса. 8-)
(Оракл 8.1.7)


 
Danilka ©   (2005-06-10 10:32) [28]

[27] Sergey13 ©   (10.06.05 10:24)
угу.
я думаю - он сначала план строит, а затем, с самого высокого уровня проверяет условия - если какое-то ложное, то сам запрос уже не отрабатывает.
у меня, кстати, тоже 8.1.7


 
jack128 ©   (2005-06-10 12:18) [29]

stelius ©   (09.06.05 17:36) [18]
Я б с удовольствием его выполнил, ток шоб он, панимаешь, данные не возвращал.


а какая тебе разница возвращает запрос данные или нет?? Если ты беспокоешься о временных затратах на фетч, то те должно помочь свойство CursorLocation


 
Seg   (2005-06-10 12:25) [30]

Надо выполнить запрос, а потом в DataSet пройтись по полям. Кроме количества полей можно вытащить еще и названия этих полей.


 
Danilka ©   (2005-06-10 12:43) [31]

[29] jack128 ©   (10.06.05 12:18)
Запрос может быть очень ресурсоемким. Неохота сервер перегружать, а клиента заставлять ждать, когда нужен всего-лишь список полей.


 
stelius ©   (2005-06-10 13:33) [32]

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
Вариант с подзапросом отпадает, так как акцесс лениться это делать.


 
Anatoly Podgoretsky ©   (2005-06-10 13:51) [33]

Плохо знаешь и справку презираешь
Предикаты ALL, DISTINCT, DISTINCTROW, TOP
Позволяют отобрать записи среди выбранных с помощью запроса на языке SQL.


 
Danilka ©   (2005-06-10 13:53) [34]

[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".
Это упрощенно, могут быть какие-то нюансы. А может быть и нет нюансов. :))


 
Danilka ©   (2005-06-10 13:57) [35]

[33] Anatoly Podgoretsky ©   (10.06.05 13:51)
угу, мне тоже странным показалось его отсутствие, проверил - есть. но из самого аццесса запрос с top 0 - ругается.
Из дельфей ломиться в базу аццессовскую не пробовал, но, наверное, тоже будет ругаться.


 
evvcom ©   (2005-06-10 14:19) [36]

А чего вы паритесь? Просто все условие в WHERE поменять на ложное независимо от того, есть в нем связки таблиц или нет. Причем во всех WHERE (если с подзапросами).


 
Danilka ©   (2005-06-10 15:06) [37]

[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%"))


 
Danilka ©   (2005-06-10 15:08) [38]

[36] evvcom ©   (10.06.05 14:19)
а вот мой вариант, предложеный в [35], должен справицца и правильно отработать. :))


 
Seg   (2005-06-10 17:21) [39]

А может подставить в конце запроса
rownum=1
и не парицца?


 
stelius ©   (2005-06-12 13:15) [40]

Во чего я нашел...
чтоб список фиелдог получить все оказываеццо проще =)
у компонента TQuery есть список FieldDefs, который достаточно обновить без открывания квери (Query1.FieldDefs.Update).

а для IBQuery еще проще, делаешь ему Prepare и список полей уже загужен.



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

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

Наверх




Память: 0.58 MB
Время: 0.044 c
1-1120737371
-ViLLaIN-
2005-07-07 15:56
2005.07.25
Программа и Диспечер задач


14-1120079587
Константинов
2005-06-30 01:13
2005.07.25
Вопрос Москвичам


14-1120394716
Gear
2005-07-03 16:45
2005.07.25
Как программно установить драйвер из inf-файла?


1-1120549448
Бу
2005-07-05 11:44
2005.07.25
проблема С Drawgrid


4-1117194360
Masta Hookah
2005-05-27 15:46
2005.07.25
Replace Tray System Clock