Regex: включает ли оператор SQL предложение WHERE? - PullRequest
1 голос
/ 15 сентября 2010

Мне нужно регулярное выражение, которое будет определять, есть ли у данного оператора SQL предложение WHERE. Моя проблема заключается в том, что переданные операторы SQL, скорее всего, будут сложными, поэтому я не могу полагаться только на существование слова WHERE в выражении.

Например, это должно соответствовать

SELECT Contacts.ID
     , CASE WHEN (Contacts.Firstname IS NULL) THEN ''
            ELSE CAST(Contacts.Firstname AS varchar)
       END AS Firstname
     , CASE WHEN (Contacts.Lastname IS NULL) THEN ''
            ELSE CAST(Contacts.Lastname AS varchar)
       END AS Lastname
     , CASE WHEN (tbl_ContactExtras.Prequalified=-1 OR
                  tbl_ContactExtras.Prequalified IS NULL) THEN ''
            WHEN tbl_ContactExtras.Prequalified=0 THEN 'No'
            WHEN tbl_ContactExtras.Prequalified=1 THEN 'Yes - Other'
            WHEN tbl_ContactExtras.Prequalified=2 THEN 'Yes'
            ELSE CAST(tbl_ContactExtras.Prequalified AS varchar)
       END AS Prequalified
FROM contacts
LEFT JOIN tbl_ContactExtras
ON tbl_ContactExtras.ContactID = Contacts.ID
WHERE (Contacts.Firstname LIKE 'Bob%')

и это не должно совпадать:

SELECT Contacts.ID
     , CASE WHEN (Contacts.Firstname IS NULL) THEN ''
            ELSE CAST(Contacts.Firstname AS varchar)
       END AS Firstname
     , CASE WHEN (Contacts.Lastname IS NULL) THEN ''
            ELSE CAST(Contacts.Lastname AS varchar)
       END AS Lastname
     , CASE WHEN (tbl_ContactExtras.Prequalified=-1 OR
                  tbl_ContactExtras.Prequalified IS NULL) THEN ''
            WHEN tbl_ContactExtras.Prequalified=0 THEN 'No'
            WHEN tbl_ContactExtras.Prequalified=1 THEN 'Yes - Other'
            WHEN tbl_ContactExtras.Prequalified=2 THEN 'Yes'
            ELSE CAST(tbl_ContactExtras.Prequalified AS varchar)
       END AS Prequalified
FROM contacts
LEFT JOIN tbl_ContactExtras
ON tbl_ContactExtras.ContactID = Contacts.ID

Это примеры некоторых более простых утверждений: в утверждении может быть до 30 CASE утверждений, или оно может вообще не содержать.

Мне нужно программно добавить WHERE параметры, но чтобы сделать это правильно, необходимо знать, присутствует ли уже предложение WHERE.

Есть идеи о регулярном выражении, которые бы сработали для этого? Если нет, то есть еще какие-нибудь идеи о том, как отличить их друг от друга?

Спасибо

Ответы [ 5 ]

2 голосов
/ 15 сентября 2010

Это невозможно, поскольку предложение WHERE может быть произвольно вложено в предложение FROM.

1 голос
/ 15 сентября 2010

Это может не охватить всех случаев, но вы можете обнаружить, что вы можете поймать большинство из них, просто найдя в выражении последний from и последний where.

ifwhere следует после from, тогда у него есть предложение where.Если where предшествует from (или нет where вообще), тогда не существует никакого предложения where.

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

Например, я работал над проектом до того, как тот проанализировал SQL, и мы обнаружили, что он не обрабатывает такие вещи, как between:

where recdate between '2010-01-01' and '2010-12-31'

Вместо того, чтобы тратить кучу денег на устранение проблемы (и, вероятно, вносить ошибки в пути), мы просто опубликовали это как ограничение и сказали всем, что они должны изменить его на:

where recdate >= '2010-01-01'
  and recdate <= '2010-12-31'

Проблема решена.Хотя хорошо, чтобы клиенты были довольны, вам не нужно обслуживать каждый каприз: -)

Кроме этого, вам нужен анализатор SQL, а SQL - не красивый язык для разбора, поверьте мне.

0 голосов
/ 17 сентября 2010

Какую проблему вы пытаетесь решить?Вы пытаетесь определить, безопасно ли добавлять ограничения к этим существующим запросам?

Например, если у вас есть этот запрос

...
where foo = 'bar'

, то вы знаете, что безопасно добавить

and bat = 'quux'

но если у вас нет предложения WHERE, вы должны сделать это как

where bat = 'quux'

Это та проблема, которую вы пытаетесь решить?Если да, можете ли вы сделать каждый SQL-запрос, с которым вы работаете, предложением WHERE, добавив «WHERE 0 = 0» к тем запросам, у которых его нет?Затем на этапе после обработки вы узнаете, что в каждом запросе он уже есть.

Конечно, это всего лишь предположение.Ваш вопрос звучал так, что это может быть более серьезной проблемой.

0 голосов
/ 15 сентября 2010

Regex не предназначен для этого. Для правильного синтаксического анализа SQL требуются соответствующие сбалансированные скобки (и другие совпадающие пары, такие как кавычки), для чего используется регулярное выражение , а не (а чистое регулярное выражение даже не оборудовано; PCRE может, но не очень красиво)

Вместо этого просто напишите базовый конечный автомат или что-то для его анализа.

0 голосов
/ 15 сентября 2010

Все ли объединения одинаковы? Если это так, вы можете найти индекс всего или части оператора FROM (возможно, с помощью регулярного выражения, допускающего небольшие различия в синтаксисе и пробеле), а затем искать вхождение слова WHERE после этого индекса.

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

...