Açıklama, aşağıdakilerin bir kombinasyonuna bağlı gibi görünmektedir: a) bağlantılı blogdan bu soruda bahsedilmeyen bir detay, b) parametrelerin her zaman içeri ve dışarı nasıl aktarıldığına uyan TVP'lerin pragmatikleri, c) ve doğa tablo değişkenleri.
Bağlantılı blog gönderisinde yer alan eksik ayrıntı, değişkenlerin Saklı Yordamlar ve İşlevlere nasıl ve nasıl aktarıldıklarıdır ("ÇIKIŞ parametreleri ise daha güvenli bir pass-by referans sürümü" sorusundaki ifadeyle ilgilidir). :
TSQL parametreleri saklı yordamlar ve işlevlere iletmek için bir kopyala / kopyala semantik kullanır.
... saklanan proc yürütmeyi bitirdiğinde (bir hataya çarpmadan), depolanan proc'ta yapılan değişikliklerle iletilen parametreyi güncelleyen bir kopyalama yapılır.
Bu yaklaşımın gerçek yararı hata durumundadır. Saklı yordamın yürütülmesinin ortasında bir hata oluşursa, parametrelerde yapılan herhangi bir değişiklik arayan kişiye geri yayılmaz.
OUTPUT anahtar sözcüğü yoksa, kopyalama yapılmaz.
Alt satır:
Saklanan procs parametreleri, bir hata ile karşılaşırsa saklanan proc'un kısmen yürütülmesini asla yansıtmaz.
Bu bulmacanın 1. kısmı parametrelerin her zaman "değere göre" iletilmesidir. Ve yalnızca parametre olarak işaretlendiğinde OUTPUT
ve Saklı Yordam başarıyla tamamlandığında geçerli değerin gerçekten geri gönderilmesi gerekir. Eğer OUTPUT
değerler gerçekten "referans olarak" geçirildi, daha sonra bu değişkenin bellekte konumu işaretçisi geçildi şey değil değerin kendisi olacaktır. İşaretçiyi (yani bellek adresi) geçirirseniz, Saklı Yordamın bir sonraki satırı bir hataya neden olsa ve yürütmeyi durdursa bile, yapılan değişiklikler hemen yansıtılır.
Kısım 1'i özetlemek gerekirse: değişken değerler daima kopyalanır; bellek adresleri tarafından referans verilmez.
Bölüm 1 göz önünde bulundurulduğunda, değişken değerleri her zaman kopyalama ilkesi, iletilen değişken oldukça büyük olduğunda kaynak sorunlarına yol açabilir. Ben damla tipleri nasıl ele alındığını görmek test etmedim ( VARCHAR(MAX)
, NVARCHAR(MAX)
, VARBINARY(MAX)
, XML
, ve artık kullanılmaması gerekir olanlar: TEXT
, NTEXT
, ve IMAGE
), ancak herhangi bir veri tablosu oldukça büyük olabilir geçirilen söylemek güvenlidir. TVP özelliğini geliştirenlerin, havalı yeni özelliklerinin sağlıklı sayıda sistemi yok etmesini (yani daha ölçeklenebilir bir yaklaşım istemek) önlemek için gerçek bir "referansla geçme" yeteneğini arzulamaları mantıklı olacaktır. Belgelerde gördüğünüz gibi yaptıkları bu:
Transact-SQL girdi verilerinin bir kopyasını yapmaktan kaçınmak için tablo değerli parametreleri yordamlara başvurur.
Ayrıca, SQL Server 2005'te tanıtılan SQLCLR API'sinde (TVP'ler SQL Server 2008'de tanıtıldı) bulunabileceğinden, bu bellek yönetimi sorunu yeni bir kavram değildi. Geçerken NVARCHAR
ve VARBINARY
(a SQLCLR Meclis içinde .NET yöntemleri yani giriş parametreleri) SQLCLR koduna veri, ya kullanarak "değeri" yaklaşımı ile gitmek seçeneğine sahip SqlString
veya SqlBinary
sırasıyla, yoksa "referans ile birlikte gidebilir "ya SqlChars
da SqlBytes
sırasıyla kullanarak yaklaşım . SqlChars
Ve SqlBytes
türleri (2 GB'ye kadar sağa) bütün bir 200 MB kopyalama değer aksine büyük değerlerin küçük parçalarını indirebiliriz şekilde .NET CLR içine tam veri akışı için izin verir.
Özetle Kısım 2: TVP'ler, doğası gereği, "değeri her zaman kopyala" modelinde kalmaları durumunda çok fazla bellek (ve dolayısıyla performansı düşürür) kullanma eğiliminde olurlar. Bu nedenle TVP'ler gerçek bir "referansla geçer" yapar.
Son bölüm, Bölüm 2'nin neden önemli olduğudur: Bir TVP'ye neden bir kopyasını değiştirmek yerine gerçekte "referans olarak" geçmek istesin. Ve bu, Bölüm 1: Başarıyla tamamlanmayan Saklı Yordamlar için temel olan tasarım hedefi tarafından yanıtlanır, herhangi bir şekilde, işaretlenmiş olsun OUTPUT
veya olmasın, giriş parametrelerinin hiçbirini değiştirmemelidir. DML işlemlerine izin vermek, çağrı bağlamında var olduğu için TVP'nin değeri üzerinde hemen bir etkiye sahip olacaktır (referansla geçmek, iletilen şeyin bir kopyasını değil, geçirilen şeyi değiştirdiğiniz anlamına gelir).
Şimdi, bir yerlerde, birisi bu noktada muhtemelen monitörleriyle konuşuyor, "Eh, sadece Saklı Yordam'a geçildiyse TVP parametrelerinde yapılan değişiklikleri geri almak için bir otomajik tesiste inşa edin. Duh. Sorun çözüldü." Çok hızlı değil. Tablo Değişkenlerinin niteliği burada devreye girer: Tablo Değişkenlerinde yapılan değişiklikler İşlemler ile sınırlı değildir! Yani değişiklikleri geri almanın bir yolu yok. Ve aslında, bu bir geri alma olması gerekiyorsa bir işlem içinde oluşturulan bilgileri kaydetmek için kullanılan bir hile :-).
Özetle Bölüm 3: Tablo Değişkenleri, Saklı Yordamın iptal edilmesine neden olan bir hata durumunda kendilerine yapılan "geri alma" değişikliklerine izin vermez. Bu da kısmi yürütmeyi asla yansıtmayan parametrelere sahip olmanın tasarım amacını ihlal eder (Bölüm 1).
TYPE
değişkeni veya aDECLARE x as TABLE (...)
) saklı yordamla değiştirmenin bir yolu yok mu? Bunun yerine bir işlevle, daha büyük bir bellek ayak izi de olsa yapabilir misinset @tvp = myfunction(@tvp)
benim işlevin eğerRETURNS
değer TVP türü ile aynı DDL ile tablodur?