[मुझे अभी-अभी एहसास हुआ कि मैंने इस प्रश्न का उत्तर पहले ही दे दिया है]
किसी संग्रहीत कार्यविधि के लिए ऐसा करना किसी दृश्य या तालिका की तुलना में बहुत अधिक जटिल है। समस्याओं में से एक यह है कि एक संग्रहीत प्रक्रिया में इनपुट पैरामीटर और यहां तक कि उन चीजों के आधार पर कई अलग-अलग कोड पथ हो सकते हैं जिन्हें आप नियंत्रित नहीं कर सकते हैं जैसे सर्वर स्थिति, दिन का समय इत्यादि। उदाहरण के लिए आप आउटपुट के रूप में क्या देखने की उम्मीद करेंगे यह संग्रहीत प्रक्रिया? क्या होगा यदि सशर्त की परवाह किए बिना एकाधिक परिणाम सेट हैं?
CREATE PROCEDURE dbo.foo
@bar INT
AS
BEGIN
SET NOCOUNT ON;
IF @bar = 1
SELECT a, b, c FROM dbo.blat;
ELSE
SELECT d, e, f, g, h FROM dbo.splunge;
END
GO
यदि आपकी संग्रहीत कार्यविधि में कोड पथ नहीं हैं और आप आश्वस्त हैं कि आप हमेशा एक ही परिणाम सेट देखेंगे (और पहले से निर्धारित कर सकते हैं कि संग्रहीत कार्यविधि में गैर-वैकल्पिक पैरामीटर होने पर कौन से मान दिए जाने चाहिए), आइए एक सरल उदाहरण लेते हैं:
CREATE PROCEDURE dbo.bar
AS
BEGIN
SET NOCOUNT ON;
SELECT a = 'a', b = 1, c = GETDATE();
END
GO
FMTONLY
एक तरीका यह है कि कुछ इस तरह किया जाए:
SET FMTONLY ON;
GO
EXEC dbo.bar;
यह आपको एक खाली परिणाम देगा और आपका क्लाइंट एप्लिकेशन कॉलम नाम और डेटा प्रकार निर्धारित करने के लिए उस परिणामसेट के गुणों पर एक नज़र डाल सकता है।
अब, SET FMTONLY ON;
. के साथ बहुत सारी समस्याएं हैं कि मैं यहां नहीं जाऊंगा, लेकिन कम से कम यह ध्यान दिया जाना चाहिए कि यह आदेश बहिष्कृत है - अच्छे कारण के लिए। SET FMTONLY OFF;
जब आप काम पूरा कर लेंगे, या आपको आश्चर्य होगा कि आप एक संग्रहित प्रक्रिया को सफलतापूर्वक क्यों बनाते हैं लेकिन फिर इसे निष्पादित नहीं कर सकते हैं। और नहीं, मैं आपको इसके बारे में चेतावनी नहीं दे रहा हूं क्योंकि यह अभी मेरे साथ हुआ है। ईमानदार। :-)
OPENQUERY
लूपबैक लिंक्ड सर्वर बनाकर, आप OPENQUERY
. जैसे टूल का उपयोग कर सकते हैं एक संग्रहीत प्रक्रिया को निष्पादित करने के लिए, लेकिन एक कंपोज़ेबल परिणाम लौटाएं (ठीक है, कृपया इसे एक अत्यंत ढीली परिभाषा के रूप में स्वीकार करें) जिसका आप निरीक्षण कर सकते हैं। पहले एक लूपबैक सर्वर बनाएं (यह FOO
. नामक एक स्थानीय उदाहरण मानता है ):
USE master;
GO
EXEC sp_addlinkedserver @server = N'.\FOO', @srvproduct=N'SQL Server'
GO
EXEC sp_serveroption @server=N'.\FOO', @optname=N'data access',
@optvalue=N'true';
अब हम ऊपर की प्रक्रिया को अपना सकते हैं और इसे इस तरह की क्वेरी में फीड कर सकते हैं:
SELECT * INTO #t
FROM OPENQUERY([.\FOO], 'EXEC dbname.dbo.bar;')
WHERE 1 = 0;
SELECT c.name, t.name
FROM tempdb.sys.columns AS c
INNER JOIN sys.types AS t
ON c.system_type_id = t.system_type_id
WHERE c.[object_id] = OBJECT_ID('tempdb..#t');
यह उपनाम प्रकारों (पहले उपयोगकर्ता-परिभाषित डेटा प्रकार के रूप में जाना जाता था) को अनदेखा करता है और कॉलम के लिए दो पंक्तियों को भी दिखा सकता है, उदाहरण के लिए, sysname
. लेकिन ऊपर से यह पैदा करता है:
name name
---- --------
b int
c datetime
a varchar
जाहिर है कि यहां और काम करना है - varchar
लंबाई नहीं दिखाता है, और आपको datetime2
जैसे अन्य प्रकारों के लिए सटीक/पैमाना प्राप्त करना होगा , time
और decimal
. लेकिन यह एक शुरुआत है।
एसक्यूएल सर्वर 2012
SQL सर्वर 2012 में कुछ नए फ़ंक्शन हैं जो मेटाडेटा खोज को बहुत आसान बनाते हैं। उपरोक्त प्रक्रिया के लिए हम निम्नलिखित कार्य कर सकते हैं:
SELECT name, system_type_name
FROM sys.dm_exec_describe_first_result_set_for_object
(
OBJECT_ID('dbo.bar'),
NULL
);
अन्य बातों के अलावा यह वास्तव में सटीक और पैमाना प्रदान करता है और हमारे लिए उपनाम प्रकारों को हल करता है। उपरोक्त प्रक्रिया के लिए यह प्राप्त होता है:
name system_type_name
---- ----------------
a varchar(1)
b int
c datetime
दृष्टि से बहुत अधिक अंतर नहीं है, लेकिन जब आप विभिन्न सटीकता और पैमाने के साथ सभी अलग-अलग डेटा प्रकारों में प्रवेश करना शुरू करते हैं, तो आप इस फ़ंक्शन द्वारा आपके लिए किए जाने वाले अतिरिक्त कार्य की सराहना करेंगे।
नकारात्मक पक्ष:SQL Server 2012 में कम से कम ये फ़ंक्शन केवल पहले . के लिए काम करते हैं परिणामसेट (जैसा कि फ़ंक्शन के नाम से पता चलता है)।