文件首頁
MySQL Connector/NET 開發人員指南
相關文件 下載本手冊
PDF (美國信紙) - 1.3Mb
PDF (A4) - 1.3Mb


6.8 教學:使用 MySqlScript

本教學課程教您如何使用 MySqlScript 類別。這個類別可讓您執行一系列陳述式。視情況而定,這會比使用 MySqlCommand 方法更方便。

MySqlScript 類別的更多詳細資料可在 MySQL Connector/NET 隨附的參考文件中找到。

若要執行本教學課程中的範例程式,請使用 mysql 命令列用戶端或 MySQL Workbench 設定簡單的測試資料庫和資料表。此處提供 mysql 命令列用戶端的命令

CREATE DATABASE TestDB;
USE TestDB;
CREATE TABLE TestTable (id INT NOT NULL PRIMARY KEY
  AUTO_INCREMENT, name VARCHAR(100));

MySqlScript 類別的主要方法是 Execute 方法。此方法會導致執行指派給 MySqlScript 物件的 Query 屬性的指令碼 (陳述式序列)。可以使用 MySqlScript 建構函式或使用 Query 屬性來設定 Query 屬性。Execute 會傳回已執行的陳述式數目。

MySqlScript 物件會在使用 Connection 屬性設定的連線上執行指定的指令碼。同樣地,這個屬性可以直接設定,也可以透過 MySqlScript 建構函式設定。以下程式碼片段說明這一點

string sql = "SELECT * FROM TestTable";
...
MySqlScript script = new MySqlScript(conn, sql);
...
MySqlScript script = new MySqlScript();
script.Query = sql;
script.Connection = conn;
...
script.Execute();

MySqlScript 類別有數個與其相關聯的事件。分別為

  1. Error - 如果發生錯誤,則會產生。

  2. ScriptCompleted - 當指令碼成功完成執行時,會產生。

  3. StatementExecuted - 在每個陳述式執行後產生。

您可以將事件處理常式指派給這些事件中的每一個。當連線的事件發生時,會回呼這些使用者提供的常式。以下程式碼顯示如何設定事件處理常式。

script.Error += new MySqlScriptErrorEventHandler(script_Error);
script.ScriptCompleted += new EventHandler(script_ScriptCompleted);
script.StatementExecuted += new MySqlStatementExecutedEventHandler(script_StatementExecuted);

在 VisualStudio 中,您可以使用 Tab 完成來填寫 Stub 常式,以節省輸入時間。例如,從輸入 script.Error += 開始。然後按 TAB,然後再按 TAB。指派完成,並建立 Stub 事件處理常式。以下顯示完整的運作範例

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Data;
using MySql.Data;
using MySql.Data.MySqlClient;

namespace MySqlScriptTest
{
    class Program
    {
        static void Main(string[] args)
        {
            string connStr = "server=localhost;user=root;database=TestDB;port=3306;password=******";
            MySqlConnection conn = new MySqlConnection(connStr);

            try
            {
                Console.WriteLine("Connecting to MySQL...");
                conn.Open();

                string sql = "INSERT INTO TestTable(name) VALUES ('Superman');" +
                             "INSERT INTO TestTable(name) VALUES ('Batman');" +
                             "INSERT INTO TestTable(name) VALUES ('Wolverine');" +
                             "INSERT INTO TestTable(name) VALUES ('Storm');";

                MySqlScript script = new MySqlScript(conn, sql);
              
                script.Error += new MySqlScriptErrorEventHandler(script_Error);
                script.ScriptCompleted += new EventHandler(script_ScriptCompleted);
                script.StatementExecuted += new MySqlStatementExecutedEventHandler(script_StatementExecuted);
              
                int count = script.Execute();

                Console.WriteLine("Executed " + count + " statement(s).");
                Console.WriteLine("Delimiter: " + script.Delimiter);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }

            conn.Close();
            Console.WriteLine("Done.");
        }

        static void script_StatementExecuted(object sender, MySqlScriptEventArgs args)
        {
            Console.WriteLine("script_StatementExecuted");  
        }

        static void script_ScriptCompleted(object sender, EventArgs e)
        {
            /// EventArgs e will be EventArgs.Empty for this method
            Console.WriteLine("script_ScriptCompleted!");
        }

        static void script_Error(Object sender, MySqlScriptErrorEventArgs args)
        {
            Console.WriteLine("script_Error: " + args.Exception.ToString());
        }
    }
}

script_ScriptCompleted 事件處理常式中,EventArgs 參數 e 將會是 EventArgs.Empty。在 ScriptCompleted 事件的情況下,沒有要取得的其他資料,這就是為什麼事件物件是 EventArgs.Empty 的原因。

在 MySqlScript 中使用分隔符號

視指令碼的性質而定,您可能需要控制用於分隔構成指令碼的陳述式的分隔符號。最常見的範例是,您的指令碼中包含多個陳述式的預存常式。在這種情況下,如果使用預設分隔符號 ;,當您嘗試執行指令碼時,會收到錯誤訊息。例如,請考慮下列預存常式

CREATE PROCEDURE test_routine()
BEGIN
    SELECT name FROM TestTable ORDER BY name;
    SELECT COUNT(name) FROM TestTable;
END

實際上,這個常式需要當作單一陳述式在 MySQL Server 上執行。但是,使用預設分隔符號 ;MySqlScript 類別會將上述內容解譯為兩個陳述式,第一個是

CREATE PROCEDURE test_routine()
BEGIN
    SELECT name FROM TestTable ORDER BY name;

如果將此當作陳述式執行,會產生錯誤。若要解決此問題,MySqlScript 支援設定不同分隔符號的功能。這是透過 Delimiter 屬性來達成。例如,您可以將分隔符號設定為 ??,在這種情況下,上述預存常式在執行時將不再產生錯誤。可以在指令碼中分隔多個陳述式,因此舉例來說,您可以擁有類似以下的三個陳述式指令碼

string sql = "DROP PROCEDURE IF EXISTS test_routine??" +
             "CREATE PROCEDURE test_routine() " +
             "BEGIN " +
             "SELECT name FROM TestTable ORDER BY name;" +
             "SELECT COUNT(name) FROM TestTable;" +
             "END??" +
             "CALL test_routine()";

您可以隨時透過設定 Delimiter 屬性來將分隔符號變更回來。以下程式碼顯示完整的運作範例

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using MySql.Data;
using MySql.Data.MySqlClient;

namespace ConsoleApplication8
{
    class Program
    {
        static void Main(string[] args)
        {
            string connStr = "server=localhost;user=root;database=TestDB;port=3306;password=******";
            MySqlConnection conn = new MySqlConnection(connStr);

            try
            {
                Console.WriteLine("Connecting to MySQL...");
                conn.Open();

                string sql =    "DROP PROCEDURE IF EXISTS test_routine??" +
                                "CREATE PROCEDURE test_routine() " +
                                "BEGIN " +
                                "SELECT name FROM TestTable ORDER BY name;" +
                                "SELECT COUNT(name) FROM TestTable;" +
                                "END??" +
                                "CALL test_routine()";

                MySqlScript script = new MySqlScript(conn);
          
                script.Query = sql;
                script.Delimiter = "??";
                int count = script.Execute();
                Console.WriteLine("Executed " + count + " statement(s)");
                script.Delimiter = ";";
                Console.WriteLine("Delimiter: " + script.Delimiter);
                Console.WriteLine("Query: " + script.Query);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }

            conn.Close();
            Console.WriteLine("Done.");
        }
    }
}