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?
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
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
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 ...
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
INSERT INTO #TempTable
EXEC(@SelectStatement)
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.
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
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