2009-03-17 3 views
1

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

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

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

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

+0

Я хотел бы пояснить, что я не хочу, чтобы закодировать регулярное выражение? Я не дурак. Зная, что операторы SQL разделены знаком «;», я считаю, что лучшим решением является написать регулярное выражение для разделения точки с запятой. Настоящая проблема заключается в совпадении точек с запятой, не включенных в одиночные или двойные кавычки. – 2009-03-18 14:04:43

+0

Может быть как поле с двумя кавычками, так и одно кавычками s в той же строке с несколькими запросами? Может ли поле с двумя кавычками содержать неэксклюзивные одиночные кавычки или наоборот? В зависимости от ответов это может быть выполнимо. –

+0

Дубликат: [http://stackoverflow.com/questions/139926/regular-expression-to-match-common-sql-syntax](http://stackoverflow.com/questions/139926/regular-expression-to-match -common-sql-синтаксис) [http://stackoverflow.com/questions/633014/split-multiple-sql-statements-into-individual-sql-statements](http://stackoverflow.com/questions/633014/ split-multiple-sql-statements-in-individual-sql-statements) – cdonner

ответ

1

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

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

1

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

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

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

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

0

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

0

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

1

возможно со следующим 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>")); 
} 
Смежные вопросы