我正在 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;