在 .NET 中将多个非 SELECT MySQL 语句作为单个命令文本执行
Executing Multiple Non-SELECT MySQL Statements as a Single Command Text in .NET
我一直在从一个线程跳到另一个线程,但我似乎找不到我需要的答案。
我想使用 .NET 在单个 ExecuteNonQuery 函数中执行非 SELECT MySQL 语句。
这是我想要 运行:
的一组示例 SQL 语句
DROP procedure IF EXISTS `SubProcA`;
DROP procedure IF EXISTS `SubProcB`;
DROP procedure IF EXISTS `SubProcC`;
CREATE PROCEDURE 'SubProcD'()
BEGIN
SELECT
(<Subselect Statement>) AS A
,(<Subselect Statement>) AS B
,(<Subselect Statement>) AS C;
END;
CREATE PROCEDURE 'SubProcE'(
VarA TEXT,
VarB VARCHAR(255),
VarC VARCHAR(255),
VarD tinyint(1)
)
BEGIN
SET @Query = "";
SET @Query = <Select Statement>;
PREPARE Statement FROM @Query;
EXECUTE Statement;
DEALLOCATE PREPARE Statement;
END;
如您所见,其中有五个语句(3 个 DROP 和 2 个 CREATE)。我在 .NET 中所做的是:
CommandText = <The SQL Statement above stored in a String variable>
Connection.Open()
Command.CommandType = CommandType.Text
Command.ExecuteNonQuery()
Connection.Close()
假设 sql 语句没有任何语法错误,我在 运行 编译代码时仍然会出错。
我尝试切碎(运行宁一个语句)的 sql 语句,它通过了。
我是不是应该在里面放一些特殊字符之类的?
这些多个串联的查询在 .net 中称为 batch
。
您必须告诉 MySQL 连接器(MySQL 的 .net 驱动程序)您想在连接字符串中使用批处理。使用 AllowBatch
option.
像这样:
var connectionString = Server=host;Database=db;Uid=user;Pwd=pass;AllowBatch=True;
您不能在批处理中包含存储过程调用。他们必须独立于 ...CommandType=CommandType.StoredProcedure
.
但是,这可能无法正常工作,具体取决于服务器和连接器版本。如果它不只是使用 "chopping" SQL 语句的解决方法。它工作正常,不会以可怕的方式破坏性能。
所以我设法找到了一种方法来完成这项工作:
- 我使用 MySQLClient 而不是 ODBC。
- 在连接字符串中,包含
allowbatch=true;allowuservariables=true;
.
- 删除
Delimiter $$
或Delimiter //
及其尾部(位于END
的$$
或//
)
- 只需将所有内容放入一个字符串变量中即可。只需确保您的 sql 语法正确即可。
这是我使用的测试代码:
Try
Dim CONN = New MySql.Data.MySqlClient.MySqlConnection("server=localhost;user=<user>;database=<database>;port=3306;password=<password>;allowbatch=true;allowuservariables=true;")
Dim CMDTXT =
<sql>
DROP procedure IF EXISTS `sample`;
CREATE PROCEDURE `sample`(
in_varA int(11),
in_varB int(11),
in_varC int(11)
)
BEGIN
SET @query = CONCAT("SELECT ",in_varA + in_varB + in_varC);
PREPARE Statement FROM @Query;
EXECUTE Statement;
DEALLOCATE PREPARE Statement;
END;
</sql>
CONN.Open()
Using TRAN = CONN.BeginTransaction
Using CMD = CONN.CreateCommand
CMD.CommandText = CMDTXT.Value
CMD.CommandType = CommandType.Text
CMD.ExecuteNonQuery()
TRAN.Commit()
End Using
End Using
CONN.Close()
Catch ex As Exception
MsgBox(ex.Message)
Exit Sub
End Try
MsgBox("success")
我基本上使用这种风格来更新远程独立服务器。我会复制我对表、子过程等所做的所有更改的更新脚本。将它们放入一个 sql 文件中,在线存储它们(我使用 Dropbox API),然后让我的应用程序(在客户端)下载它并在其自己的本地数据库上应用更改。
SET @query = CONCAT("SELECT ",in_varA + in_varB + in_varC);
PREPARE Statement FROM @Query;
EXECUTE Statement;
DEALLOCATE PREPARE Statement;
我需要 allowuservariables=true;
以便我可以在查询中声明 @query
和其他变量。我在上面使用的代码段允许我创建动态子进程——一个根据需求构建自己的查询的子进程。
我希望这对其他人有所帮助。
特别感谢 O. Jones。
我一直在从一个线程跳到另一个线程,但我似乎找不到我需要的答案。
我想使用 .NET 在单个 ExecuteNonQuery 函数中执行非 SELECT MySQL 语句。
这是我想要 运行:
的一组示例 SQL 语句DROP procedure IF EXISTS `SubProcA`;
DROP procedure IF EXISTS `SubProcB`;
DROP procedure IF EXISTS `SubProcC`;
CREATE PROCEDURE 'SubProcD'()
BEGIN
SELECT
(<Subselect Statement>) AS A
,(<Subselect Statement>) AS B
,(<Subselect Statement>) AS C;
END;
CREATE PROCEDURE 'SubProcE'(
VarA TEXT,
VarB VARCHAR(255),
VarC VARCHAR(255),
VarD tinyint(1)
)
BEGIN
SET @Query = "";
SET @Query = <Select Statement>;
PREPARE Statement FROM @Query;
EXECUTE Statement;
DEALLOCATE PREPARE Statement;
END;
如您所见,其中有五个语句(3 个 DROP 和 2 个 CREATE)。我在 .NET 中所做的是:
CommandText = <The SQL Statement above stored in a String variable>
Connection.Open()
Command.CommandType = CommandType.Text
Command.ExecuteNonQuery()
Connection.Close()
假设 sql 语句没有任何语法错误,我在 运行 编译代码时仍然会出错。
我尝试切碎(运行宁一个语句)的 sql 语句,它通过了。
我是不是应该在里面放一些特殊字符之类的?
这些多个串联的查询在 .net 中称为 batch
。
您必须告诉 MySQL 连接器(MySQL 的 .net 驱动程序)您想在连接字符串中使用批处理。使用 AllowBatch
option.
像这样:
var connectionString = Server=host;Database=db;Uid=user;Pwd=pass;AllowBatch=True;
您不能在批处理中包含存储过程调用。他们必须独立于 ...CommandType=CommandType.StoredProcedure
.
但是,这可能无法正常工作,具体取决于服务器和连接器版本。如果它不只是使用 "chopping" SQL 语句的解决方法。它工作正常,不会以可怕的方式破坏性能。
所以我设法找到了一种方法来完成这项工作:
- 我使用 MySQLClient 而不是 ODBC。
- 在连接字符串中,包含
allowbatch=true;allowuservariables=true;
. - 删除
Delimiter $$
或Delimiter //
及其尾部(位于END
的$$
或//
) - 只需将所有内容放入一个字符串变量中即可。只需确保您的 sql 语法正确即可。
这是我使用的测试代码:
Try
Dim CONN = New MySql.Data.MySqlClient.MySqlConnection("server=localhost;user=<user>;database=<database>;port=3306;password=<password>;allowbatch=true;allowuservariables=true;")
Dim CMDTXT =
<sql>
DROP procedure IF EXISTS `sample`;
CREATE PROCEDURE `sample`(
in_varA int(11),
in_varB int(11),
in_varC int(11)
)
BEGIN
SET @query = CONCAT("SELECT ",in_varA + in_varB + in_varC);
PREPARE Statement FROM @Query;
EXECUTE Statement;
DEALLOCATE PREPARE Statement;
END;
</sql>
CONN.Open()
Using TRAN = CONN.BeginTransaction
Using CMD = CONN.CreateCommand
CMD.CommandText = CMDTXT.Value
CMD.CommandType = CommandType.Text
CMD.ExecuteNonQuery()
TRAN.Commit()
End Using
End Using
CONN.Close()
Catch ex As Exception
MsgBox(ex.Message)
Exit Sub
End Try
MsgBox("success")
我基本上使用这种风格来更新远程独立服务器。我会复制我对表、子过程等所做的所有更改的更新脚本。将它们放入一个 sql 文件中,在线存储它们(我使用 Dropbox API),然后让我的应用程序(在客户端)下载它并在其自己的本地数据库上应用更改。
SET @query = CONCAT("SELECT ",in_varA + in_varB + in_varC);
PREPARE Statement FROM @Query;
EXECUTE Statement;
DEALLOCATE PREPARE Statement;
我需要 allowuservariables=true;
以便我可以在查询中声明 @query
和其他变量。我在上面使用的代码段允许我创建动态子进程——一个根据需求构建自己的查询的子进程。
我希望这对其他人有所帮助。
特别感谢 O. Jones。