Ключевые слова в данных сценария SQL, вызывающие проблемы при программном выполнении - C # - PullRequest
1 голос
/ 27 марта 2012

Я довольно новичок в SQL, и у меня проблема с ключевыми словами, вызывающими хаос в моем сценарии SQL. Я пытаюсь выполнить список готовых файлов сценариев .sql в C #. В настоящее время я читаю файл в строку и выполняю его с помощью command.ExecuteNonQuery (). Это прекрасно работает для большинства скриптов, но я сталкиваюсь с тем, что случайно содержит ключевое слово:

INSERT INTO [thetable]
SELECT '123123', 'abcabc', 'I WANT TO GO TO BED'
UNION ALL
SELECT '123124', 'abcdef', 'SOOO TIRED'

По сути, когда он попадает в GO, команда не выполняется.

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

Любая помощь будет принята с благодарностью. Большое спасибо!

РЕДАКТИРОВАТЬ , чтобы добавить информацию:

Для пояснения, настоящая строка выглядит примерно так: «ASVFDS4 + 23eF3da34sddsdf3d3t4g ... 100charslater ... sd5OAyGOsiISIssdsd / sNUIGsdisd354f». Когда я пытаюсь выполнить команду, я ловлю исключение, которое говорит:

"Unclosed quotation mark after character string 'ASVFDS4+23eF3da34sddsdf3d3t4g...100charslater...sd5OAy'

Обратите внимание, что за 5OAy немедленно следует GOsiIS ..., что заставляет меня поверить, что GO фактически читается как команда, заставляя его ожидать конца строки перед этой командой.

Запуск .NET 3.5

РЕДАКТИРОВАТЬ 2 Я также должен уточнить, я в настоящее время делится на фактические операторы GO и выполняю команды индивидуально.

1025 * т.е. *

USE MyDatabase
GO
INSERT INTO [thetable]
SELECT '123123', 'abcabc', 'I WANT TO GO TO BED'
UNION ALL
SELECT '123124', 'abcdef', 'SOOO TIRED'
UNION ALL
...
SELECT '123189', 'abcabc', 'HAD SOME SLEEP'
GO

разбивается, поэтому я выполняю

USE MyDatabase

и

INSERT INTO [thetable]
SELECT '123123', 'abcabc', 'I WANT TO GO TO BED'
UNION ALL
SELECT '123124', 'abcdef', 'SOOO TIRED'
UNION ALL
...
SELECT '123189', 'abcabc', 'HAD SOME SLEEP'

отдельно. Поэтому моя проблема не в реальных операторах GO, а в том, что в строке данных появляются символы «GO».

ОТВЕТ : Проблема в том, что я совершил ужасно глупую ошибку. Я разделил на «GO», который разбивает командную строку прямо в середине того параметра, где появляются буквы GO.

/ Facepalm

Спасибо за помощь!

Ответы [ 2 ]

4 голосов
/ 27 марта 2012

Если вам нужно проанализировать любые сценарии Sql с комментариями и строковыми значениями с помощью 'go' ("smth go smth") и т. Д., Вы можете использовать инструмент gplex .Правила Gplex для разбора сценария sql:

%namespace LexScanner
%option verbose, summary, noparser, unicode

%x QUOTE
%x COMMENT

%{
    static string line = "";
    static List<string> butch = new List<string>();
    enum TokenType {
        SL_COMMENT,
        ML_COMMENT,
        STRING,
        WORD,
        OTHER,
        ending
    };
%}

dotchr [^\r\n] 
eol (\r\n?|\n)
%%
\-\-[^\n]*$             { add(yytext, TokenType.SL_COMMENT); }

\/\*                    { add(yytext, TokenType.ML_COMMENT); BEGIN(COMMENT); }
<COMMENT>\*\/           { add(yytext, TokenType.ML_COMMENT); BEGIN(INITIAL); }
<COMMENT>[^\*]+         { add(yytext, TokenType.ML_COMMENT); }
<COMMENT>\*             { add(yytext, TokenType.ML_COMMENT); }

\'                      { add(yytext, TokenType.STRING); BEGIN(QUOTE); }
<QUOTE>\'\'             { add(yytext, TokenType.STRING); }
<QUOTE>[^\']+           { add(yytext, TokenType.STRING); }
<QUOTE>\'               { add(yytext, TokenType.STRING); BEGIN(INITIAL); }

[gG][oO]                { push(); }

[a-zA-Z0-9]+            { add(yytext, TokenType.WORD); }
.                       { add(yytext, TokenType.OTHER); }
\r?\n                   { add(yytext, TokenType.OTHER); }
<<EOF>>                 { push(); }
%%

Затем вы создаете класс C # и используете его.

РЕДАКТИРОВАТЬ: Еще несколько комментариев, как его использовать.Функции add(string text, TokenType token) и push() - что делать с анализируемой строкой.Функция add () собирает проанализированные строки между ключевыми словами GO и записывает результаты в выходной файл (только для управления):

private void add(string text, TokenType token)
{
    //write to the file for output control (for test only)
    using (StreamWriter str = new StreamWriter("C:\\temp\\temp.txt", true))
    {
        str.WriteLine(token + " : " + text); 
    }
    line += text;
}

push () собирает строки буширования для выполнения:

private void push()
{
    //write to the file for output control (for test only)
    using (StreamWriter str = new StreamWriter("C:\\temp\\butch.txt", true))
    {
        str.WriteLine("GO: " + line); 
    }

    butch.Add(line);
    line = "";
}

Toиспользуйте этот класс из кода C #, вы должны указать точку входа.Например:

 public static List<string> ParseFile(String fileToParse)
 {
     int tok;
     Scanner scnr = new Scanner();
     scnr.SetSource(fileToParse, 0);
     do {
             tok = scnr.yylex();
         } while (tok > (int)Tokens.EOF);
     return butch;
 }

Или определите функцию Main, чтобы использовать ее в качестве автономного приложения.

Весь приведенный выше код должен быть помещен в файл .lex.Файл sqlparser.cs создается путем вызова из командной строки:

gplex sqlparser.lex

Gplex имеет хорошую документацию и примеры, как его использовать.

1 голос
/ 27 марта 2012

Вам нужно распознать GO самостоятельно и использовать его для разделения файла на пакеты, а затем выполнить каждый из них по отдельности.

Используйте регулярное выражение, например, m / ^ \ s + GO \ s + $ /я, чтобы распознать GO линии.

...