Форум: "Базы";
Текущий архив: 2005.07.25;
Скачать: [xml.tar.bz2];
Вниз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;
Скачать: [xml.tar.bz2];
Память: 0.56 MB
Время: 0.012 c