Разделенные операторы SQL - PullRequest
2 голосов
/ 17 марта 2009

Я пишу бэкэнд-приложение, которое должно иметь возможность отправлять несколько команд SQL на сервер MySQL. MySQL> = 5.x поддерживает несколько операторов, но, к сожалению, мы взаимодействуем с MySQL 4.x.

Я пытаюсь найти способ (подсказка: регулярное выражение) разделить операторы SQL по их точкам с запятой, но он должен игнорировать точки с запятой в одиночных и двойных кавычках.

http://www.dev -explorer.com / article / множественные mysql-запросы имеет очень хорошее регулярное выражение для этого, но не поддерживает двойные кавычки.

Буду рад услышать ваши предложения.

Ответы [ 5 ]

2 голосов
/ 18 марта 2009

Невозможно сделать с помощью регулярных выражений, он недостаточно мощный для анализа SQL. Для вашего языка может быть доступен синтаксический анализатор SQL - что это? - но синтаксический анализ SQL довольно сложен, особенно учитывая диапазон различных доступных синтаксисов. Даже в одной только MySQL существует много флагов SQL_MODE на сервере и уровне соединения, которые могут повлиять на анализ основных строк и комментариев, заставляя операторы вести себя совершенно по-другому.

Пример в dev-explorer идет на забавные длины, чтобы попытаться справиться с экранированными апострофами и замыкающими строками, но все равно потерпит неудачу для многих допустимых их комбинаций, не говоря уже о двойных кавычках, обратных галочках, различных синтаксисах комментариев или ANSI SQL_MODE.

1 голос
/ 13 мая 2010

может быть со следующим Java Regexp? проверить тест ...

@Test
public void testRegexp() {
    String s = //
        "SELECT 'hello;world' \n" + //
        "FROM DUAL; \n" + //
        "\n" + //
        "SELECT 'hello;world' \n" + //
        "FROM DUAL; \n" + //
        "\n";

    String regexp = "([^;]*?('.*?')?)*?;\\s*";

    assertEquals("<statement><statement>", s.replaceAll(regexp, "<statement>"));
}
1 голос
/ 18 марта 2009

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

Я думаю, что самый быстрый путь к решению этой проблемы - функция строкового сканера, которая проверяет каждый символ строки в последовательности и реагирует, основываясь на некотором сохраненном состоянии. Грубый псевдокод:

  1. Читать в символе
  2. Если символ не особенный, ПРОДОЛЖИТЬ
  3. Если символ экранирован (проверка, вероятно, требует проверки предыдущего символа), ПРОДОЛЖИТЬ
  4. Если символ начинает новую строку или заканчивает существующую, переключите флаг IN_STRING (вам может понадобиться несколько флагов для разных типов строк ... Я честно пытался и преуспел, оставаясь в неведении о мелочах цитирования SQL / бежать) и ПРОДОЛЖИТЬ
  5. Если символ является точкой с запятой И мы в настоящее время не в строке, мы нашли запрос! ВЫХОДИТЕ и ПРОДОЛЖИТЕ сканирование до конца строки.

Синтаксический анализ языков не входит в мои области опыта, поэтому вам следует тщательно рассмотреть этот подход; тем не менее, это будет быстро (со строками в стиле C, ни один из этих шагов совсем не дорогой, за исключением, возможно, для OUTPUT, в зависимости от того, что означает «вывод» в вашем контексте), и я думаю, что он должен выполнить работу.

0 голосов
/ 17 июля 2009

Попробуй это. Просто заменил 1-й 'на \ ", и, кажется, работает как для" и " ;? + (= ([^ \ "| ^ \\ '] [' | \\ '] [^' | ^ \\ '] [' | \\ ']) [ ^ '| ^ \\'] [^ '| ^ \\'] $)

0 голосов
/ 18 марта 2009

Я бы посоветовал посмотреть, сможете ли вы переопределить проблемное пространство, поэтому необходимость отправки нескольких запросов, разделенных только их терминатором, не требуется.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...