Как выбрать схему на основе переменной? - PullRequest
11 голосов
/ 30 сентября 2011

Рассмотрим:

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; проверьте руководство, соответствующее вашей версии сервера MySQL, чтобы узнать правильный синтаксис для использования рядом с'@REFRESHDB`. Metadata`

Насколько я могу судить, я все сделал правильно, согласно документации . Тем не менее MySQL говорит, что это не разрешено. Это какое-то ограничение MySQL (не позволяющее использовать переменные в качестве идентификаторов) или что-то еще?

Ответы [ 3 ]

8 голосов
/ 30 сентября 2011

Для этого вам понадобится подготовить оператор / динамический 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;
3 голосов
/ 30 сентября 2011

Документация гласит:

«Пользовательским переменным может быть присвоено значение из ограниченного набора типов данных: целочисленная, десятичная, с плавающей точкой, двоичная или недвоичная строка или значение NULL»

Вы пытаетесь использовать переменную в качестве объекта. Это не поддерживается.

0 голосов
/ 30 сентября 2011

Я бы предложил вам написать хранимую процедуру:

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 ;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...