Saklı yordam oluştururken tablo var olsa bile Ertelenmiş Ad Çözümlemesi zorlamak için bir yolu var mı?


10

SQL Server'da saklı yordam oluştururken, var olmayan tablolara başvurmanıza izin verilir. Ancak, tablo varsa, yordamda başvurduğunuz herhangi bir sütun bu tabloda ( Ertelenmiş Ad Çözümlemesi ) bulunmalıdır .

SQL Server'a, var olup olmadıklarına bakılmaksızın, bir yordamda başvurulan tüm tabloların ad çözümlemesini ertelemesini bildirmek mümkün müdür? Genel sözdizimi denetimini tutmak istiyorum, bu yüzden mümkün olsa bile, saklı yordam tanımını bir sistem tablosuna kesmek bir seçenek değildir.

Bunu yapmak istemem biraz tuhaf görünebilir , bu yüzden bazı arka plan: C # ile yazılmış bir uygulamadan tablo tanımlarını ve saklı yordamları otomatik olarak oluşturuyorum ve değişiklikleri SQL gereksinimleri olarak sipariş etmek için kodu değiştirmek benim için çok zor onlar. Kodum şema bir işlem içinde tutarlı olduğunu garanti eder, ancak şu anda bunlara başvuran saklı yordamı tanımlamak önce tablo sütunları tanımlanmış garanti edemez.

Aşağıda çözmeye çalıştığım sorunu "gösteren" C # tarafından oluşturulan SQL kanonik bir örneğidir.

--Say this table already exists.
CREATE TABLE myTable
(
    a NVARCHAR(MAX)
)
GO

--My C# code creates something like this
BEGIN TRAN 
GO

--the stored procedure gets generated first.
CREATE PROCEDURE mySproc
AS
BEGIN
    SELECT a,b FROM myTable
END

--then the table update
ALTER TABLE myTable
    ADD b nvarchar(MAX)

COMMIT TRAN 

O ise beni C # kodu Bunu düzeltmek için mümkün, ama basit bir "sihirli" Ben SQL indirebiliriz çimdik umuyorum. Bu benim için çok zaman kazandıracak.


1
Herhangi bir prosedür oluşturmadan / değiştirmeden önce tüm şema değişikliklerini işleyemez misiniz? Tablo doğru olmadan önce prosedür neden mevcut olmalıdır?
Aaron Bertrand

Şimdi kodda bu seçeneği takip ediyorum. SQL'in üretilme şekli oldukça karmaşıktır (bu basit bir örnektir), ancak düşündüğüm kadar PITA olmayacak gibi görünüyor.
Daniel James Bryars

2
Tabii ki dinamik SQL dolu saklı yordamları doldurarak bunu halledebilirsiniz - ama şema değişikliklerini işlemek için komut dosyası oluşturma düşünemiyorum o zaman saklı yordamlar o kadar zor olurdu. Ertelenmiş ad çözümlemesinin nasıl çalıştığını dikte etmek için çok fazla seçenek yoktur. Bildiğim veya en azından eğlendirmekle ilgilendiklerini anlayabildiğim kitaplara ilişkin tek öneri aslında başka bir yol - daha DAHA sıkı yapmak - bkz. Sommarskog.se/strict_checks.html ).
Aaron Bertrand

Dinamik SQL hakkında iyi fikir. Tetikleyiciler, Dizinler, Görünümler, Sprocs ve İşlevler için de aynı sorunu yaşıyorum. Ancak kodu sadece Tablolar, sonra Dizinler, sonra Tetikleyiciler, sonra işlevler, sonra sprocs değişiklikler yapar şekilde değiştirdim.
Daniel James Bryars

Sommarskog'un önerilerini seviyorum, kesinlikle hatalardan kaçınmaya yardımcı olacak. Sıkı bir seçenek uyguladılarsa, varolan sproc'ları bozup bozmadığını görmek için bir tablo değişikliği olduğunda tüm "Sıkı AÇIK" sprocs'ları da yeniden değerlendirebilirler - açıkçası "DDL'de mantıksal işlem" yapmanız gerekir. daha sonra Tablo ve Sprocs'u tek bir birim olarak değiştirebilir.
Daniel James Bryars

Yanıtlar:



5

Hala ilgileniyorsanız, kullanabileceğiniz potansiyel bir çözüm vardır. Yordamdaki #deferResolutionher sorguya geçici tabloyu tanıtan güncellenmiş kod . Geçici tablo yalnızca çalışma zamanında var olacağından, uygun sütunlar henüz mevcut olmasa bile yordam derlenebilir myTable.

#deferResolutionSorgu optimize edicinin bunu WHERE NOT EXISTSher zaman doğru olarak değerlendirdiğini kanıtlayabileceği için prosedürdeki her ifade için aynı yürütme planını ( tabloya referans yok) bile alacaksınız .

Bütün bunlar, çoğunlukla entelektüel çıkarlar için sunulan korkunç bir hack ve çöktüğü bir uç dava olabilir. Aaron'un belirttiği gibi, tüm şema değişikliklerinizi doğru sırayla yapmak daha iyi olur.

--Say this table already exists.
CREATE TABLE myTable
(
    a NVARCHAR(MAX)
)
GO

--My C# code creates something like this
BEGIN TRAN 
GO

--the sproc gets generated first.
CREATE PROCEDURE mySproc
AS
BEGIN
    CREATE TABLE #deferResolution (dummy INT NOT NULL)
    SELECT a,b FROM myTable WHERE NOT EXISTS (SELECT * FROM #deferResolution WHERE 0=1)
END

--then the table update
ALTER TABLE myTable
    ADD b nvarchar(MAX)

COMMIT TRAN 
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.