Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 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.57 MB
Время: 0.012 c
6-1113740754
Alpine
2005-04-17 16:25
2005.07.25
Работа с Модемом.


14-1120431235
TStas
2005-07-04 02:53
2005.07.25
КАк создавать файлы помощи? (ссылки)


3-1118428253
Andy Nortsov
2005-06-10 22:30
2005.07.25
импорт данных из Excel в Firebird


3-1118525726
Erich
2005-06-12 01:35
2005.07.25
Ошибка при получении значения генератора


1-1118160195
Дмитрий_05
2005-06-07 20:03
2005.07.25
Изменение размера формы мышкой





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