Aracılığıyla paylaş


sp_executesql (Transact-SQL)

Şunlar için geçerlidir:SQL ServerAzure SQL VeritabanıAzure SQL Yönetilen ÖrneğiAzure Synapse AnalyticsAnalytics Platform Sistemi (PDW)Microsoft FabricWarehouse'da SQL analiz uç noktası

Birçok kez yeniden kullanılabilecek bir Transact-SQL deyimini veya toplu işlemini ya da dinamik olarak oluşturulan bir deyimini yürütür. Transact-SQL deyimi veya toplu işlemi katıştırılmış parametreler içerebilir.

Dikkat

Çalışma zamanı derlenmiş Transact-SQL deyimleri uygulamaları kötü amaçlı saldırılara maruz bırakabiliyor. sp_executesqlkullanırken sorgularınızı parametreleştirmelisiniz. Daha fazla bilgi için bkz. sql ekleme .

Transact-SQL söz dizimi kuralları

Sözdizimi

SQL Server, Azure SQL Veritabanı, Azure SQL Yönetilen Örneği, Azure Synapse Analytics ve Analytics Platform Sistemi (PDW) için söz dizimi.

sp_executesql [ @stmt = ] N'statement'
[
    [ , [ @params = ] N'@parameter_name data_type [ { OUT | OUTPUT } ] [ , ...n ]' ]
    [ , [ @param1 = ] 'value1' [ , ...n ] ]
]

Bu makaledeki kod örnekleri, AdventureWorks2022 giriş sayfasından indirebileceğiniz AdventureWorksDW2022 veya örnek veritabanını kullanır.

Bağımsız değişken

Önemli

Genişletilmiş saklı yordamlar için bağımsız değişkenler, Sözdizimi bölümünde açıklandığı gibi belirli bir sırada girilmelidir. Parametreler sıra dışı girilirse bir hata iletisi oluşur.

[ @stmt = ] N'deyimi'

Transact-SQL deyimi veya toplu işlemi içeren bir Unicode dizesi. @stmt bir Unicode sabiti veya Unicode değişkeni olmalıdır. İki dizeyi + işleciyle birleştirmek gibi daha karmaşık Unicode ifadelerine izin verilmez. Karakter sabitlerine izin verilmez. Unicode sabitlerine bir Nön eki eklenmelidir. Örneğin, Unicode sabiti N'sp_who' geçerlidir, ancak karakter sabiti 'sp_who' geçerli değildir. Dizenin boyutu yalnızca kullanılabilir veritabanı sunucusu belleğiyle sınırlıdır. 64 bit sunucularda, dizenin boyutu 2 GB ile sınırlıdır; en büyük boyut nvarchar(max).

@stmt, değişken adıyla aynı forma sahip parametreler içerebilir. Mesela:

N'SELECT * FROM HumanResources.Employee WHERE EmployeeID = @IDParameter';

@stmt dahil edilen her parametrenin hem @params parametre tanımı listesinde hem de parametre değerleri listesinde karşılık gelen bir girdisi olmalıdır.

[ @params = ] N'@parameter_namedata_type [ , ... n ]'

@stmteklenmiş tüm parametrelerin tanımlarını içeren bir dize. Dize bir Unicode sabiti veya Unicode değişkeni olmalıdır. Her parametre tanımı bir parametre adından ve bir veri türünden oluşur. n, daha fazla parametre tanımını gösteren bir yer tutucudur. @stmt'de belirtilen her parametre @paramsiçinde tanımlanmalıdır. @stmt'daki Transact-SQL deyimi veya toplu işlemi parametre içermiyorsa @params gerekli değildir. Bu parametrenin varsayılan değeri NULL.

[ @param1 = ] 'value1'

Parametre dizesinde tanımlanan ilk parametre için bir değer. Değer bir Unicode sabiti veya Unicode değişkeni olabilir. @stmtdahil edilen her parametre için bir parametre değeri sağlanmalıdır. @stmt'daki Transact-SQL deyiminde veya toplu işte parametre olmadığında değerler gerekli değildir.

{ OUT | OUTPUT }

Parametresinin bir çıkış parametresi olduğunu gösterir. metin, ntextve görüntü parametreleri, yordam ortak dil çalışma zamanı (CLR) yordamı olmadığı sürece OUTPUT parametreleri olarak kullanılabilir. OUTPUT anahtar sözcüğünü kullanan bir çıkış parametresi, yordam bir CLR yordamı olmadığı sürece imleç yer tutucusu olabilir.

[ ... n ]

Ek parametrelerin değerleri için yer tutucu. Değerler yalnızca sabitler veya değişkenler olabilir. Değerler, işlevler gibi daha karmaşık ifadeler veya işleçler kullanılarak oluşturulan ifadeler olamaz.

Dönüş kodu değerleri

0 (başarı) veya sıfır olmayan (başarısızlık).

Sonuç kümesi

SQL dizesinde yerleşik olarak bulunan tüm SQL deyimlerinden sonuç kümelerini döndürür.

Açıklamalar

sp_executesql parametreleri, bu makalenin önceki bölümlerindeki Sözdizimi bölümünde açıklandığı gibi belirli bir sırada girilmelidir. Parametreler sıra dışı girilirse bir hata iletisi oluşur.

sp_executesql toplu işler, adların kapsamı ve veritabanı bağlamı ile ilgili EXECUTE aynı davranışa sahiptir. sp_executesql deyimi yürütülene kadar sp_executesql parametresindeki Transact-SQL deyimi veya toplu işlemi derlenmemiştir. @stmt içeriği daha sonra derlenir ve sp_executesqladlı toplu işlemin yürütme planından ayrı bir yürütme planı olarak yürütülür. sp_executesql toplu işlemi, sp_executesqlçağıran toplu işte bildirilen değişkenlere başvuramaz. sp_executesql toplu işlemindeki yerel imleçler veya değişkenler, sp_executesqlçağıran toplu iş tarafından görünmez. Veritabanı bağlamındaki değişiklikler yalnızca sp_executesql deyiminin sonuna kadar sürer.

sp_executesql, bir Transact-SQL deyimini birçok kez yürütmek için saklı yordamlar yerine, deyimdeki parametre değerlerindeki değişiklik tek varyasyon olduğunda kullanılabilir. Transact-SQL deyiminin kendisi sabit kaldığından ve yalnızca parametre değerleri değiştiğinden, SQL Server sorgu iyileştiricisinin ilk yürütme için oluşturduğu yürütme planını yeniden kullanma olasılığı yüksektir. Bu senaryoda performans, saklı yordamla eşdeğerdir.

Not

Performansı geliştirmek için deyim dizesinde tam nesne adlarını kullanın.

sp_executesql, aşağıdaki örnekte gösterildiği gibi parametre değerlerinin Transact-SQL dizesinden ayrı olarak ayarlanmasını destekler.

DECLARE @IntVariable AS INT;
DECLARE @SQLString AS NVARCHAR (500);
DECLARE @ParmDefinition AS NVARCHAR (500);

/* Build the SQL string once */
SET @SQLString = N'SELECT BusinessEntityID, NationalIDNumber, JobTitle, LoginID
       FROM AdventureWorks2022.HumanResources.Employee
       WHERE BusinessEntityID = @BusinessEntityID';

SET @ParmDefinition = N'@BusinessEntityID tinyint';

/* Execute the string with the first parameter value. */
SET @IntVariable = 197;

EXECUTE sp_executesql
    @SQLString,
    @ParmDefinition,
    @BusinessEntityID = @IntVariable;

/* Execute the same string with the second parameter value. */
SET @IntVariable = 109;

EXECUTE sp_executesql
    @SQLString,
    @ParmDefinition,
    @BusinessEntityID = @IntVariable;

Çıkış parametreleri sp_executesqlile de kullanılabilir. Aşağıdaki örnek, HumanResources.Employee örnek veritabanındaki AdventureWorks2022 tablosundan bir iş başlığı alır ve bunu @max_titleçıkış parametresinde döndürür.

DECLARE @IntVariable AS INT;
DECLARE @SQLString AS NVARCHAR (500);
DECLARE @ParmDefinition AS NVARCHAR (500);
DECLARE @max_title AS VARCHAR (30);

SET @IntVariable = 197;

SET @SQLString = N'SELECT @max_titleOUT = max(JobTitle)
   FROM AdventureWorks2022.HumanResources.Employee
   WHERE BusinessEntityID = @level';

SET @ParmDefinition = N'@level TINYINT, @max_titleOUT VARCHAR(30) OUTPUT';

EXECUTE sp_executesql
    @SQLString,
    @ParmDefinition,
    @level = @IntVariable,
    @max_titleOUT = @max_title OUTPUT;

SELECT @max_title;

sp_executesql'da parametreleri değiştirebilmek, bir dize yürütmek için EXECUTE deyimini kullanmaya göre aşağıdaki avantajları sunar:

  • sp_executesql dizesindeki Transact-SQL deyiminin gerçek metni yürütmeler arasında değişmediğinden, sorgu iyileştiricisi büyük olasılıkla ikinci yürütmedeki Transact-SQL deyimini ilk yürütme için oluşturulan yürütme planıyla eşleştirir. Bu nedenle, SQL Server'ın ikinci deyimini derlemesi gerekmez.

  • Transact-SQL dizesi yalnızca bir kez oluşturulur.

  • Tamsayı parametresi kendi yerel biçiminde belirtilir. Unicode'a atama gerekli değildir.

OPTIMIZED_SP_EXECUTESQL

Şunlar için geçerlidir: Microsoft Fabric'te SQL Server 2025 (17.x) Önizleme, Azure SQL Veritabanı ve SQL veritabanı

veritabanı kapsamlı yapılandırma OPTIMIZED_SP_EXECUTESQL etkinleştirildiğinde, sp_executesql kullanılarak gönderilen toplu işlemlerin derleme davranışı, saklı yordamlar ve tetikleyiciler gibi nesnelerin şu anda kullandığı serileştirilmiş derleme davranışıyla aynı olur.

Toplu işler özdeş olduğunda (parametre farklılıkları hariç), OPTIMIZED_SP_EXECUTESQL seçeneği derleme işleminin seri hale getirildiğini garanti etmek için zorlama mekanizması olarak bir derleme kilidi elde etmeye çalışır. Bu kilit, birden çok oturum aynı anda sp_executesql çağırırsa, ilk oturum derleme işlemini başlatıldıktan sonra özel derleme kilidi elde etmeye çalışırken bu oturumların beklemesini sağlar. sp_executesql ilk yürütmesi derlenmiş planını derler ve plan önbelleğine ekler. Diğer oturumlar derleme kilidinde beklemeyi durdurur ve kullanılabilir duruma geldikten sonra planı yeniden kullanabilir.

OPTIMIZED_SP_EXECUTESQL seçeneği olmadan, sp_executesql aracılığıyla yürütülen aynı toplu işlemlerin birden çok çağrısı paralel olarak derlenir ve bazı durumlarda plan önbelleği girdilerinin yerini alan veya yinelenen plan önbelleğine kendi derlenmiş planının kopyalarını yerleştirir.

Not

OPTIMIZED_SP_EXECUTESQL veritabanı kapsamlı yapılandırmasını etkinleştirmeden önce, otomatik güncelleştirme istatistikleri etkinleştirildiyse, ASYNC_STATS_UPDATE_WAIT_AT_LOW_PRIORITY veritabanı kapsamlı yapılandırma seçeneğiyle otomatik güncelleştirme istatistikleri zaman uyumsuz seçeneğini de etkinleştirmeniz gerekir. Bu iki seçeneğin etkinleştirilmesi, uzun derleme süreleriyle ilgili performans sorunlarının aşırı, kilit yöneticisi özel kilitleri (LCK_M_X) ve WAIT_ON_SYNC_STATISTICS_REFRESH beklemeleri olasılığını önemli ölçüde azaltabilir.

OPTIMIZED_SP_EXECUTESQL varsayılan olarak kapalıdır. veritabanı düzeyinde OPTIMIZED_SP_EXECUTESQL etkinleştirmek için aşağıdaki Transact-SQL deyimini kullanın:

ALTER DATABASE SCOPED CONFIGURATION SET OPTIMIZED_SP_EXECUTESQL = ON;

İzinler

genel rolüne üyelik gerektirir.

Örnekler

A. SELECT deyimi yürütme

Aşağıdaki örnek, SELECTadlı katıştırılmış parametreyi içeren bir @level deyimi oluşturur ve yürütür.

EXECUTE sp_executesql N'SELECT * FROM AdventureWorks2022.HumanResources.Employee
    WHERE BusinessEntityID = @level', N'@level TINYINT', @level = 109;

B. Dinamik olarak oluşturulmuş bir dize yürütme

Aşağıdaki örnekte, dinamik olarak oluşturulmuş bir dize yürütmek için sp_executesql kullanımı gösterilmektedir. Örnek saklı yordam, bir yıl boyunca satış verilerini bölümlendirmek için kullanılan bir tablo kümesine veri eklemek için kullanılır. Yılın her ayı için aşağıdaki biçime sahip bir tablo vardır:

CREATE TABLE May1998Sales
(
    OrderID INT PRIMARY KEY,
    CustomerID INT NOT NULL,
    OrderDate DATETIME NULL CHECK (DATEPART(yy, OrderDate) = 1998),
    OrderMonth INT CHECK (OrderMonth = 5),
    DeliveryDate DATETIME NULL,
    CHECK (DATEPART(mm, OrderDate) = OrderMonth)
);

Bu örnek saklı yordam, doğru tabloya yeni siparişler eklemek için dinamik olarak bir INSERT deyimi oluşturur ve yürütür. Örnek, verileri içermesi gereken tablonun adını oluşturmak için sipariş tarihini kullanır ve ardından bu adı bir INSERT deyimine ekler.

Not

Bu, sp_executesqliçin temel bir örnektir. Örnekte hata denetimi yoktur ve sipariş numaralarının tablolar arasında yinelenmeyeceklerini garanti etme gibi iş kuralları denetimleri yoktur.

CREATE PROCEDURE InsertSales (
    @PrmOrderID INT,
    @PrmCustomerID INT,
    @PrmOrderDate DATETIME,
    @PrmDeliveryDate DATETIME
)
AS
DECLARE @InsertString AS NVARCHAR (500);
DECLARE @OrderMonth AS INT;
-- Build the INSERT statement.
SET @InsertString = 'INSERT INTO ' +
    /* Build the name of the table. */
    SUBSTRING(DATENAME(mm, @PrmOrderDate), 1, 3)
    + CAST (DATEPART(yy, @PrmOrderDate) AS CHAR (4)) + 'Sales' +
    /* Build a VALUES clause. */
    ' VALUES (@InsOrderID, @InsCustID, @InsOrdDate,'
    + ' @InsOrdMonth, @InsDelDate)';

/* Set the value to use for the order month because
   functions are not allowed in the sp_executesql parameter
   list. */
SET @OrderMonth = DATEPART(mm, @PrmOrderDate);
EXECUTE sp_executesql
    @InsertString, N'@InsOrderID INT, @InsCustID INT, @InsOrdDate DATETIME, @InsOrdMonth INT, @InsDelDate DATETIME',
    @PrmOrderID,
    @PrmCustomerID,
    @PrmOrderDate,
    @OrderMonth,
    @PrmDeliveryDate;
GO

Bu yordamda sp_executesql kullanmak, parametre işaretçilerinin kullanılmasına izin verdiğinden dinamik olarak oluşturulan dizeyi yürütmek için EXECUTE kullanmaktan daha verimlidir. Parametre işaretçileri, Veritabanı Altyapısı'nın oluşturulan sorgu planını yeniden kullanma olasılığını daha yüksektir ve bu da ek sorgu derlemelerini önlemeye yardımcı olur. EXECUTEile, parametre değerleri farklı olduğundan ve dinamik olarak oluşturulan dizenin sonuna eklendiğinden her INSERT dizesi benzersizdir. Yürütülürken sorgu, planın yeniden kullanılmasını teşvik edecek şekilde parametrelendirilmeyecek ve her INSERT deyimi yürütülmeden önce derlenmelidir ve bu da sorgunun plan önbelleğine ayrı bir önbelleğe alınmış girdisini ekler.

C. OUTPUT parametresini kullanma

Aşağıdaki örnek, OUTPUT deyimi tarafından oluşturulan sonuç kümesini SELECT parametresinde depolamak için bir @SQLString parametresi kullanır. Ardından SELECT parametresinin değerini kullanan iki OUTPUT deyimi yürütülür.

USE AdventureWorks2022;
GO

DECLARE @SQLString AS NVARCHAR (500);
DECLARE @ParmDefinition AS NVARCHAR (500);
DECLARE @SalesOrderNumber AS NVARCHAR (25);
DECLARE @IntVariable AS INT;

SET @SQLString = N'SELECT @SalesOrderOUT = MAX(SalesOrderNumber)
    FROM Sales.SalesOrderHeader
    WHERE CustomerID = @CustomerID';

SET @ParmDefinition = N'@CustomerID INT,
    @SalesOrderOUT NVARCHAR(25) OUTPUT';

SET @IntVariable = 22276;

EXECUTE sp_executesql
    @SQLString,
    @ParmDefinition,
    @CustomerID = @IntVariable,
    @SalesOrderOUT = @SalesOrderNumber OUTPUT;

-- This SELECT statement returns the value of the OUTPUT parameter.
SELECT @SalesOrderNumber;

-- This SELECT statement uses the value of the OUTPUT parameter in
-- the WHERE clause.
SELECT OrderDate,
       TotalDue
FROM Sales.SalesOrderHeader
WHERE SalesOrderNumber = @SalesOrderNumber;

Örnekler: Azure Synapse Analytics ve Analytics Platform Sistemi (PDW)

D. SELECT deyimi yürütme

Aşağıdaki örnek, SELECTadlı katıştırılmış parametreyi içeren bir @level deyimi oluşturur ve yürütür.

EXECUTE sp_executesql
    N'SELECT * FROM AdventureWorksPDW2012.dbo.DimEmployee WHERE EmployeeKey = @level',
    N'@level TINYINT;',
    @level = 109;