Bagaimana cara mendapatkan hasil sp_executesql menjadi variabel?


178

Saya memiliki sepotong SQL dinamis yang perlu saya jalankan, saya kemudian perlu menyimpan hasilnya ke dalam variabel.

Saya tahu saya dapat menggunakan sp_executesqltetapi tidak dapat menemukan contoh yang jelas tentang bagaimana melakukan ini.

Jawaban:


253

Jika Anda memiliki parameter OUTPUT yang dapat Anda lakukan

DECLARE @retval int   
DECLARE @sSQL nvarchar(500);
DECLARE @ParmDefinition nvarchar(500);

DECLARE @tablename nvarchar(50)  
SELECT @tablename = N'products'  

SELECT @sSQL = N'SELECT @retvalOUT = MAX(ID) FROM ' + @tablename;  
SET @ParmDefinition = N'@retvalOUT int OUTPUT';

EXEC sp_executesql @sSQL, @ParmDefinition, @retvalOUT=@retval OUTPUT;

SELECT @retval;

Tetapi jika tidak, dan tidak dapat memodifikasi SP:

-- Assuming that your SP return 1 value
create table #temptable (ID int null)
insert into #temptable exec mysp 'Value1', 'Value2'
select * from #temptable

Tidak cantik, tapi berhasil.


sp saya akan sp_executesql @myQuery
JohnIdol

1
@retvalOUT=@retval OUTPUT? Bukankah seharusnya parameter ketiga dari sp_executesqladil @retval OUTPUT?
Mohammad Dehghan

2
Hanya Pertanyaan Tangensial, Bagaimana dengan lebih dari satu OUTPUT? akan seperti apa tampilan Query?
Srivastav

3
@SrivastavReddy Saya tidak mengerti bagaimana jawaban ini bisa mendapatkan banyak upvotes ini. Periksa jawaban Nishanth ..
sotn

2
Saya pikir ini benar:EXEC sp_executesql @sSQL, @ParmDefinition, @retval OUTPUT;
Ian

50
DECLARE @tab AS TABLE (col1 VARCHAR(10), col2 varchar(10)) 
INSERT into @tab EXECUTE  sp_executesql N'
SELECT 1 AS col1, 2 AS col2
UNION ALL
SELECT 1 AS col1, 2 AS col2
UNION ALL
SELECT 1 AS col1, 2 AS col2'

SELECT * FROM @tab

Saya telah menggunakan metode ini sebelumnya. Sepertinya hanya bekerja pada yang pertama insert into @tab. Jika Anda mencoba insert into @tabdan menjalankan lebih dari satu execute sp_executesql, dengan sql yang berbeda, select * from @tabhanya menunjukkan hasil eksekusi pertama
Mike Causer

Ups, salahku. Ada kesalahan dalam pilih saya yang ke-2, yang berarti mengembalikan baris nol. Metode ini berfungsi dengan baik, dan tidak memerlukan tabel temp!
Mike Causer

Ini jawaban terbaik. Meskipun saya perlu menjalankan SQL dinamis, yang berarti Anda perlu membangun SQL dinamis Anda menjadi parameter pertama yaitu Deklarasikan @SQL nvarchar (255) = N'Seleksi 20 '- maka cukup sl_executeSql melewati parameter sebagai gantinya.
Josh Harris

Solusi ini adalah yang terbaik, saya mencoba banyak yang lain dan ini HANYA yang bekerja untuk saya. Nishanth
MMEL

40
DECLARE @vi INT
DECLARE @vQuery NVARCHAR(1000)

SET @vQuery = N'SELECT @vi= COUNT(*) FROM <TableName>'

EXEC SP_EXECUTESQL 
        @Query  = @vQuery
      , @Params = N'@vi INT OUTPUT'
      , @vi = @vi OUTPUT

SELECT @vi

8
Di mana deklarasi variabel viOUTPUT dan viINT?
Jeson Martajaya

1
Yang ini berhasil untuk saya. Jawaban dengan lebih banyak suara tidak berfungsi
sh_kamalh

5
Parameter @vQuery HARUS dinyatakan sebagai NVARCHAR bukan VARCHAR.
Farzad Karimi


3

Nilai pengembalian umumnya tidak digunakan untuk "mengembalikan" hasil tetapi untuk mengembalikan keberhasilan (0) atau nomor kesalahan (1-65K). Semua di atas tampaknya menunjukkan bahwa sp_executesql tidak mengembalikan nilai, yang tidak benar. sp_executesql akan mengembalikan 0 untuk sukses dan nomor lainnya untuk kegagalan.

Di bawah ini, @ i akan mengembalikan 2727

DECLARE @s NVARCHAR(500)
DECLARE @i INT;
SET @s = 'USE [Blah]; UPDATE STATISTICS [dbo].[TableName] [NonExistantStatisticsName];';
EXEC @i = sys.sp_executesql @s
SELECT @i AS 'Blah'

SSMS akan menampilkan Msg 2727 ini, Level 11, State 1, Line 1 Tidak dapat menemukan indeks 'NonExistantStaticsName'.


2

DECLARE @ValueTable TABLE (Nilai VARCHAR (100))

                    SELECT @sql = N'SELECT SRS_SizeSetDetails.'+@COLUMN_NAME+' FROM SRS_SizeSetDetails WHERE FSizeID = '''+@FSizeID+''' AND SRS_SizeSetID = '''+@SRS_SizeSetID+'''';

                    INSERT INTO @ValueTable
                    EXEC sp_executesql @sql;

                    SET @Value='';

                    SET @Value = (SELECT TOP 1  Value FROM @ValueTable)

                    DELETE FROM @ValueTable

2

Jika Anda ingin mengembalikan lebih dari 1 nilai, gunakan ini:

DECLARE @sqlstatement2      NVARCHAR(MAX);
DECLARE @retText            NVARCHAR(MAX);  
DECLARE @ParmDefinition     NVARCHAR(MAX);
DECLARE @retIndex           INT = 0;

SELECT @sqlstatement = 'SELECT @retIndexOUT=column1 @retTextOUT=column2 FROM XXX WHERE bla bla';

SET @ParmDefinition = N'@retIndexOUT INT OUTPUT, @retTextOUT NVARCHAR(MAX) OUTPUT';

exec sp_executesql @sqlstatement, @ParmDefinition, @retIndexOUT=@retIndex OUTPUT, @retTextOUT=@retText OUTPUT;

nilai yang dikembalikan dalam @retIndex dan @retText


1

Ini sesuatu yang bisa Anda coba

DECLARE  @SqlStatement  NVARCHAR(MAX) = ''
       ,@result     XML
       ,@DatabaseName  VARCHAR(100)
       ,@SchemaName    VARCHAR(10)
       ,@ObjectName    VARCHAR(200);

SELECT   @DatabaseName = 'some database'
       ,@SchemaName   = 'some schema'
       ,@ObjectName   = 'some object (Table/View)'

SET @SqlStatement = '
                    SELECT @result = CONVERT(XML,
                                            STUFF( ( SELECT *
                                                     FROM 
                                                       (
                                                          SELECT TOP(100) 
                                                          * 
                                                          FROM ' + QUOTENAME(@DatabaseName) +'.'+ QUOTENAME(@SchemaName) +'.' + QUOTENAME(@ObjectName) + '
                                                       ) AS A1 
                                                    FOR XML PATH(''row''), ELEMENTS, ROOT(''recordset'')
                                                 ), 1, 0, '''')
                                       )
                ';

EXEC sp_executesql @SqlStatement,N'@result XML OUTPUT', @result = @result OUTPUT;

SELECT DISTINCT
    QUOTENAME(r.value('fn:local-name(.)', 'VARCHAR(200)')) AS ColumnName
FROM @result.nodes('//recordset/*/*') AS records(r)
ORDER BY ColumnName

0

Ini sudah lama sekali, jadi tidak yakin apakah ini masih diperlukan, tetapi Anda bisa menggunakan variabel @@ ROWCOUNT untuk melihat berapa banyak baris yang terpengaruh dengan pernyataan sql sebelumnya.

Ini berguna ketika misalnya Anda membangun pernyataan Pembaruan dinamis dan menjalankannya dengan exec. @@ ROWCOUNT akan menunjukkan berapa banyak baris yang diperbarui.

Inilah definisi


0

Ini bekerja untuk saya:

DECLARE @SQL NVARCHAR(4000)

DECLARE @tbl Table (
    Id int,
    Account varchar(50),
    Amount int
) 

-- Lots of code to Create my dynamic sql statement

insert into @tbl EXEC sp_executesql @SQL

select * from @tbl
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.