EXEC ve sp_executesql Hangisi ?

Doğrudan SQL komutu çalıştırmak yerine bazı durumlarda dinamik SQL scriptleri çalıştırmak zorunda kalabiliyoruz. Özellikle stored procedure’ler içerisinde değişkenler kullanılarak oluşturulmuş script’leri çalıştırmak için EXEC komutu veya sp_executesql prosedürü kullanılır. Peki bunlardan hangisini ne zaman tercih etmeliyiz. Normal şartlar altında bir SQL cümlesini doğrudan çalıştırdığımız SQL Server, bellekten ilgili yürütme planını okuyup ona göre sorguyu çalıştırır. Böylece daha önceki deneyimleri doğrultusunda en uygun okumayı tercih etmiş olur. Fakat dinamik cümleleri çalıştırırken execution plan kullanılmaz her çalıştırmada yeni bir execution plan oluşturulur. Bu iki komutun en önemli farkı sp_executesql, parametrik olabilirken EXEC / EXECUTE parametrik değildir. Buradaki parametreden kastımız bu komutlara parametre olarak verilmiş sorgunun parametrik olmasıdır. Asıl önemli olan konu performans açısından sunucu aynı execution plan’ı kullandığı için daha sp_executesql yordamı daha iyi sonuç vermektedir. Çünkü bu yordamın mantığı sorgunun aynı olduğu sadece parametrenin farklı çalıştırılıyor olmasıdır. Aşağıdaki örnekte küçük bir tablodan bu 2 yordam aracılığıyla okuma yapılmış olup execution plan durumları listelenmiştir. Sistemdeki mevcut execution plan’ları temizlemek için DBCC FREEPROCCACHE kullanılır.

CREATE TABLE Musteri (MusteriId int, AdSoyad VARCHAR(100))
GO
INSERT Musteri VALUES(1,'M1')
INSERT Musteri VALUES(2,'M2')
GO
DBCC FREEPROCCACHE

DECLARE @MusteriId INT
DECLARE @Sorgu NVARCHAR(200)

SET @Sorgu = 'SELECT * FROM Musteri WHERE MusteriId = '

SET @MusteriId = 1
EXEC( @Sorgu + @MusteriId)

SET @MusteriId = 2
EXEC( @Sorgu + @MusteriId)

SET @Sorgu = 'SELECT * FROM Musteri WHERE MusteriId = @PrmMusteriId'

SET @MusteriId = 1
EXEC sp_executesql @Sorgu, N'@PrmMusteriId INT', @PrmMusteriId = @MusteriId

SET @MusteriId = 2
EXEC sp_executesql @Sorgu, N'@PrmMusteriId INT', @PrmMusteriId = @MusteriId

Sistemdeki yürütme planlarını görmek için sys.syscacheobjects tablosuna bakabiliriz.

SELECT usecounts [Kullanim Adeti], sql Sorgu FROM sys.syscacheobjects


2 (@PrmMusteriId INT)SELECT * FROM Musteri WHERE MusteriId = @PrmMusteriId
1 SELECT * FROM Musteri WHERE MusteriId = 1
1 SELECT * FROM Musteri WHERE MusteriId = 2

Görüldüğü gibi sp_executesql yordamı aynı execution plan’ı kullanmıştır. EXEC ise her defasında yeni bir execution olan oluşturmuş. Bu mantığından dolayı sp_executesql yordamı “Forced Statement Caching” olarak EXEC/EXECUTE yordamları için “Dynamic String Execution” olarak bilinir.
Parametrik yapıyı genellikle SQL injection
Bu komutları linked server olarak tanımlı sunucular için de kolayca kullanabiliriz.

EXEC sp_addlinkedserver 'UzakSunucu', 'SQL Server'
GO
EXECUTE ( 'SELECT * FROM Alisveris.dbo.tbSatis' ) AT UzakSunucu;
GO
UzakSunucu.Alisveris.dbo.sp_executesql N'SELECT * FROM tbSatis'

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir