我是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'。当我尝试执行命令时,我捕获了异常,其中说:
"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”。
ANSWER : 问题是我犯了一个非常愚蠢的错误。我拆分为“GO”,它将命令字符串分割在该参数的中间,其中出现字母GO。
/捂脸
感谢您的帮助!
答案 0 :(得分:4)
如果你需要使用带有'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有一个很好的文档和示例如何使用它。
答案 1 :(得分:1)
您需要自己识别GO,并使用它将文件分批分批,然后逐个执行。
使用像m / ^ \ s + GO \ s + $ / i这样的正则表达式来识别GO行。