194 votes

Un nom de table comme variable

J'essaie d'exécuter cette requête :

declare @tablename varchar(50)
set @tablename = 'test'
select * from @tablename

Cela produit l'erreur suivante :

Msg 1087, Niveau 16, Etat 1, Ligne 5

Doit déclarer la variable de table "@tablename".

Quelle est la bonne façon de faire en sorte que le nom de la table soit rempli de façon dynamique ?

150voto

mdma Points 33973

Pour les requêtes statiques, comme celle de votre question, les noms des tables et des colonnes doivent être statiques.

Pour les requêtes dynamiques, vous devez générer le SQL complet de manière dynamique, et utiliser sp_executesql pour l'exécuter.

Voici un exemple de script utilisé pour comparer les données entre les mêmes tables de différentes bases de données :

Requête statique :

SELECT * FROM [DB_ONE].[dbo].[ACTY]
EXCEPT
SELECT * FROM [DB_TWO].[dbo].[ACTY]

Puisque je veux changer facilement le nom de table y schema J'ai créé cette requête dynamique :

declare @schema varchar(50)
declare @table varchar(50)
declare @query nvarchar(500)

set @schema = 'dbo'
set @table = 'ACTY'

set @query = 'SELECT * FROM [DB_ONE].[' + @schema + '].[' + @table + '] EXCEPT SELECT * FROM [DB_TWO].[' + @schema + '].[' + @table + ']'

EXEC sp_executesql @query

Comme les requêtes dynamiques comportent de nombreux détails à prendre en compte et qu'elles sont difficiles à maintenir, je vous recommande de lire : La malédiction et les bienfaits du SQL dynamique

2 votes

La meilleure pratique pour assembler des noms d'objets dans des instructions SQL dynamiques est d'utiliser QuoteName() pour éviter les problèmes liés aux noms bizarres, par exemple New Table avec un espace ou des mots réservés comme From .

116voto

Tim Points 81

Changez votre dernière déclaration en ceci :

EXEC('SELECT * FROM ' + @tablename)

Voici comment je fais le mien dans une procédure stockée. Le premier bloc déclare la variable et définit le nom de la table en fonction de l'année et du mois en cours, dans ce cas TEST_2012OCTOBER. Je vérifie ensuite si la variable existe déjà dans la base de données, et je la supprime si c'est le cas. Ensuite, le bloc suivant utilise une instruction SELECT INTO pour créer la table et la remplir d'enregistrements provenant d'une autre table avec des paramètres.

--DECLARE TABLE NAME VARIABLE DYNAMICALLY
DECLARE @table_name varchar(max)
SET @table_name =
    (SELECT 'TEST_'
            + DATENAME(YEAR,GETDATE())
            + UPPER(DATENAME(MONTH,GETDATE())) )

--DROP THE TABLE IF IT ALREADY EXISTS
IF EXISTS(SELECT name
          FROM sysobjects
          WHERE name = @table_name AND xtype = 'U')

BEGIN
    EXEC('drop table ' +  @table_name)
END

--CREATES TABLE FROM DYNAMIC VARIABLE AND INSERTS ROWS FROM ANOTHER TABLE
EXEC('SELECT * INTO ' + @table_name + ' FROM dbo.MASTER WHERE STATUS_CD = ''A''')

0 votes

C'est la meilleure réponse.

0 votes

C'est la meilleure réponse car elle est la plus directement applicable au code existant du PO.

41voto

Atul Chaudhary Points 179

Utilisez :

CREATE PROCEDURE [dbo].[GetByName]
    @TableName NVARCHAR(100)
    AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;
    DECLARE @sSQL nvarchar(500);

    SELECT @sSQL = N'SELECT * FROM' + QUOTENAME(@TableName);

    EXEC sp_executesql @sSQL
END

17 votes

Le QUOTENAME est important pour la sécurité. Merci.

3 votes

Mais comment retourner une valeur à partir d'une telle requête ? Par exemple COUNT(*) ?

1 votes

@Suncatcher Vous pourriez avoir un paramètre de sortie ou le retourner comme un ensemble de résultats. Pour montrer comment le lire dans une variable et sans les symboles 'at' en tête des variables en raison des restrictions d'affichage des commentaires : declare nCount int Exec('select nCount = count(*) from ' + sTableName)

37voto

dcp Points 26928

Vous ne pouvez pas utiliser un nom de table pour une variable. Vous devez faire ceci à la place :

DECLARE @sqlCommand varchar(1000)
SET @sqlCommand = 'SELECT * from yourtable'
EXEC (@sqlCommand)

17voto

Paul Kearney - pk Points 3300

Vous devrez générer le contenu SQL de manière dynamique :

declare @tablename varchar(50)

set @tablename = 'test'

declare @sql varchar(500)

set @sql = 'select * from ' + @tablename

exec (@sql)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X