Executing Multiple Non-SELECT MySQL Statements as a Single Command Text in .NET

こ雲淡風輕ζ 提交于 2021-01-28 07:24:57

问题


I've been jumping from one thread to another but I can't seem to find the answer that I need.

I wanted to execute non-SELECT MySQL statements in a single ExecuteNonQuery function using .NET.

Here is a sample group of SQL statements I wanted to run:

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;

As you can see, there are five statements in there (3 DROPs and 2 CREATEs). What I do in .NET is:

    CommandText = <The SQL Statement above stored in a String variable>
    Connection.Open()
    Command.CommandType = CommandType.Text
    Command.ExecuteNonQuery()
    Connection.Close()

Assuming that the sql statements have no syntax error whatsoever, I still get an error when running the code.

I tried chopping the sql statements of (running one statement) and it pushes through.

Am I suppose to put some special character in there or something?


回答1:


These multiple concatenated queries are known as a batch in .net parlance.

You must tell the MySQL connector (the .net driver for MySQL) you want to use batches in your connection string. Use the AllowBatch option.

Something like this:

var connectionString = Server=host;Database=db;Uid=user;Pwd=pass;AllowBatch=True;

You cannot include stored procedure invocations within a batch. They must stand alone with ...CommandType=CommandType.StoredProcedure .

But, this may not work depending on server and connector versions. If it doesn't just use your workaround of "chopping" the SQL statements. It works fine and doesn't mess up performance in a horrible way.




回答2:


So I managed to find a way to make this work:

  • I used MySQLClient instead of ODBC.
  • In the connection string, include allowbatch=true;allowuservariables=true;.
  • Remove Delimiter $$ or Delimiter // and its tail (the $$ or // located at END)
  • Just put everything in a string variable and fire away. Just make sure your sql syntax is correct.

This is the test code I used:

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")

I basically used this style in updating a remote stand alone server. I would copy the update script of all the changes I made on my tables, sub procs, etc. Put them into one sql file, store them online (I used Dropbox API), and let my application (on client) download it and apply the changes on its own local database.

SET @query = CONCAT("SELECT ",in_varA + in_varB + in_varC);
PREPARE Statement FROM @Query;
EXECUTE Statement;
DEALLOCATE PREPARE Statement;      

I needed the allowuservariables=true; so I could declare @query and other variables within my query. The code segment I used above allowed me to create dynamic subprocs - one that builds its own query depending on the demand.

I hope this would help others.

Special thanks to O. Jones.



来源:https://stackoverflow.com/questions/53481632/executing-multiple-non-select-mysql-statements-as-a-single-command-text-in-net

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!