web-dev-qa-db-fra.com

utiliser une variable pour le nom de la table dans mysql sproc

J'essaie de passer un nom de table dans ma procédure stockée mysql pour utiliser ce sproc pour sélectionner des tables différentes mais cela ne fonctionne pas ...

c'est ce que j'essaye:

CREATE PROCEDURE `usp_SelectFromTables`(
 IN TableName varchar(100)
)
BEGIN
        SELECT * FROM @TableName;
END

Je l'ai également essayé sans signe @ et cela me dit simplement que TableName n'existe pas ... ce que je sais :)

26
Kyle

Cela dépend du SGBD, mais la notation nécessite généralement Dynamic SQL et pose le problème que les valeurs de retour de la fonction dépendent des entrées lors de son exécution. Cela donne les conniptions du système. En règle générale (et donc probablement soumis à des exceptions), les SGBD ne vous permettent pas d'utiliser des espaces réservés (paramètres) pour les éléments structurels d'une requête tels que les noms de table ou les noms de colonne; ils vous permettent uniquement de spécifier des valeurs telles que des valeurs de colonne.

Certains SGBD ont une prise en charge des procédures stockées qui vous permettra de créer une chaîne SQL, puis de travailler avec, en utilisant des opérations "préparer" ou "exécuter immédiatement" ou des opérations similaires. Notez, cependant, que vous êtes soudainement vulnérable aux attaques par injection SQL - quelqu'un qui peut exécuter votre procédure est alors en mesure de contrôler, en partie, ce que SQL est exécuté.

13
SET @cname:='jello';
SET @vname:='dwb';
SET @sql_text = concat('select concept_id,concept_name,',@vname,' from enc2.concept a JOIN enc2.ratings b USING(concept_id) where concept_name like (''%',@cname,'%'') and 3 is not null order by 3 asc');

PREPARE stmt FROM @sql_text;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
54
Angelo

Un petit plus qui m'a causé des problèmes.

Je voulais définir le nom et le champ de la table dynamiquement dans une requête comme le demandait @kyle, mais je voulais également stocker le résultat de cette requête dans une variable @a dans la requête.

Au lieu de mettre la variable @a dans le concat littéralement, vous devez l'inclure dans le texte de la chaîne.

delimiter //

CREATE PROCEDURE removeProcessed(table_name VARCHAR(255), keyField VARCHAR(255), maxId INT, num_rows INT)

BEGIN
  SET @table_name = table_name;
  SET @keyField = keyField;
  SET @maxId = maxId;
  SET @num_rows = num_rows;

  SET @sql_text1 = concat('SELECT MIN(',@keyField,') INTO @a FROM ',@table_name);
  PREPARE stmt1 FROM @sql_text1;
  EXECUTE stmt1;
  DEALLOCATE PREPARE stmt1;

  loop_label:  LOOP
    SET @sql_text2 = concat('SELECT ',@keyField,' INTO @z FROM ',@table_name,' WHERE ',@keyField,' >= ',@a,' ORDER BY ',@keyField,' LIMIT ',@num_rows,',1');
    PREPARE stmt2 FROM @sql_text2;
    EXECUTE stmt2;
    DEALLOCATE PREPARE stmt2;

    ...Additional looping code...

    END LOOP;
END
//

delimiter ;

Donc, dans @sql_text1 affecter le résultat de la requête à @a dans la chaîne en utilisant:

') INTO @a FROM '

Puis dans @sql_text2 utilisation @a comme variable réelle:

,' WHERE ',@keyField,' >= ',@une,' ORDER BY '

14
codewaggle