Регулярное выражение для соответствия общему синтаксису SQL?
На прошлой неделе я писал несколько модульных тестов для фрагмента кода, который генерировал некоторые операторы SQL.
Я пытался найти регулярное выражение для соответствия синтаксису SELECT,INSERT и UPDATE, чтобы я мог проверить, что мои методы генерировали правильный SQL, и после 3-4 часов поиска и работы с различными редакторами регулярных выражений я отказался.
Мне удалось получить частичные совпадения, но поскольку раздел в кавычках может содержать любые символы, он быстро расширяется, чтобы соответствовать всему описанию.
Буду признателен за любую помощь, я не очень хорошо с регулярными выражениями, но я хотел бы узнать о них больше.
Кстати, это C# регулярное выражение, что я после.
осветление
Мне не нужен доступ к базе данных, так как это часть модульного теста, и мне не нужно поддерживать базу данных для тестирования моего кода. который может жить дольше, чем проект.
13 ответов
Регулярные выражения могут соответствовать языкам, которые может анализировать только конечный автомат, что очень ограничено, тогда как SQL является синтаксисом. Можно продемонстрировать, что вы не можете проверять SQL с помощью регулярных выражений. Итак, вы можете перестать пытаться.
SQL - это грамматика типа 2, она слишком мощная, чтобы ее можно было описать с помощью регулярных выражений. Это так же, как если бы вы решили сгенерировать код на C#, а затем проверить его, не вызывая компилятор. Движок базы данных в целом слишком сложен, чтобы его можно было легко заглушить.
Тем не менее, вы можете попробовать грамматики SQL ANTLR.
У меня была та же проблема - подход, который работал бы для всех более стандартных операторов SQL, состоял бы в том, чтобы раскрутить базу данных Sqlite в памяти и выполнить запрос к ней, если вы получите ошибку "таблица не существует", то Ваш запрос проанализирован правильно.
Насколько я знаю, это выходит за рамки регулярных выражений, и вы приближаетесь к темному искусству BnF и компиляторов.
То же самое происходит с людьми, которые хотят делать правильную подсветку синтаксиса. Вы начинаете втискивать вещи в регулярные выражения, а затем заканчиваете тем, что пишете компилятор...
Сверху головы: не могли бы вы передать сгенерированный SQL в базу данных, использовать для них EXPLAIN и перехватить какие-либо исключения, которые бы указывали на плохо сформированный SQL?
Чтобы проверить запросы, просто запустите их с помощью команды SET NOEXEC ON, как это делает Entreprise Manager, когда вы анализируете запрос, не выполняя его.
Кроме того, если вы используете регулярное выражение для проверки SQL-запросов, вы можете быть почти уверены, что пропустите некоторые угловые случаи или что запрос недействителен по другим причинам, даже если он синтаксически правильный.
Я не думаю, что вам даже нужно создавать схему, чтобы можно было проверить утверждение, потому что система не будет пытаться разрешить имя_объекта и т. Д., Пока не выполнит успешный анализ оператора.
На примере Oracle вы наверняка получите ошибку, если сделаете следующее:
select * from non_existant_table;
В этом случае "ORA-00942: таблица или представление не существует".
Однако если вы выполните:
select * frm non_existant_table;
Затем вы получите синтаксическую ошибку "ORA-00923: ключевое слово FROM не найдено там, где ожидается".
Должна быть возможность классифицировать ошибки на ошибки синтаксического анализа, которые указывают на неправильный синтаксис и ошибки, связанные с именами и разрешениями таблиц и т. Д.
Добавьте к этому проблему разных СУБД и даже разных версий, допускающих разные синтаксисы, и я думаю, что для этой задачи вам действительно нужно обратиться к движку db.
Вы пробовали ленивые селекторы. Вместо того, чтобы соответствовать как можно большему, они совпадают как можно меньше, что, вероятно, то, что вам нужно для цитат.
Лучший способ - это проверить параметры, используемые для создания запроса, а не сам запрос. Функция, которая получает переменные, может проверять длину строк, допустимые числа, действительные электронные письма или что-то еще. Вы можете использовать регулярные выражения для выполнения этой проверки.
Есть грамматики ANTLR для разбора SQL. Это действительно лучшая идея использовать базу данных в памяти или очень легкую базу данных, такую как sqlite. Мне кажется расточительным проверять, является ли SQL действительным с точки зрения синтаксического анализа, и гораздо более полезным проверять имена таблиц и столбцов, а также особенности вашего запроса.
Я предлагаю создать базу данных с той же схемой, возможно, с использованием встроенного движка SQL, и передать ей SQL.
Я предполагаю, что вы сделали что-то вроде ".*", Попробуйте вместо "[^"]*", что не даст вам съесть всю строку. Это все равно даст ложные срабатывания в тех случаях, когда у вас есть \" внутри ваших строк.
public bool IsValid(string sql)
{
string pattern = @"SELECT\s.*FROM\s.*WHERE\s.*";
Regex rgx = new Regex(pattern, RegexOptions.IgnoreCase);
return rgx.IsMatch(sql);
}