0

我正在 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)连接字符串需要“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;
4

1 回答 1

1

根据我们的聊天:

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

于 2013-08-16T12:37:27.810 回答