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

EDIT:Reubzのおかげで、コードが機能しました。2 つの部分が必要でした: (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 に答える