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

我是sql的新手,我的sql脚本中的关键字问题导致了严重问题。 我正在尝试在C#中执行premade .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’。 当我尝试执行命令时,我捕获了exception,其中说:

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

注意,GOOAIS紧跟着5OAy,这让我相信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。

/捂脸

感谢您的帮助!

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

使用像m / ^ \ s + GO \ s + $ / i这样的正则表达式来识别GO行。

如果你需要使用带有’go’(“smth go smth”)等的注释和字符串值来解析任何Sql脚本,你可以使用gplex工具。 用于sql脚本解析的Gplex规则:

 %namespace LexScanner %option verbose, summary, noparser, unicode %x QUOTE %x COMMENT %{ static string line = ""; static List butch = new List(); 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); } \*\/ { add(yytext, TokenType.ML_COMMENT); BEGIN(INITIAL); } [^\*]+ { add(yytext, TokenType.ML_COMMENT); } \* { add(yytext, TokenType.ML_COMMENT); } \' { add(yytext, TokenType.STRING); BEGIN(QUOTE); } \'\' { add(yytext, TokenType.STRING); } [^\']+ { add(yytext, TokenType.STRING); } \' { 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); } <> { 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 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有一个很好的文档和示例如何使用它。