web-dev-qa-db-fra.com

Résultats SQL dynamiques dans la table temporaire de la procédure stockée SQL

Le code est comme suit: 

ALTER PROCEDURE dbo.pdpd_DynamicCall 
@SQLString varchar(4096) = null

AS

Begin

    create TABLE #T1 ( column_1 varchar(10) , column_2 varchar(100) )

    insert into #T1 
        execute ('execute ' + @SQLString )

    select * from #T1 

End

Le problème est que je souhaite appeler différentes procédures pouvant restituer différentes colonnes . Par conséquent, je devrais définir le tableau # T1 de manière générique .

Quelqu'un peut-il m'aider sur ce problème?

42
Dhana

Essayer:

SELECT into #T1 execute ('execute ' + @SQLString )

Et cela sent vraiment mauvais comme une vulnérabilité d'injection SQL.


correction (par le commentaire de @ CarpeDiem):

INSERT into #T1 execute ('execute ' + @SQLString )

omettez également le 'execute' si la chaîne SQL est autre chose qu'une procédure

37
Joel Coehoorn

Vous pouvez définir une table de manière dynamique, tout comme vous y insérez de manière dynamique, mais le problème réside dans la portée des tables temporaires. Par exemple, ce code:

DECLARE @sql varchar(max)
SET @sql = 'CREATE TABLE #T1 (Col1 varchar(20))'
EXEC(@sql)
INSERT INTO #T1 (Col1) VALUES ('This will not work.')
SELECT * FROM #T1

retournera avec l'erreur "Nom d'objet invalide '# T1'." En effet, la table temporaire n ° T1 est créée à un "niveau inférieur" par rapport au bloc de code en cours d'exécution. Pour résoudre ce problème, utilisez une table temporaire globale:

DECLARE @sql varchar(max)
SET @sql = 'CREATE TABLE ##T1 (Col1 varchar(20))'
EXEC(@sql)
INSERT INTO ##T1 (Col1) VALUES ('This will work.')
SELECT * FROM ##T1

J'espère que ça aide, Jesse

31
Jesse

Méfiez-vous des solutions de table temporaire globale, car cela peut échouer si deux utilisateurs utilisent la même routine en même temps, car une table globale peut être visualisée par tous les utilisateurs ... 

15
Runonthespot

créer une table temporaire globale avec un GUID dans le nom de manière dynamique. Ensuite, vous pouvez l’utiliser dans votre code, via dyn sql, sans craindre qu’un autre processus appelant le même sproc ne l’utilise. Ceci est utile lorsque vous ne savez pas à quoi vous attendre de la table sélectionnée sous-jacente à chaque exécution, il est donc impossible de créer explicitement une table temporaire auparavant. c'est-à-dire que vous devez utiliser la syntaxe SELECT * INTO

DECLARE @TmpGlobalTable varchar(255) = 'SomeText_' + convert(varchar(36),NEWID())

-- select @TmpGlobalTable 

-- build query
    SET @Sql = 
        'SELECT * INTO [##' + @TmpGlobalTable + '] FROM SomeTable'
EXEC (@Sql)
EXEC ('SELECT * FROM [##' + @TmpGlobalTable + '] ')
EXEC ('DROP TABLE [##' + @TmpGlobalTable + ']')
PRINT 'Dropped Table ' + @TmpGlobalTable 
9
paul
INSERT INTO #TempTable
EXEC(@SelectStatement)
7
MTS

Vous n'êtes pas sûr de bien comprendre, mais vous pourriez peut-être former l'instruction CREATE à l'intérieur d'une chaîne, puis exécuter cette chaîne? De cette façon, vous pouvez ajouter autant de colonnes que vous le souhaitez.

0
Seb
DECLARE @EmpGroup INT =3 ,
        @IsActive BIT=1

DECLARE @tblEmpMaster AS TABLE
        (EmpCode VARCHAR(20),EmpName VARCHAR(50),EmpAddress VARCHAR(500))

INSERT INTO @tblEmpMaster EXECUTE SPGetEmpList @EmpGroup,@IsActive

SELECT * FROM @tblEmpMaster
0
URVISH SUTHAR
CREATE PROCEDURE dbo.pdpd_DynamicCall 
AS
DECLARE @SQLString_2 NVARCHAR(4000)
SET NOCOUNT ON
Begin
    --- Create global temp table
    CREATE TABLE ##T1 ( column_1 varchar(10) , column_2 varchar(100) )

    SELECT @SQLString_2 = 'INSERT INTO ##T1( column_1, column_2) SELECT column_1 = "123", column_2 = "MUHAMMAD IMRON"'
    SELECT @SQLString_2 = REPLACE(@SQLString_2, '"', '''')

    EXEC SP_EXECUTESQL @SQLString_2

    --- Test Display records
    SELECT * FROM ##T1

    --- Drop global temp table 
    IF OBJECT_ID('tempdb..##T1','u') IS NOT NULL
    DROP TABLE ##T1
End
0
Muhammad Imron