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
感谢所有的帮助!
如果您需要用'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行。