在存储过程中使用动态SQL?

时间:2013-08-16 10:38:12

标签: c# mysql

我正在C#应用程序中为MySQL创建存储过程。存储过程包含一些动态创建的SQL,用于删除索引(如果存在),然后[重新]创建它。 SQL代码可以在MySQL Workbench中正常运行,但是当我从我的C#应用​​程序运行它时,我遇到了MySQL异常。

这是存储过程代码(因为它在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 Workbench中使用的代码,可以非常愉快地创建该过程:

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)连接字符串需要“允许用户变量=真;”包括,和(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;

1 个答案:

答案 0 :(得分:1)

根据我们的聊天:

您必须将@符号用于用户定义的变量s,以便将其与系统变量区分开来。但是,在较新版本的MySQL连接器中,默认情况下禁用用户定义的变量。要启用它,您需要更改连接字符串并添加User Variables = True参数。