1

私はSQLにかなり慣れておらず、SQLスクリプトで大混乱を引き起こすキーワードに問題があります。C#で事前に作成された.sqlスクリプトファイルのリストを実行しようとしています。現在、ファイルを文字列に読み込んで、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は実際にはコマンドとして読み取られているため、そのコマンドの前に文字列が終了することが予想されます。

.NET3.5の実行

編集2 また、明確にする必要があります。現在、実際のGOステートメントを分割し、コマンドを個別に実行しています。

すなわち

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

すべての助けをありがとう!

4

2 に答える 2

4

コメント付きのSQLスクリプトと'go'( "smth go smth")などの文字列値を解析する必要がある場合は、gplexツールを使用できます。SQLスクリプト解析のGplexルール:

%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 = "";
}

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;
 }

または、メイン関数を定義して、スタンドアロンアプリケーションとして使用します。

上記のコードはすべて.lexファイルに配置する必要があります。ファイルsqlparser.csは、コマンドラインから呼び出すことによって作成されます。

gplex sqlparser.lex

Gplexには、優れたドキュメントとその使用方法の例があります。

于 2012-03-27T15:12:02.597 に答える
1

GOを自分で認識し、それを使用してファイルをバッチに分割し、それぞれを個別に実行する必要があります。

m / ^ \ s + GO \ s + $ / iのような正規表現を使用して、GOラインを認識します。

于 2012-03-27T09:51:13.447 に答える