SQL सर्वर - संग्रहीत कार्यविधि से चयन करें


334

मेरे पास एक संग्रहीत प्रक्रिया है जो पंक्तियों को लौटाती है:

CREATE PROCEDURE MyProc
AS
BEGIN
    SELECT * FROM MyTable
END

मेरी वास्तविक प्रक्रिया थोड़ी अधिक जटिल है, यही वजह है कि एक स्पोक आवश्यक है।

क्या इस प्रक्रिया को कॉल करके आउटपुट का चयन करना संभव है?

कुछ इस तरह:

SELECT * FROM (EXEC MyProc) AS TEMP

मैं उपयोग करने की आवश्यकता SELECT TOP X, ROW_NUMBERऔर, एक अतिरिक्त WHEREपृष्ठ पर खंड अपने डेटा, और मैं नहीं है वास्तव में पैरामीटर के रूप में इन मूल्यों को पास करना चाहते हैं।


मैं अनिश्चित हूं कि आप यहां क्या करने का इरादा रखते हैं क्योंकि जब आप प्रक्रिया को निष्पादित करते हैं, तो आप पंक्तियों को वापस पा रहे हैं। क्या यह है कि आप एक सेलेक्ट स्टेटमेंट के अंदर की प्रक्रिया को निष्पादित करना चाहते हैं, ताकि आप इसे एक पेजेबल ऑब्जेक्ट से बाँध सकें?
राज मोरे

1
क्या कोई विशेष कारण है कि आप मानों को मापदंडों के रूप में पारित नहीं करना चाहते हैं? ऐसा करने के लिए जिस तरह से आप सुझाव दे रहे हैं वह थोड़ा अक्षम है - आप अपनी ज़रूरत से ज़्यादा डेटा का चयन करेंगे, और फिर सभी का उपयोग नहीं करेंगे।
मार्क बेल

2
यहाँ देखें: sommarskog.se/share_data.html
pylover

जवाबों:


149

आप एक उपयोगकर्ता-परिभाषित फ़ंक्शन या एक प्रक्रिया के बजाय एक दृश्य का उपयोग कर सकते हैं ।

एक प्रक्रिया कई परिणाम सेट लौटा सकती है, प्रत्येक अपने स्वयं के स्कीमा के साथ। यह एक SELECTबयान में उपयोग करने के लिए उपयुक्त नहीं है ।


8
इसके अतिरिक्त, यदि आप एक यूडीएफ में परिवर्तित होने के बाद पाते हैं कि आपको संग्रहीत प्रक्रिया शब्दार्थ की आवश्यकता है तो आप हमेशा एक प्रक्रिया के साथ यूडीएफ को लपेट सकते हैं।
जोएल कोएहॉर्न सिप

क्या होगा, अगर हमें संग्रहित प्रक्रियाओं के लिए पैरामीटर भेजने और उन्हें एक बड़ी संग्रहीत प्रक्रिया में संयोजित करने की आवश्यकता है? देख सकते हैं, पैरामीटर लेते हैं, जैसे संग्रहीत कार्यविधियाँ करता है
mrN

3
@mrN व्यूज पैरामीटर नहीं लेते हैं, लेकिन UDFs करते हैं।
मेहरदाद अफश्री

3
हैलो, मुझे वास्तव में किसी दृश्य या फ़ंक्शन के लिए सपा को परिवर्तित किए बिना ऐसा करने की आवश्यकता है, क्या यह संभव है?
लुइस बेसेरिल

2
जबकि आपका जवाब एक सच्चा कथन है, यह सवाल का जवाब नहीं देता है .... "संग्रहीत कार्यविधि का चयन करें" जो सुनिश्चित करता है कि यह आदर्श नहीं है, लेकिन यह वही है जो ... @ आमिर का उत्तर सही उत्तर है। या तो उस प्रश्न को बदलने की जरूरत है ... जो मुझे थोड़ा हास्यास्पद लगता है।
उर्सक्वायरेल

202

आप ऐसा कर सकते हैं

  1. संग्रहित खरीद से सेट परिणाम को रखने के लिए एक टेबल चर बनाएं और फिर
  2. संग्रहीत चर के आउटपुट को तालिका चर में डालें, और फिर
  3. टेबल वेरिएबल का उपयोग ठीक वैसे ही करें जैसे आप किसी अन्य टेबल ...

... sql ...।

Declare @T Table ([column definitions here])
Insert @T Exec storedProcname params 
Select * from @T Where ...

34
के साथ समस्या INSERT #Tया INSERT @Tयह है कि एक INSERT EXECबयान नेस्टेड नहीं किया जा सकता है। यदि संग्रहीत प्रक्रिया पहले से ही इसमें INSERT EXECहै, तो यह काम नहीं करेगा।
MOHCTP

2
यह शायद सबसे पोर्टेबल समाधान है, जो मूल एसक्यूएल के सबसे करीब है। यह मजबूत स्तंभ प्रकार परिभाषाओं को बनाए रखने में भी मदद करता है। ऊपर वालों की तुलना में अधिक upvotes होना चाहिए।

तालिका चर एसपी recompile के मामले में अस्थायी तालिकाओं की तुलना में यहाँ और अधिक उपयोगी लग रहा है। तो मैं मानता हूं, इस उत्तर में अधिक उत्थान होना चाहिए।
resnyanskiy

76

आप या तो टेबल-वेल्यू किए गए फ़ंक्शन चाहते हैं या अपने EXEC को एक अस्थायी तालिका में सम्मिलित करते हैं:

INSERT INTO #tab EXEC MyProc

32
के साथ समस्या INSERT #Tया INSERT @Tयह है कि एक INSERT EXECबयान नेस्टेड नहीं किया जा सकता है। यदि संग्रहीत प्रक्रिया पहले से ही इसमें INSERT EXECहै, तो यह काम नहीं करेगा।
MOHCTP

46

आपको OPENROWSET और OPENQUERY के बारे में जरूर पढ़ना चाहिए

SELECT  * 
INTO    #tmp FROM    
OPENQUERY(YOURSERVERNAME, 'EXEC MyProc @parameters')

4
कैसे गतिशील रूप से आपका प्राप्त करने के लिए? आप हमेशा जानने की उम्मीद नहीं कर सकते। क्या यह हर दूसरे मंगलवार को नहीं टूटेगा? सो अगर मुझे 100 सर्वर सब अलग-अलग नामों से मिले हैं ...
Urasquirrel

यह भी कि यदि मेरा डेटाबेस इसे अनुमति देने के लिए कॉन्फ़िगर नहीं किया गया है तो क्या होगा?
उर्सक्वायरेल

4
इसे गतिशील रूप से प्राप्त करने के लिए @@ सर्वरनाम आज़माएं
सिद्धार्थ गांधी

44

आपको एक तालिका प्रकार घोषित करने की आवश्यकता है जिसमें समान संख्या में कॉलम होते हैं जो आपकी स्टोर प्रक्रिया वापस आ रही है। तालिका प्रकार में स्तंभों के डेटा प्रकार और प्रक्रियाओं द्वारा लौटाए गए स्तंभ समान होने चाहिए

declare @MyTableType as table
(
FIRSTCOLUMN int
,.....
)  

फिर आपको अपनी तालिका में आपके द्वारा निर्धारित प्रक्रिया के परिणाम को सम्मिलित करना होगा

Insert into @MyTableType 
EXEC [dbo].[MyStoredProcedure]

अंत में बस अपने टेबल प्रकार से चयन करें

Select * from @MyTableType

यह मेरे लिए सबसे अच्छा समाधान है, क्योंकि आपको सर्वर नाम, कनेक्शन स्ट्रिंग्स को निर्दिष्ट करने की आवश्यकता नहीं है या इसे काम करने के लिए किसी भी लिंक किए गए सर्वर को कॉन्फ़िगर करना होगा - वे चीजें हैं जो मैं सिर्फ पाने के लिए नहीं करना चाहता हूं कुछ डेटा वापस। धन्यवाद! अजीब जवाब!
मैट

अच्छा जवाब ღ answer ღ❤ღ ೋ❤ ღ❤
नाहिद

जब संग्रहीत प्रक्रिया बहुत भिन्न होती है - यह विधि काम नहीं करती है, उदाहरण के लिए, जब संग्रहीत प्रक्रिया दो अस्थायी-तालिकाओं का उपयोग करती है।
nic_n_a

34

यह आवश्यक नहीं है कि एक अस्थायी तालिका का उपयोग करें।

यह मेरा समाधान है

SELECT  *  FROM    
OPENQUERY(YOURSERVERNAME, 'EXEC MyProc @parameters')
WHERE somefield = anyvalue

2
इसके लिए आपको अपने सर्वर को खुद से लिंक सर्वर के रूप में जोड़ना होगा, लेकिन यह एक आकर्षण की तरह काम करता है! धन्यवाद!
vaheeds

इस पर कुछ महान चेतावनी: stackoverflow.com/questions/2374741/…
कीथ एडलर

1
हम्म ... मुझे त्रुटि मिल रही है "त्रुटि 7411: सर्वर 'YourServerName' DATA ACCESS के लिए कॉन्फ़िगर नहीं किया गया है।" मुझे क्या बदलने की आवश्यकता है?
मैट

क्या आपने अपने सर्वर को लिंक्ड सर्वर के रूप में जोड़ा है? YourServerName आपके सर्वर का नाम है। आपको अपने असली सर्वर नाम के साथ YourServerName को बदलना होगा।
डेविडीडीएम

@ sp_serveroption 'MYSERVER', 'DATA ACCESS', TRUE;
मट

23

आप उत्पादन को पीछे से अस्थायी तालिका में कॉपी कर सकते हैं।

CREATE TABLE #GetVersionValues
(
    [Index] int,
    [Name]  sysname,
    Internal_value  int,
    Character_Value sysname
)
INSERT #GetVersionValues EXEC master.dbo.xp_msver 'WindowsVersion'
SELECT * FROM #GetVersionValues
drop TABLE #GetVersionValues

7

OPENQUERY और befor Execute सेट का उपयोग करें 'FM FMLY OFF; सेट पर सेट करें! '

इस नमूना कोड का प्रयास करें:

SELECT top(1)*
FROM
OPENQUERY( [Server], 'SET FMTONLY OFF; SET NOCOUNT ON; EXECUTE  [database].[dbo].[storedprocedure]  value,value ')

6

अपनी प्रक्रिया को इनलाइन फ़ंक्शन में परिवर्तित करने का प्रयास करें जो निम्नानुसार तालिका लौटाता है:

CREATE FUNCTION MyProc()
RETURNS TABLE AS
RETURN (SELECT * FROM MyTable)

और फिर आप इसे कॉल कर सकते हैं

SELECT * FROM MyProc()

आपके पास फ़ंक्शन को निम्न प्रकार से पास करने का विकल्प भी है:

CREATE FUNCTION FuncName (@para1 para1_type, @para2 para2_type , ... ) 

और बुला लो

SELECT * FROM FuncName ( @para1 , @para2 )

6

यदि 'डेटा पहुंच' गलत है,

EXEC sp_serveroption 'SQLSERVERNAME', 'DATA ACCESS', TRUE

उपरांत,

SELECT  *  FROM OPENQUERY(SQLSERVERNAME, 'EXEC DBNAME..MyProc @parameters')

यह काम करता हैं।


5

आप OPENROWSET के साथ थोड़ा धोखा कर सकते हैं:

SELECT ...fieldlist...
FROM OPENROWSET('SQLNCLI', 'connection string', 'name of sp')
WHERE ...

यह निश्चित रूप से हर बार पूरे एसपी को चलाएगा।


4

सादगी के लिए और इसे फिर से चलाने योग्य बनाने के लिए, मैंने डेटा प्राप्त करने के लिए एक सिस्टम StoredProcedure "sp_readerrorlog" का उपयोग किया है:

-----USING Table Variable
DECLARE @tblVar TABLE (
   LogDate DATETIME,
   ProcessInfo NVARCHAR(MAX),
   [Text] NVARCHAR(MAX)
)
INSERT INTO @tblVar Exec sp_readerrorlog
SELECT LogDate as DateOccured, ProcessInfo as pInfo, [Text] as Message FROM @tblVar



-----(OR): Using Temp Table
IF OBJECT_ID('tempdb..#temp') IS NOT NULL  DROP TABLE #temp;
CREATE TABLE #temp (
   LogDate DATETIME,
   ProcessInfo NVARCHAR(55),
   Text NVARCHAR(MAX)
)
INSERT INTO #temp EXEC sp_readerrorlog
SELECT * FROM #temp

1

ऐसा लगता है कि आपको सिर्फ एक दृश्य का उपयोग करने की आवश्यकता हो सकती है । एक दृश्य एक क्वेरी को एक तालिका के रूप में प्रस्तुत करने की अनुमति देता है ताकि यह, दृश्य, क्वियर किया जा सके।


1

यदि आपके सर्वर को उदाहरण के लिए SERVERX कहा जाता है, तो मैंने इसे कैसे किया ...

EXEC sp_serveroption 'SERVERX', 'DATA ACCESS', TRUE;
DECLARE @CMD VARCHAR(1000);
DECLARE @StudentID CHAR(10);
SET @StudentID = 'STUDENT01';
SET @CMD = 'SELECT * FROM OPENQUERY([SERVERX], ''SET FMTONLY OFF; SET NOCOUNT ON; EXECUTE MYDATABASE.dbo.MYSTOREDPROC ' + @StudentID + ''') WHERE SOMEFIELD = SOMEVALUE';
EXEC (@CMD);

इस काम को जांचने के लिए, मैंने EXEC()कमांड लाइन पर टिप्पणी की और इसे SELECT @CMDनिष्पादित करने का प्रयास करने से पहले कमांड की समीक्षा करने की जगह ले ली ! यह सुनिश्चित करना था कि सभी सही संख्या में एकल-उद्धरण सही जगह पर थे। :-)

मुझे उम्मीद है कि किसी की मदद करता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.