2010-05-02 5 views
23

Je suis en train de passer un nom de table dans mon mysql procédure stockée à utiliser cette procédure stockée pour sélectionner hors des tables différentes, mais il ne fonctionne pas ...utiliser une variable pour le nom de la table dans une base MySQL sproc

c'est ce que I "m essayer:

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

J'ai aussi essayé w/o le signe @ et qui me dit juste que TableName n'existe pas ... que je sais :)

Répondre

12

cela dépend le SGBD, mais la notation nécessite généralement SQL dynamique, et se heurte au problème que les valeurs de retour de la f l'onction dépend des entrées quand elle est exécutée. Cela donne les connivences du système. En règle générale (et donc probablement sujet à 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 tables ou les noms de colonnes; ils vous permettent uniquement d'indiquer des valeurs telles que les valeurs de colonne.

Certains SGBD ont une prise en charge de procédure stockée qui vous permettra de créer une chaîne SQL, puis de travailler avec celle-ci, en utilisant 'prepare' ou 'execute immediate' 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 capable de contrôler, en partie, ce que SQL est exécuté.

44
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; 
+0

WOW, quelle chance manière liant! –

12

Un bit supplémentaire qui m'a causé des problèmes.

Je voulais définir le nom de la table et le champ dynamique dans une requête comme @kyle a demandé, mais je voulais aussi stocker le résultat de cette requête dans une variable @a dans la requête. Au lieu de placer littéralement la variable @a dans le concat, 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 ; 

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

') INTO @a FROM '

Puis, en @sql_text2 utilisation @a comme une variable réelle:

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

Questions connexes