TSQL'de PRINT arabelleğini nasıl temizlerim?


220

Hata ayıklamaya çalıştığım SQL Server 2005'te çok uzun süredir saklanan bir yordam var ve bunu yapmak için 'Yazdır' komutunu kullanıyorum. Sorun şu ki, sadece sproc'umun sonunda SQL Server'dan mesajları alıyorum - Mesaj arabelleğini yıkamak ve bu mesajları sproc'un çalışma zamanında hemen yerine görmek istiyorum. son.


1
(Benim gibi) yanıtların kendileri için uygun olmadığını düşünecek insanlar için kısa bir bildirim: Sorgu çalışırken "Mesajlar" sekmesine geçmeyi unutmayın. Varsayılan olarak "Sonuçlar" sekmesini görürsünüz.
Tomasz Gandor

Yanıtlar:


305

RAISERRORİşlevi kullanın :

RAISERROR( 'This message will show up right away...',0,1) WITH NOWAIT

Tüm baskılarınızı raiserror ile tamamen değiştirmemelisiniz. Bir yerde bir döngü veya büyük imleciniz varsa, yineleme başına bir veya iki kez veya hatta her birkaç yinelemede bir yapın.

Ayrıca: RAISERROR'u ilk öğrendim, şimdi SQL Server Hata işleme konusunda kesin kaynağı düşünüyor ve kesinlikle okumaya değer:
http://www.sommarskog.se/error-handling-I.html


41
SQL'deki TRY / CATCH değerinin yalnızca> 10 önem derecesine sahip hataları yakalayacağını unutmayın, bu nedenle RAISERROR'un bu şekilde kullanılması CATCH deyiminize atlamaz. Bu harika, çünkü yine de böyle bir RAISERROR'u TRY / CATCH ile kullanabilirsiniz. ref: msdn.microsoft.com/en-us/library/ms175976.aspx
Rory

13
Bunun ilk 500 iletiden sonra çalışmadığını unutmayın; bundan daha fazla yazdırdığınızda aniden arabelleğe almaya başlar!
GendoIkari

@MahmoudMoravej Hayır, hala RAISEERROR kullanarak uzun süredir devam eden işlemler yürütüyorum ve sadece bir süre sonra mesajların arabelleğe alınmaya başlamasıyla ilgileniyorum. Görünüşe göre tek çözüm SSMS'den farklı bir araç kullanmak olacak.
GendoIkari

1
Bence bu, SS'nin son versiyonunda değişen bir şey. Bunu ilk yazdığımda, RAISERROR'u 500'den fazla mesaj içeren gece toplu işlemlerinin kapsamlı günlüğü için kullandık ve bu bir problem değildi. Ancak 7 yılda çok şey değişebilir.
Joel Coehoorn

1
@ GendoIkari'nin bildiriminde. Ben bu komut dosyası ile 2016SP1 gelen ssms ile denedim. 500'de 50 satır arabelleğe alır ve 1k'da her biri 100 satıra geçer. Bu en azından 2k'ye kadar devam etti, ama sonra senaryoyu durdurdum. declare @i int set @i = 0 declare @t varchar (100), 1 = 1 başlarken @i = @i + 1 set @t = 'print' + convert (varchar, @i) RAISERROR (@t, 10 , 1) NOWAIT İLE gecikme '00: 00: 00.010 'gecikmesi
Zartag

28

@JoelCoehoorn'un cevabına dayanarak, yaklaşımım tüm PRINT ifadelerimi yerinde bırakmak ve bunları floşise neden olmak için RAISERROR ifadesiyle takip etmektir.

Örneğin:

PRINT 'MyVariableName: ' + @MyVariableName
RAISERROR(N'', 0, 1) WITH NOWAIT

Bu yaklaşımın avantajı, PRINT deyimlerinin dizeleri birleştirebilmesidir, ancak RAISERROR bunu yapamaz. (Her iki şekilde de, RAISERROR'da kullanmak için bir değişken bildirmeniz ve ayarlamanız gerektiği için aynı sayıda kod satırına sahip olursunuz).

Benim gibi AutoHotKey veya SSMSBoost veya eşdeğer bir araç kullanıyorsanız, RAISERROR satırını sizin için girmek için kolayca "] flush" gibi bir kısayol ayarlayabilirsiniz. Bu, her seferinde aynı kod satırıysa size zaman kazandırır, yani belirli bir metni veya değişkeni tutmak için özelleştirilmesine gerek yoktur.


6
-Style dize enterpolasyonunu RAISERROR()desteklediğini unutmayın printf(). Örneğin, eğer @MyVariableNamebir stringish türü (örn olduğunu VARCHAR(MAX), NVARCHAR(MAX)vb) kullanabilirsiniz RAISERROR(): bir satır ile RAISERROR(N'MyVariableName: %s', 0, 1, @MyVariableName).
binki

Bu çok uygun! RAISERROR'un basit bir ikame yapabileceğini biliyorum, ancak [tarih] saatini değiştirmeyi veya RAISERROR deyiminin içinden bir işlev çağırmayı deneyin! Bu cevap size, boş bir hatayı (bir satırsonu pahasına) yükseltme şeklinde basit bir FLUSH verir.
Tomasz Gandor

19

Evet ... RAISERROR işlevinin ilk parametresi bir NVARCHAR değişkenine ihtiyaç duyar. Bu yüzden aşağıdakileri deneyin;

-- Replace PRINT function
DECLARE @strMsg NVARCHAR(100)
SELECT @strMsg = 'Here''s your message...'
RAISERROR (@strMsg, 0, 1) WITH NOWAIT

VEYA

RAISERROR (n'Here''s your message...', 0, 1) WITH NOWAIT

10
Sonuçlar sekmesinin yanındaki alttaki Mesajlar sekmesine bakın veya Sonuçlar Metin moduna geçin.
Mehmet Ergut

Sonuçlar'ı Metin moduna geçirmek için, SSMS'de Araçlar -> Seçenekler -> Sorgu Sonuçları -> SQL Server -> Genel -> Sonuçlar için Varsayılan Hedef menüsünü seçin ve "Şebekeye Sonuçlar" yerine "Metne Sonuçlar" ı seçin. -sorgu penceresini açın ve RAISERROR çıktısı Mesajlar sekmesine giderken orada boş bir Sonuçlar sekmesine kukla gibi bakarak oturmayacaksınız.
Adam

13

Başka bir daha iyi seçenek, PRINT veya RAISERROR'a bağlı olmamak ve "print" ifadelerinizi TempDB'deki ## Temp tablosuna veya veritabanınızdaki kalıcı bir tabloya yüklemenizdir. . Bu benim için en iyisi. Kalıcı bir tablo kullanmak da geçmişte olanlara bir kütük görevi görür. Yazdırma ifadeleri hatalar için kullanışlıdır, ancak günlük tablosunu kullanarak söz konusu yürütme için son günlüğe kaydedilen değere bağlı olarak kesin hata noktasını da belirleyebilirsiniz (günlük tablonuzdaki genel yürütme başlangıç ​​saatini izlediğiniz varsayılarak).


2
Aktarma ve geri alma ile gerçekten işlemsel bir komut dosyası yazıyorsanız, bu bir sorun olabilir. Geçici tablonuzu canlı olarak sorgulayabileceğinize inanmıyorum ve işleminiz başarısız olursa gidecek.
SteveJ

@SteveJ SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;izleme oturumunuzu kullanarak canlı sorgulayabilirsiniz
TheConstructor

1
@TheConstructor; Bu yararlı bir ipucu - bundan faydalanacağım, teşekkürler. Ancak, temp tablosunun geri dönmeye devam etmesine hala devam etmedik mi? Eğer başarısızlık analizi yapılıyorsa, bu büyük bir eksiklik gibi görünüyor.
SteveJ

1
@SteveJ evet, kesinlikle var. Elbette bir READ UNCOMMITTEDişlemdeki verileri başka bir tabloya kopyalayabilirsiniz , ancak muhtemelen daha önce olan anı kaçırırsınız ROLLBACK. Yani muhtemelen 'ne kadar?' 'neden geri dönüş?'
Yapımcı

4

Sadece referans için, saklı yordamda değil, komut dosyalarında (toplu işleme) çalışıyorsanız , yıkama çıkışı GO komutu tarafından tetiklenir, örn.

print 'test'
print 'test'
go

Genel olarak, benim sonuç şu: SMS GUI veya sqlcmd.exe ile yürütme mssql komut dosyası yürütme çıktı, ilk GO deyiminde veya komut dosyasının sonuna kadar dosya, stdoutput, gui penceresine akıtıldı.

GO içine yerleştiremeyeceğiniz için, saklı yordamın içindeki yıkama farklı işlev görür.

Referans: tsql Go ifadesi


2
gosadece çıktıyı yıkamakla kalmaz, aynı zamanda sağladığınız bağlantıya göre toplu işi sonlandırır. Sizin herhangi bir şey declareatılır, bu yüzden hata ayıklama için çok kullanışlı değildir. yeni bir toplu iş olduğu için tanımlanmayan declare @test int print "I want to read this!" go set @test=5bir hata olduğunu @testbelirtir.
asontu

1
Katılıyorum, bu bu soruya uygun bir cevap değil, ama başka biri için yararlı olabileceğinden cevabı koydum (başlangıçtaki feragatnameye bakın) - örneğin toplu sql çalıştıran biri.
Robert Lujo
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.