C# SQL脚本数据中的关键字在以编程方式执行时导致问题-C
我对sql相当陌生,并且在sql脚本中遇到了关键字造成严重破坏的问题。我正在尝试以C语言执行一个预制的.sql脚本文件列表。我当前正在将该文件读取为字符串,并使用command.ExecuteNonQuery执行它。这对于大多数脚本来说都非常有效,但我无意中遇到了一个包含关键字的脚本:C# SQL脚本数据中的关键字在以编程方式执行时导致问题-C,c#,sql,sql-injection,sqlcommand,sql-insert,C#,Sql,Sql Injection,Sqlcommand,Sql Insert,我对sql相当陌生,并且在sql脚本中遇到了关键字造成严重破坏的问题。我正在尝试以C语言执行一个预制的.sql脚本文件列表。我当前正在将该文件读取为字符串,并使用command.ExecuteNonQuery执行它。这对于大多数脚本来说都非常有效,但我无意中遇到了一个包含关键字的脚本: INSERT INTO [thetable] SELECT '123123', 'abcabc', 'I WANT TO GO TO BED' UNION ALL SELECT '123124', 'abcdef
INSERT INTO [thetable]
SELECT '123123', 'abcabc', 'I WANT TO GO TO BED'
UNION ALL
SELECT '123124', 'abcdef', 'SOOO TIRED'
基本上,当它点击GO时,命令失败
我负责创建这些插入文件,所以如果我需要以某种方式重新格式化它们,那么这是可能的;但是,其中的数据是不可协商的。而且,由于我是从一个包含许多行的文件中加载它们,因此避免这种情况的参数化似乎也不可行
在这一点上,任何帮助都将不胜感激。非常感谢
编辑以添加信息:
为了澄清,实际字符串更像是“ASVFDS4+23ef3da34sddsdf3t4g…100charslater…sd5oaygosisssdsd/sNUIGsdisd354f”。当我尝试并执行该命令时,我捕获异常,该异常表示:
"Unclosed quotation mark after character string 'ASVFDS4+23eF3da34sddsdf3d3t4g...100charslater...sd5OAy'
请注意,5OAy后面紧跟着GOsiIS…,这使我相信GO实际上是作为命令读取的,这导致它期望在该命令之前字符串结束
运行.NET3.5
编辑2
我还应该澄清一下,我目前正在分割实际的GO语句,并单独执行这些命令
i、 e
分裂,所以我执行
USE MyDatabase
及
分开。所以我的问题不是实际的GO语句,而是数据字符串中出现的字符“GO”
答复:
问题是我犯了一个极其愚蠢的错误。我在GO上分裂,它在命令出现的字母的中间分割命令字符串。
/掌纹
谢谢你的帮助 您需要自己识别GO,并使用它将文件分为多个批,然后分别执行每个批
使用类似于m/^\s+GO\s+$/i的正则表达式来识别GO行。您需要自己识别GO,并使用它将文件分为多个批,然后分别执行每个批
使用类似于m/^\s+GO\s+$/i的正则表达式来识别GO行。如果需要解析任何带有注释的Sql脚本以及带有“GO”smth GO smth等的字符串值,可以使用该工具。用于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(); }
%%
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;
}
Gplex有很好的文档和如何使用它的示例 如果您需要使用'go'smth go smth等解析任何带有注释和字符串值的Sql脚本,您可以使用该工具。用于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(); }
%%
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;
}
Gplex有很好的文档和如何使用它的示例 你得到的例外是什么?我非常怀疑你所遇到的问题是否与GO是否是一个关键字有关,至少正如上面的sql所示。我猜它是撇号或其他什么。在一些应用程序中,GO用作批处理分隔符。不要认为command.ExecuteNonQuery可以识别GO。您可能有一些C语言的代码可以解析SQL脚本并一次执行一个批处理,对吗?你需要寻找一种方法来解决这个问题。如果您自己编写了代码并控制了脚本文件的生成,那么您可以更改代码,使其仅在GO单独在一行上时触发新批处理。您使用的是什么数据库?如果是SQL Server,并且是开发人员版本或更高版本。尝试运行SQL Profiler以查看正在服务器上运行的SQL。同意Andrew的观点:查看正在执行的实际SQL,并通过SQL Profiler确保它是干净的@Mikael Eriksson-我在.NET中使用.ExecuteOnQuery方法专门处理GO关键字-它将其识别为批处理分隔符。MarnBeast-理想情况下,我们需要更多信息。张贴您的C代码以及!你得到的例外情况是什么?我非常怀疑你所遇到的问题是否与GO是否是一个关键字有关,至少正如上面的sql所示。我猜它是撇号或其他什么。在一些应用程序中,GO用作批处理分隔符。不要认为command.ExecuteNonQuery可以识别GO。您可能有一些C语言的代码可以解析SQL脚本并一次执行一个批处理,对吗?你需要寻找一种方法来解决这个问题。如果您自己编写了代码并控制了脚本文件的生成,那么您可以更改代码,使其仅在GO单独在一行上时触发新批处理。您使用的是什么数据库?如果是SQL Server,并且是开发人员版本或更高版本。尝试运行SQL Profiler以查看正在服务器上运行的SQL。同意Andrew的说法:查看
正在执行的实际SQL,并通过SQL探查器确保它是干净的@Mikael Eriksson-我在.NET中使用.ExecuteOnQuery方法专门处理GO关键字-它将其识别为批处理分隔符。MarnBeast-理想情况下,我们需要更多信息。张贴您的C代码以及!有趣的是,我实际上是在使用.splitnewstring[]{GO},StringSplitOptions.RemoveEmptyEntries执行此操作。这比我预期的更有效,因为我意识到它在脚本中拆分了前面提到的字符串字段,它看到了字母的去向。因此,在从String返回的命令字符串列表中,其中一个命令在字符串字段的中间被分割为一半。哎呀。将其更改为.Splitnew string[]{\r\nGO},StringSplitOptions.RemoveEmptyEntries后,问题得到了修复。有趣的是,我实际上是在使用.Splitnew string[]{GO},StringSplitOptions.RemoveEmptyEntries来执行此操作的。这比我预期的更有效,因为我意识到它在脚本中拆分了前面提到的字符串字段,它看到了字母的去向。因此,在从String返回的命令字符串列表中,其中一个命令在字符串字段的中间被分割为一半。哎呀。在将其更改为.Splitnew string[]{\r\nGO},StringSplitOptions.RemoveEmptyEntries后,问题得到了解决。请您提供更多详细信息添加、推送方法以及如何从C中使用此方法,这肯定是一种方法,但我不是Lex的专家。。。谢谢!你可以提供更多的细节,添加,推送方法,以及如何从C使用它,这是肯定的方式去,但我不是一个专家在所有与莱克斯。。。谢谢!
gplex sqlparser.lex