2013-08-16 23 views
0

我在C#應用程序中爲MySQL創建存儲過程。存儲過程包含一些動態創建的SQL,用於在索引存在的情況下刪除索引,然後[重新]創建它。 SQL代碼在MySQL Workbench中工作正常,但是當我從C#應用程序運行它時,出現MySQL異常。在存儲過程中使用動態SQL?

這裏是存儲過程的代碼(因爲它是在C#中,有標識前沒有「@」符號,C#使他們本身,我的理解):

CREATE PROCEDURE recreate_index_sp(IN theTable varchar(128), IN theIndexName varchar(128), IN theIndexColumns varchar(128)) 
BEGIN 
    IF ((SELECT COUNT(*) AS index_exists FROM information_schema.statistics WHERE TABLE_SCHEMA = DATABASE() and table_name = theTable AND index_name = theIndexName) > 0) THEN 
     SET s = CONCAT('DROP INDEX ', theIndexName, ' ON ', theTable); 
     PREPARE stmt FROM s; 
     EXECUTE stmt; 
     DEALLOCATE PREPARE stmt; 
    END IF; 
    SET s = CONCAT('CREATE INDEX ' , theIndexName , ' ON ' , theTable, '(', theIndexColumns, ')'); 
    PREPARE stmt FROM s; 
    EXECUTE stmt; 
    DEALLOCATE PREPARE stmt; 
END; 

的例外,我」得到的是:MySql.Data.MySqlClient.MySqlException: Unknown system variable 's'

如果我因此在存儲過程的開始時定義了s - DECLARE s varchar(255) - 我反而得到錯誤You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 's;EXECUTE stmt;DEALLOCATE PREPARE stmt;END' at line 1。但是我在MySQL Workbench中使用的代碼不需要定義變量,所以我不知道爲什麼它在這裏堅持。

如果我使用@s作爲變量名稱(包括定義它!),則例外說Parameter '@s' must be defined

任何想法,我可以得到這個工作?

有關的信息,下面是創建的過程很愉快我使用的代碼在MySQL工作臺:

CREATE PROCEDURE recreate_index_sp(IN theTable varchar(128), IN theIndexName varchar(128), IN theIndexColumns varchar(128)) 
BEGIN 
    IF ((SELECT COUNT(*) AS index_exists FROM information_schema.statistics WHERE TABLE_SCHEMA = DATABASE() and table_name = @theTable AND index_name = @theIndexName) > 0) THEN 
     SET @s = CONCAT('DROP INDEX ', @theIndexName, ' ON ', @theTable); 
     PREPARE stmt FROM @s; 
     EXECUTE stmt; 
     DEALLOCATE PREPARE stmt; 
    END IF; 
    SET @s = CONCAT('CREATE INDEX ', @theIndexName, ' ON ', @theTable, '(', @theIndexColumns, ')'); 
    PREPARE stmt FROM @s; 
    EXECUTE stmt; 
    DEALLOCATE PREPARE stmt; 
END 

編輯:感謝Reubz,我得到的代碼工作。需要兩部分:(1)需要連接字符串「Allow User Variables = True」包括,和(2)@符號是必需的(並且變量不需要聲明)。

因此,這裏的工作代碼:

CREATE PROCEDURE recreate_index_sp(IN theTable varchar(128), IN theIndexName varchar(128), IN theIndexColumns varchar(128)) 
BEGIN 
    IF ((SELECT COUNT(*) AS index_exists FROM information_schema.statistics WHERE TABLE_SCHEMA = DATABASE() and table_name = theTable AND index_name = theIndexName) > 0) THEN 
     SET @sqlPrep = CONCAT('DROP INDEX ', theIndexName, ' ON ', theTable); 
     PREPARE stmt FROM @sqlPrep; 
     EXECUTE stmt; 
     DEALLOCATE PREPARE stmt; 
    END IF; 
    SET @sqlPrep = CONCAT('CREATE INDEX ' , theIndexName , ' ON ' , theTable, '(', theIndexColumns, ')'); 
    PREPARE stmt FROM @sqlPrep; 
    EXECUTE stmt; 
    DEALLOCATE PREPARE stmt; 
END; 
+0

如果它有什麼區別,我使用的是MySQL Connector Net v6.5.5,MySQL Server v5.1,並在Visual Studio 2012 Pro中編寫C#應用程序。 –

+0

你是如何在c#中創建這個存儲過程的?你能發佈實際的代碼嗎? – Riv

+0

發佈代碼時相當困難,因爲它包含在無數類對象中,但足以說:我可以使用完全相同的代碼創建其他存儲過程,表和視圖,所以我不認爲它是C#代碼本身。但我會看看我能提取什麼。 –

回答

1

根據我們聊天:

你必須使用你的用戶定義的變量s @符號,爲了從一個系統變量區別開來。但是,在新版本的MySQL連接器中,默認情況下,用戶定義的變量被禁用。要啓用它,您需要更改連接字符串並添加用戶變量= True參數。

+0

再次感謝。我將在我的問題中發佈完整的工作查詢代碼以供將來參考。 –