Bir değişkene sp_executesql sonucu nasıl alınır?


178

Çalıştırmam gereken dinamik SQL parçam var, sonucu değişkene kaydetmem gerekiyor.

Kullanabileceğimi biliyorum, sp_executesqlancak bunun nasıl yapılacağı hakkında net örnekler bulamıyorum.

Yanıtlar:


253

OUTPUT parametreleriniz varsa yapabilirsiniz

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;

Ancak SP'yi değiştirmezseniz ve değiştiremezseniz:

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

Güzel değil, ama işe yarıyor.


benim sp olacak sp_executesql @myQuery
JohnIdol

1
@retvalOUT=@retval OUTPUT? Üçüncü parametre sp_executesqlsadece olmamalı @retval OUTPUTmı?
Muhammed Dehghan

2
Sadece teğetsel bir soru, Birden fazla ÇIKIŞ ne olacak? Sorgu nasıl olurdu?
Srivastav

3
@SrivastavReddy Bu cevabı nasıl bu kadar çok oy alabilir ki anlamıyorum. Nishanth'ın cevabını kontrol edin ..
17'de

2
Bunun doğru olduğunu düşünüyorum: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

Bu yöntemi daha önce kullandım. Sadece ilk üzerinde çalışıyor gibi görünüyor insert into @tab. Farklı sql ile insert into @tabbirden fazla çalıştırmaya çalışırsanız execute sp_executesql, select * from @tabyalnızca ilk yürütmenin sonuçlarını gösterir
Mike Causer

Hata! 2. seçimimde bir hata vardı, bu da sıfır satır döndürdüğü anlamına geliyordu. Bu yöntem harika çalışıyor ve geçici bir tablo gerektirmiyor!
Mike Causer

Bu en iyi cevap. Her ne kadar dinamik SQL çalıştırmam gerekiyorsa, bu da dinamik SQL'inizi önce bir parametreye inşa etmeniz gerektiği anlamına gelir, yani Declare @SQL nvarchar (255) = N'Select 20 '- daha sonra parametrenin yerine geçen sl_executeSql.
Josh Harris

Bu çözüm en iyisi, ben birçok başka denedim ve bu benim için çalışan SADECE. Teşekkür ederim 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
ViOUTPUT ve viINT değişkeninin bildirimi nerede?
Jeson Martajaya

1
Bu benim için çalıştı. Daha fazla oy içeren cevap işe yaramadı
sh_kamalh

5
@VQuery parametresi VARCHAR olarak değil, NVARCHAR olarak bildirilmelidir ZORUNLU .
Farzad Karimi


3

Dönüş değerleri genellikle bir sonucu "döndürmek" için değil, başarıyı (0) veya bir hata numarasını (1-65K) döndürmek için kullanılır. Yukarıdakilerin hepsi, sp_executesql öğesinin doğru olmayan bir değer döndürmediğini gösterir. sp_executesql, başarı için 0 ve başarısızlık için başka herhangi bir sayı döndürür.

Aşağıda @ i 2727 döndürecek

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 bu Msg 2727, Seviye 11, Durum 1, Satır 1 'NonExistantStaticsName' dizini bulunamıyor gösterecektir.


2

DECLARE @ValueTable TABLO (Değer 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

1'den fazla değer döndürmek istiyorsanız bunu kullanın:

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;

döndürülen değerler @retIndex ve @retText'te


1

İşte deneyebileceğiniz bir şey

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

Bu uzun zaman önceydi, bu yüzden hala gerekli olup olmadığından emin değilim, ancak önceki sql deyiminden kaç satır etkilendiğini görmek için @@ ROWCOUNT değişkenini kullanabilirsiniz.

Örneğin, dinamik bir Update deyimi oluşturup exec ile çalıştırdığınızda bu yararlı olur. @@ ROWCOUNT kaç satır güncellendiğini gösterir.

İşte tanımı


0

Bu benim için çalıştı:

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.