मैं TSQL में PRINT बफर को कैसे फ्लश करूं?


220

मेरे पास SQL ​​Server 2005 में बहुत लंबी चलने वाली संग्रहीत प्रक्रिया है जिसे मैं डिबग करने की कोशिश कर रहा हूं, और मैं इसे करने के लिए 'प्रिंट' कमांड का उपयोग कर रहा हूं। समस्या यह है, मैं केवल अपने स्प्रो के अंत में SQL सर्वर से संदेश प्राप्त कर रहा हूं - मैं संदेश बफर को फ्लश करने में सक्षम होना चाहता हूं और इन संदेशों को स्प्रो के रनटाइम के दौरान तुरंत देखना चाहता हूं, बजाय बहुत समाप्त।


1
उन लोगों के लिए बस एक छोटी सूचना जो (मेरे जैसे) सोचते हैं कि उत्तर उनके लिए काम नहीं करते हैं: क्वेरी चलने पर "संदेश" टैब पर स्विच करना सुनिश्चित करें। डिफ़ॉल्ट रूप से आपको "परिणाम" टैब दिखाई देगा।
टॉमस गैंडर

जवाबों:


305

RAISERRORफ़ंक्शन का उपयोग करें :

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

आपको अपने सभी प्रिंटों को किशमिश से पूरी तरह से बदलना नहीं चाहिए। यदि आपके पास एक लूप या बड़ा कर्सर है, तो इसे सिर्फ एक या दो बार प्रति चलना या यहां तक ​​कि हर कई पुनरावृत्तियों में से एक में करें।

इसके अलावा: मैंने पहली बार इस लिंक पर RAISERROR के बारे में सीखा, जिसे अब मैं SQL सर्वर त्रुटि से निपटने के निश्चित स्रोत पर विचार करता हूं और निश्चित रूप से पढ़ने लायक हूं:
http://www.sommarskog.se/error-handling-I.html


41
ध्यान दें कि SQL में TRY / CATCH केवल गंभीरता> 10 के साथ त्रुटियों को पकड़ लेगा, इसलिए इस तरह RAISERROR का उपयोग आपके CATCH स्टेटमेंट में नहीं आएगा। जो बहुत अच्छा है, क्योंकि इसका मतलब है कि आप अभी भी TRISER / CATCH के साथ इस तरह RAISERROR का उपयोग कर सकते हैं। रेफरी: msdn.microsoft.com/en-us/library/ms175976.aspx
Rory

13
ध्यान दें कि यह पहले 500 संदेशों के बाद काम नहीं करता है; एक बार जब आप इससे अधिक प्रिंट करते हैं तो यह अचानक बफ़र करना शुरू कर देता है!
गंडोइकरी 20

@MahmoudMoravej नहीं, मैं अभी भी RAISEERROR का उपयोग करके लंबी-लंबी प्रक्रियाएँ चला रहा हूँ, और बस इस तथ्य से निपट रहा हूँ कि थोड़ी देर के बाद, संदेश बफ़र होने लगते हैं। ऐसा प्रतीत होता है कि एकमात्र समाधान SSMS के अलावा किसी अन्य उपकरण का उपयोग करना होगा।
गेंडोइकरी

1
मुझे लगता है कि यह कुछ ऐसा है जो एसएस के हाल के संस्करण में बदल गया है। जब मैंने पहली बार यह लिखा था तो हमने 500 से अधिक संदेशों के साथ रातोंरात बैच प्रक्रियाओं के व्यापक लॉगिंग के लिए RAISERROR का उपयोग किया था, और यह कोई समस्या नहीं थी। लेकिन 7 साल में बहुत कुछ बदल सकता है।
जोएल कोएहॉर्न

1
@ GendoIkari की सूचना पर। मैंने इसे इस स्क्रिप्ट के साथ 2016SP1 से ssms के साथ आज़माया है। 500 पर यह 50 लाइनों को बफ़र करने के लिए स्विच करता है और 1k पर यह 100 लाइनों में से प्रत्येक पर स्विच करता है। यह कम से कम 2k तक जारी रहा, लेकिन फिर मैंने स्क्रिप्ट को रोक दिया। घोषित @i int सेट @i = 0 घोषित @t varchar (100) जबकि 1 = 1 शुरू सेट @i = @i + 1 सेट @t = 'प्रिंट' + रूपांतरित (varchar, @i) RAISERROR (@t, 10) , 1) NowAIT वेटफोर विलम्ब के साथ '00: 00: 00.010 'का अंत
Zartag

28

@JoelCoehoorn द्वारा जवाब पर निर्माण, मेरा दृष्टिकोण मेरे सभी प्रिंट बयानों को जगह में छोड़ना है, और फ्लश पैदा करने के लिए RAISERROR बयान के साथ बस उनका पालन करना है।

उदाहरण के लिए:

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

इस दृष्टिकोण का लाभ यह है कि प्रिंट स्टेटमेंट स्ट्रिंग्स को समेट सकता है, जबकि RAISERROR नहीं कर सकता है। (इसलिए या तो आपके पास कोड की समान संख्या है, जैसा कि आपको RAISERROR में उपयोग करने के लिए एक चर घोषित और सेट करना होगा)।

यदि, मेरी तरह, आप AutoHotKey या SSMSBoost या समकक्ष टूल का उपयोग करते हैं, तो आप आसानी से आपके लिए RAISERROR लाइन डालने के लिए "] फ्लश" जैसे शॉर्टकट सेट कर सकते हैं। यह आपको समय बचाता है यदि यह हर बार कोड की एक ही पंक्ति है, अर्थात विशिष्ट पाठ या चर को रखने के लिए अनुकूलित करने की आवश्यकता नहीं है।


6
ध्यान दें कि RAISERROR()समर्थन printf()-स्टाइल स्ट्रिंग प्रक्षेप करता है। उदाहरण के लिए यदि @MyVariableNameएक stringish प्रकार (जैसे, है VARCHAR(MAX), NVARCHAR(MAX), आदि), आप उपयोग कर सकते हैं RAISERROR(): एक लाइन के साथ RAISERROR(N'MyVariableName: %s', 0, 1, @MyVariableName)
बिंकी जू

यह बहुत सुविधाजनक है! मुझे पता है कि RAISERROR कुछ सरल प्रतिस्थापन कर सकता है, लेकिन एक [दिनांक] समय को प्रतिस्थापित करने का प्रयास करें, या RAISERROR कथन के अंदर से किसी फ़ंक्शन को कॉल करें! यह उत्तर आपको खाली त्रुटि (एक नई सीमा की लागत पर) बढ़ाने के रूप में एक साधारण FLUSH देता है।
टॉमस गैंडर

19

हां ... RAISERROR फ़ंक्शन के पहले पैरामीटर को NVARCHAR चर की आवश्यकता होती है। तो निम्नलिखित प्रयास करें;

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

या

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

10
नीचे टैब पर संदेश टैब देखें, परिणाम टैब के बगल में या परिणाम मोड पर पाठ मोड पर जाएं।
मेहमत एर्गुट

SSMS, मेनू टूल्स -> विकल्प -> क्वेरी परिणाम -> SQL सर्वर -> सामान्य -> ​​परिणामों के लिए डिफ़ॉल्ट गंतव्य पर पाठ मोड में परिणाम स्विच करने के लिए, और "परिणाम के लिए पाठ" के बजाय "परिणाम के लिए पाठ" चुनें, फिर से क्वेरी विंडो को खोलें और फिर आप वहाँ एक डमी की तरह एक खाली परिणाम टैब को देखते हुए नहीं बैठेंगे जबकि RAISERROR आउटपुट संदेश टैब पर जाता है।
एडम

13

एक और बेहतर विकल्प PRINT या RAISERROR पर निर्भर नहीं होना है और अपने "प्रिंट" स्टेटमेंट को TempDB में ## टेम्‍प टेबल में या अपने डेटाबेस में एक स्‍थायी तालिका में लोड करना है, जो आपको किसी अन्‍य विंडो के साथ सेलेक्‍ट स्टेटमेंट के माध्‍यम से तुरंत डेटा को दृश्‍यता प्रदान करेगा। । यह मेरे लिए सबसे अच्छा काम करता है। एक स्थायी तालिका का उपयोग करना भी अतीत में क्या हुआ लॉग के रूप में कार्य करता है। प्रिंट स्टेटमेंट त्रुटियों के लिए आसान हैं, लेकिन लॉग टेबल का उपयोग करके आप उस विशेष निष्पादन के लिए अंतिम लॉग मान के आधार पर विफलता का सटीक बिंदु भी निर्धारित कर सकते हैं (यह मानकर कि आप अपने लॉग टेबल में समग्र निष्पादन के समय को ट्रैक करते हैं।)


2
यह एक मुद्दा हो सकता है यदि आप कमिट और रोलबैक के साथ सही मायने में ट्रांस्क्रिप्शनल स्क्रिप्ट लिख रहे हैं। मुझे विश्वास नहीं है कि आप अपनी अस्थायी तालिका को लाइव करने में सक्षम होंगे - और यदि आपका लेनदेन विफल हो जाता है तो यह दूर हो जाएगा।
स्टीवजे

@SteveJ आप इसे SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;अपने मॉनिटरिंग सेशन में इस्तेमाल करके लाइव कर सकते हैं
TheConstructor

1
@ कंस्ट्रक्टर; यह एक उपयोगी टिप है - मैं इसका उपयोग करूँगा, धन्यवाद। हालाँकि, हम अभी भी अस्थायी तालिका के साथ रोलबैक पर नहीं जा रहे हैं? यदि विफलता विश्लेषण करते हैं, तो ऐसा लगता है कि यह एक बड़ी कमी होगी।
स्टीवजे

1
@SteveJ हाँ, यह निश्चित रूप से है। आप निश्चित रूप READ UNCOMMITTEDसे किसी अन्य तालिका में लेन-देन में डेटा की प्रतिलिपि बना सकते हैं , लेकिन आप शायद पहले ही क्षण को याद करते हैं ROLLBACK। तो यह शायद 'कितनी दूर है?' नहीं 'क्यों रोलबैक?'
द कन्स्ट्रक्टर

4

केवल संदर्भ के लिए, यदि आप स्क्रिप्ट (बैच प्रोसेसिंग) में काम करते हैं , तो संग्रहीत कार्यविधि में नहीं , GO कमांड द्वारा फ्लशिंग आउटपुट को ट्रिगर किया जाता है, जैसे।

print 'test'
print 'test'
go

सामान्य तौर पर, मेरा निष्कर्ष निम्नलिखित है: mssql स्क्रिप्ट निष्पादन का उत्पादन, SMS GUI में निष्पादित या sqlcmd.exe के साथ, पहले GO स्टेटमेंट पर या स्क्रिप्ट के अंत तक फ़ाइल, stdoutput, gui विंडो पर फ़्लश किया जाता है।

संग्रहीत कार्यविधि के अंदर फ्लशिंग अलग प्रकार से कार्य करता है, क्योंकि आप जीओ को अंदर नहीं रख सकते हैं।

संदर्भ: tsql Go स्टेटमेंट


2
goसिर्फ आउटपुट फ्लश नहीं करता है, यह आपके द्वारा दिए गए लिंक के अनुसार बैच को समाप्त करता है। आपके declareद्वारा छोड़ी गई कोई भी चीज़ त्याग दी जाती है, इसलिए डिबगिंग के लिए बहुत उपयोगी नहीं है। declare @test int print "I want to read this!" go set @test=5हालाँकि आप दावा करने @testमें त्रुटि के कारण अपरिभाषित हैं क्योंकि यह एक नए बैच में है।
asontu

1
मैं मानता हूं, यह इस सवाल का उचित जवाब नहीं है, लेकिन मैंने जवाब डाल दिया (शुरुआत पर अस्वीकरण देखें) क्योंकि यह किसी और के लिए उपयोगी हो सकता है - जैसे कोई व्यक्ति जो बैच एसक्यूएल चलाता है।
रॉबर्ट लूजो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.