SQL脚本数据中的关键字在以编程方式执行时导致问题-C#

本文关键字:执行 方式 -C# 问题 编程 数据 脚本 关键字 SQL | 更新日期: 2023-09-27 18:29:17

我对sql还很陌生,关键字对我的sql脚本造成了严重破坏。我正在尝试在C#中执行一个预制.sql脚本文件列表。我目前正在将文件读取为字符串,并使用命令执行它。ExecuteNonQuery()。这对大多数脚本都很有效,但我无意中遇到了一个包含关键字的脚本:

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

本质上,当它击中GO时,命令会失败。

我负责创建这些插入文件,所以如果我需要以某种方式重新格式化它们,那么这是可能的;然而,其中的数据是不可协商的。此外,由于我是从一个有很多行的文件中加载它们,因此参数化以避免这种情况似乎也不可行。

在这一点上,任何帮助都将不胜感激。非常感谢!

编辑以添加信息:

为了澄清,实际字符串更像"ASVFDS4+23eF3da34sddsdf3d3t4g。。。100个字符后。。。sd5OAyGOsiISIssdsd/sNUIGsdisd354f'。当我尝试执行命令时,我会捕捉到异常,它显示:

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

注意5OAy后面紧跟GOsiIS。。。,这让我相信GO实际上是作为一个命令读取的,这导致它期望在该命令之前的字符串结束。

运行.NET 3.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

感谢所有的帮助!

SQL脚本数据中的关键字在以编程方式执行时导致问题-C#

如果您需要用'go'("smth-go-smth")等解析任何带有注释和字符串值的Sql脚本,您可以使用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()收集用于执行的butch字符串:

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

或者定义一个Main函数,将其用作独立的应用程序。

上述所有代码都应该放在.lex文件中。sqlparser.cs文件是通过从命令行调用创建的:

gplex sqlparser.lex

Gplex有很好的文档和如何使用它的示例。

您需要自己识别GO,并使用它将文件拆分为多个批,然后分别执行每个批。

使用类似m/^''s+GO''s+$/i的正则表达式来识别GO行。