mysqlにプロシージャ解決パラメータをテーブル名として格納


キーワード:mysqlストレージ・プロシージャ
1.変数をテーブル名として使用:
簡単にsetまたはdeclare文で変数を定義し、sqlのテーブル名として直接使用することはできません.mysqlは変数名をテーブル名として使用します.他のsqlデータベースでも、mssqlの解決策は、sql文全体を変数とし、変数をテーブル名として挿入し、sp_を使用することです.executesqlは文を呼び出します.
これはmysql 5にあります.0以前はだめでしたが、5.0以降にsp_のような新しい文が導入されました.executesqlの機能(procedureのみ有効、functionはダイナミッククエリーをサポートしません):
PREPARE stmt_name FROM preparable_stmt;
EXECUTE stmt_name [USING @var_name [, @var_name] ...];
{DEALLOCATE | DROP} PREPARE stmt_name;
感性的な認識を持つために、
次に、いくつかの例を示します.
mysql> PREPARE stmt1 FROM 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
mysql> SET @a = 3;
mysql> SET @b = 4;
mysql> EXECUTE stmt1 USING @a, @b;
+------------+
| hypotenuse |
+------------+
| 5 |
+------------+
mysql> DEALLOCATE PREPARE stmt1;
mysql> SET @s = 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
mysql> PREPARE stmt2 FROM @s;
mysql> SET @a = 6;
mysql> SET @b = 8;
mysql> EXECUTE stmt2 USING @a, @b;
+------------+
| hypotenuse |
+------------+
| 10 |
+------------+
mysql> DEALLOCATE PREPARE stmt2;
MySQLバージョンが5.0.7以上の場合は、LIMIT句で使用することもできます.例は次のとおりです.
mysql> SET @a=1;mysql> PREPARE STMT FROM "SELECT * FROM tbl LIMIT ?";
mysql> EXECUTE STMT USING @a;
mysql> SET @skip=1; SET @numrows=5;
mysql> PREPARE STMT FROM "SELECT * FROM tbl LIMIT ?, ?";
mysql> EXECUTE STMT USING @skip, @numrows;
PREPAREを使用するいくつかの注意点:
A:PREPARE stmt_name FROM preparable_stmt;文を事前に定義し、stmt_に割り当てます.name ,tmt_name
大文字と小文字を区別しません.
B:preparable_でもstmt文の?文字列を表していますが、あなたも必要ありませんか?引用符で囲みます.
C:新しいPREPARE文が既存のstmt_を使用している場合name、元のものはすぐに解放されます!この新しいPREPARE文がエラーで正しく実行されなくても.
D: PREPARE stmt_nameの役割ドメインは、現在のクライアント接続セッションが表示されます.
E:事前定義された文のリソースを解放するには、DEALLOCATE PREPARE構文を使用します.
F: EXECUTE stmt_name構文でstmt_nameが存在しない場合、エラーが発生します.
G:クライアント接続セッションの終了時にDEALLOCATE PREPARE構文を明示的に呼び出してリソースを解放しない場合、サーバ側はそれを自動的に解放します.
H:事前定義文では、CREATE TABLE、DELETE、DO、INSERT、REPLACE、SELECT、SET、UPDATE、および大部分のSHOW構文がサポートされています.
I:PREPARE文は、ストアド・プロシージャ、カスタム関数には使用できません.ただし、MySQL 5.0.13からは、ストレージ・プロシージャに使用できますが、関数での使用はサポートされていません.
次に例を示します.
Javaコード
  • CREATE PROCEDURE `p1`(IN id INT UNSIGNED,IN name VARCHAR( 11 ))  
  • BEGIN lable_exit:  
  • BEGIN  
  • SET @SqlCmd  =  'SELECT * FROM tA ' ;  
  • IF id IS NOT NULL THEN  
  • SET @SqlCmd  = CONCAT( @SqlCmd  ,  'WHERE id=?' );  
  • PREPARE stmt FROM @SqlCmd ;  
  • SET @a  = id;  
  • EXECUTE stmt USING @a ;  
  • LEAVE lable_exit;  
  • END IF;  
  • IF name IS NOT NULL THEN  
  • SET @SqlCmd  = CONCAT( @SqlCmd  ,  'WHERE name LIKE ?' );  
  • PREPARE stmt FROM @SqlCmd ;  
  • SET @a  = CONCAT(name,  '%' );  
  • EXECUTE stmt USING @a ;  
  • LEAVE lable_exit;  
  • END IF;  
  • END lable_exit;  
  • END;  
  • CALL `p1`(1 ,NULL);  
  • CALL `p1`(NULL,'QQ' );  
  • DROP PROCEDURE `p1`;  
  • CREATE PROCEDURE `p1`(IN id INT UNSIGNED,IN name VARCHAR(11))
    BEGIN lable_exit:
    BEGIN
    SET @SqlCmd = 'SELECT * FROM tA ';
    IF id IS NOT NULL THEN
    SET @SqlCmd = CONCAT(@SqlCmd , 'WHERE id=?');
    PREPARE stmt FROM @SqlCmd;
    SET @a = id;
    EXECUTE stmt USING @a;
    LEAVE lable_exit;
    END IF;
    IF name IS NOT NULL THEN
    SET @SqlCmd = CONCAT(@SqlCmd , 'WHERE name LIKE ?');
    PREPARE stmt FROM @SqlCmd;
    SET @a = CONCAT(name, '%');
    EXECUTE stmt USING @a;
    LEAVE lable_exit;
    END IF;
    END lable_exit;
    END;
    CALL `p1`(1,NULL);
    CALL `p1`(NULL,'QQ');
    DROP PROCEDURE `p1`;

    PREPAREの使い方を知って、変数で表名を作るのは簡単です.しかし、実際の操作中には、変数定義、declare変数、set@var=value変数の使用、パラメータが入力する変数など、他の問題も発見されました.
    テストの結果、set@var=valueのように定義された変数は文字列に直接書くと変数変換として扱われ、declareの変数とパラメータが入力された変数はCONCATで接続する必要があることが分かった.具体的な原理は研究されていない.
    EXECUTE stmt USING @a;このような文USINGの後の変数もset@var=valueというようにdeclareやパラメータが入ってくる変数ではだめです.
    またphpがmysqlストレージ・プロシージャを呼び出す際にも多くの問題が発生し、PROCEDURE p can't return a result set in the given contextという問題が発生します.
    変換元:http://jspengxue.javaeye.com/blog/46712