Как выбрать схему на основе переменной?

Рассмотрим:

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 (не позволяя использовать переменные как идентификаторы) или что-то еще?

Ответ 1

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

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

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

Ответ 2

Для этого вам нужно будет использовать инструкцию prepare/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;

Ответ 3

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

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 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 ;