2011-09-30 14 views
11

を考えてみましょう:変数に基づいてスキーマを選択するにはどうすればよいですか?

SET @PREFIX='DEV_'; 

SET @REFRESHDB=CONCAT(@PREFIX,'Refresh'); 

CREATE TABLE @REFRESHDB.`Metadata` 
(
    `Key` VARCHAR(30) NOT NULL, 
    `Value` VARCHAR(30) NOT NULL, 
    PRIMARY KEY (`Key`) 
) ENGINE = InnoDB; 

INSERT INTO @REFRESDB.`Metadata` (`Key`, `Value`) VALUES ("Version", "0"); 

をこれは有効ではないようです:MySQLはして戻ってくる:

あなたのSQL構文でエラーが発生しています。私の知る限り、私はthe documentationに従って正しく物事をやった言うことができるようにREFRESHDB.`Metadata`

@」付近に使用する権利構文についてはMySQLサーバのバージョンに対応するマニュアルを確認してください。しかし、MySQLは許可されていないと言います。これは、MySQLのいくつかの制限(識別子としての変数の使用を許可しない)なのでしょうか?

答えて

3

ドキュメントの状態:

「ユーザー変数から値を割り当てることができます整数型、10進数型、浮動小数点型、バイナリ型または非バイナリ型の文字列、またはNULL値 "

変数をオブジェクトとして使用しようとしています。これはサポートされていません。

+0

変数が使用できる変数コントロールに何が割り当てられるのかわかりません。 –

+0

'@ REFRESHDB'の値が実際には文字列値ではなく、スキーマオブジェクトであることを意味するオブジェクトとして使用しています。 –

+1

コメントしますか? –

8

これを行うには、prepare statement/dynamic sqlを使用する必要があります。

この記事では、優れ詳細にこれらの両方の上に行く:

http://rpbouman.blogspot.com/2005/11/mysql-5-prepared-statement-syntax-and.html

これを試してみてください:

SET @PREFIX='DEV_'; 

SET @REFRESHDB=CONCAT(@PREFIX,'Refresh'); 

SET @st = CONCAT('CREATE TABLE ', @REFRESHDB,'.`Metadata` 
(
    `Key` VARCHAR(30) NOT NULL, 
    `Value` VARCHAR(30) NOT NULL, 
    PRIMARY KEY (`Key`) 
) ENGINE = InnoDB'); 

PREPARE tStmt FROM @s; 
EXECUTE tStmt; 


SET @s = CONCAT('INSERT INTO ', @PREFIX, '.`Metadata` (`Key`, `Value`) VALUES ("Version", "0")'); 

PREPARE stmt FROM @s; 
EXECUTE stmt; 
+0

CREATE TABLE文は失敗します。 –

+0

ああ、私はそれを逃しました、あなたは準備された声明にそれを入れなければなりません。私はそれを更新して、作成したテーブルを準備されたステートメントに入れました。 –

+0

この修正により、あなたは何をしていますか?これを実装しようとする人は、セキュリティとパフォーマンスの考慮事項に注意してください。 動的SQLは、わずかな黒い芸術です。 –

0

私は、ストアドプロシージャを記述することをお勧め:

DELIMITER $$ 
CREATE PROCEDURE (IN DBname varchar(255) 
       , IN AKey varchar(255) 
       , IN AValue varchar(255)) 
BEGIN 
    DECLARE query VARCHAR(1000); 
    -- First check the DBName against a list of allowed DBnames, 
    -- to prevent SQL-injection with dynamic tablenames. 

    DECLARE NameAllowed BOOLEAN; 
    SELECT 1 INTO NameAllowed WHERE DBName IN ('validDB1','validDB2'); 
    IF (NameAllowed = 1) THEN BEGIN 

    -- DBName is in the whitelist, it's safe to continue. 
    SET query = CONCAT('INSERT INTO ' 
         ,DBName 
         ,'.MetaData (`key`,`value`) values (?,?)); 
    -- note the use of parameter placeholders, to prevent SQL-injection. 
    PREPARE stmt FROM query; 
    EXECUTE stmt USING Akey, AValue; 
    DEALLOCATE PREPARE stmt; -- clears the query and its result from the cache. 
    END; END IF; 
END $$ 

DELIMITER ; 
+0

これは、挿入ではなくCREATE TABLE文で失敗しています。 –

関連する問題