क्या मैं स्क्रिप्ट या संग्रहित प्रक्रिया में वन-टाइम-उपयोग फ़ंक्शन बना सकता हूं?


109

SQL Server 2005 में, क्या SQL स्क्रिप्ट या संग्रहित प्रक्रिया के अंदर घोषित एक-बार-उपयोग या स्थानीय फ़ंक्शन की अवधारणा है? मैं जिस स्क्रिप्ट को लिख रहा हूं, उसमें कुछ जटिलता को छोड़ना चाहता हूं, लेकिन इसे एक फंक्शन घोषित करने में सक्षम होना चाहिए।

बस उत्सुक।


वहाँ शायद एक बेहतर तरीका है कि आप एक फ़ंक्शन के बिना क्या करना चाहते हैं। शायद आपको उस कोड का एक स्निपेट पोस्ट करना चाहिए जिसे आप फ़ंक्शन में बदलना चाहते हैं?
DForck42

क्या आप गतिशील रूप से एक फ़ंक्शन उत्पन्न कर रहे हैं तो यह हर बार अलग है? यदि आप फ़ंक्शन हमेशा समान होते हैं तो इसे डेटाबेस में छोड़ दें
के.एम.

1
मैं इसे क्वेरी को अधिक पठनीय बनाने के तरीके के रूप में करने की कोशिश कर रहा था। विशाल प्रश्न बनाने के विचार को बनाए रखना कठिन हो जाता है।
Jp_

जवाबों:


65

आप CREATE Functionअपनी स्क्रिप्ट की शुरुआत और DROP Functionअंत के पास कॉल कर सकते हैं ।


6
मैं यह सुझाव देने जा रहा था। बस सावधान रहें कि आपकी स्क्रिप्ट खत्म हो जाए; यदि यह गर्भपात करता है, तो आप अभी भी डीबी में कार्य करेंगे।
चोकोजोश

6
आप प्रत्येक रन से पहले एक IF EXTSTS चेक कर सकते हैं और कुछ भी मिलने पर हटा सकते हैं।
एड्रियन गोडोंग

7
@chocojosh, यदि आप इसे लेन-देन में लपेटते हैं तो यह ठीक होना चाहिए। लेन-देन बम होने पर फ़ंक्शन डेटाबेस में नहीं होना चाहिए।
जेफ लाफे

12
@JoelCoehoorn: इसके लिए अभी भी लिखने के विशेषाधिकारों की आवश्यकता है।
user2284570

2
ध्यान दें कि यह एक फ़ंक्शन के अंदर काम नहीं करेगा - कार्यों के अंदर अस्थायी कार्यों की अनुमति नहीं है। देखें: Technet.microsoft.com/en-us/library/ms191320.aspx#Restrictions
डैनियल नील

95

आप अस्थायी संग्रहीत कार्यविधियाँ बना सकते हैं जैसे:

create procedure #mytemp as
begin
   select getdate() into #mytemptable;
end

SQL स्क्रिप्ट में, लेकिन फ़ंक्शंस नहीं। आपके पास यद्यपि यह एक अस्थायी तालिका में परिणामी दुकान हो सकती है, फिर स्क्रिप्ट में बाद में उस जानकारी का उपयोग करें।


7
इसका उत्तर होना चाहिए। यह वास्तव में एकल-उपयोग है यदि केवल कनेक्शन अस्थायी (एकल #) स्कूप किया गया है, और एसक्यूएल उपयोगकर्ता प्रतिबंधों को दरकिनार करने का लाभ है।
टॉड

इसका उपयोग कैसे किया जाता है? यह अभिव्यक्ति में चयन में इस्तेमाल प्रक्रिया के नाम में एक टाइपो नहीं है?
jgomo3

जब मैं BEGINकीवर्ड हटाता हूं , और ENDकीवर्ड को बदलने के साथ आपके उदाहरण संग्रहीत कार्यविधि से परिणाम प्राप्त करने में सक्षम हूं GO
जोसेफ डाइक्स्ट्रा

ओपी एक अस्थायी समारोह के लिए पूछ रहा था और कम से कम SQL सर्वर 2012 कार्यों के लिए -syntax की अनुमति नहीं देगा। केवल प्रक्रियाएं।
एरक

यह एक स्क्रिप्ट के भीतर कार्य नहीं करता है और अभी भी अनुमति की आवश्यकता हो सकती है। दोहराव वाले खंडों से बचने के लिए एकमात्र विकल्प SQL में कथन है।
एलेक्सर।

25

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


5
इसे सही उत्तर के रूप में स्वीकार किया जाना चाहिए। स्वीकृत उत्तर धागा सुरक्षित नहीं है।
कल्याण

11
निर्भर करता है कि आप क्या करने की कोशिश कर रहे हैं। मुझे यह सवाल इसलिए मिला क्योंकि मैं एक डेटा सीटर लिख रहा हूं और मैं 30 बार MERGE INTO की 10 लाइनें दोहराना नहीं चाहता। मुझे थ्रेडसेफ़ की परवाह नहीं है और सीटीई मेरे लिए काम नहीं करेगा।
सिपाही

16
मुझे लगता है कि यह जवाब है, और यह दावा है कि यह सही जवाब है, याद आती है कि सवाल एक अस्थायी उत्सव की तलाश में है, न कि अस्थायी तालिका। जब तक मैं कुछ याद नहीं कर रहा हूं (असामान्य नहीं) सीटीई टेम्पर टेबल के बराबर हैं।
जेडी लॉन्ग

8
एक फ़ंक्शन तर्क ले सकता है जबकि एक CTE नहीं कर सकता।
रेज़वान फ्लेवियस पांडा

4
CTE और एक अस्थायी संग्रहित प्रक्रिया के बीच कई अंतर हैं (जो कि सही उत्तर यहाँ IMO है)। शुरुआत के लिए, सीटीई केवल एक बयान के लिए मौजूद हैं, जबकि अस्थायी चर का उपयोग पूरी स्क्रिप्ट में किया जा सकता है। अन्य अंतरों में शामिल हैं: (1) CTE एक ही तर्क नहीं रख सकता है कि एक SP, (2) CTE चर स्वीकार नहीं कर सकता है। एक सीटीई सिर्फ वाक्यगत शर्करा है जो आपको एक बयान में उपयोग के लिए अधिक आसानी से नेस्टेड टेबल एक्सप्रेशंस बनाने की अनुमति देता है। फिर भी वे खतरनाक प्रदर्शन-वार हो सकते हैं यदि आपको कैविटीज़ की जानकारी नहीं है।
यह उतार चढ़ाव भरा

12

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

DECLARE @add_a_b_func nvarchar(4000) = N'SELECT @c = @a + @b;';
DECLARE @add_a_b_parm nvarchar(500) = N'@a int, @b int, @c int OUTPUT';

DECLARE @result int;
EXEC sp_executesql @add_a_b_func, @add_a_b_parm, 2, 3, @c = @result OUTPUT;
PRINT CONVERT(varchar, @result); -- prints '5'

4

स्क्रिप्ट में आपके पास अधिक विकल्प होते हैं और तर्कसंगत अपघटन पर एक बेहतर शॉट होता है। SQLCMD मोड में देखें (क्वेरी मेनू -> SQLCMD मोड), विशेष रूप से: setvar और: r कमांड।

एक संग्रहीत प्रक्रिया के भीतर आपके विकल्प बहुत सीमित हैं। आप सीधे कार्यविधि के साथ किसी फ़ंक्शन को परिभाषित नहीं कर सकते। सबसे अच्छा आप कुछ ऐसा कर सकते हैं, गतिशील एसक्यूएल के साथ:

create proc DoStuff
as begin

  declare @sql nvarchar(max)

  /*
  define function here, within a string
  note the underscore prefix, a good convention for user-defined temporary objects
  */
  set @sql = '
    create function dbo._object_name_twopart (@object_id int)
    returns nvarchar(517) as
    begin
      return 
        quotename(object_schema_name(@object_id))+N''.''+
        quotename(object_name(@object_id))
    end
  '

  /*
  create the function by executing the string, with a conditional object drop upfront
  */
  if object_id('dbo._object_name_twopart') is not null drop function _object_name_twopart
  exec (@sql)

  /*
  use the function in a query
  */
  select object_id, dbo._object_name_twopart(object_id) 
  from sys.objects
  where type = 'U'

  /*
  clean up
  */
  drop function _object_name_twopart

end
go

यह एक वैश्विक अस्थायी फ़ंक्शन का अनुमान लगाता है, अगर ऐसा कुछ मौजूद था। यह अभी भी अन्य उपयोगकर्ताओं के लिए दृश्यमान है। आप नाम को अद्वितीय बनाने के लिए अपने कनेक्शन के @@ SPID को जोड़ सकते हैं, लेकिन इसके बाद डायनेमिक डेटा का भी उपयोग करने के लिए बाकी प्रक्रिया की आवश्यकता होगी।


3

नीचे मैंने वही किया है जो मैंने MS SQL में Scalar UDF की आवश्यकता को पूरा करने के लिए इस्तेमाल किया है:

IF OBJECT_ID('tempdb..##fn_Divide') IS NOT NULL DROP PROCEDURE ##fn_Divide
GO
CREATE PROCEDURE ##fn_Divide (@Numerator Real, @Denominator Real) AS
BEGIN
    SELECT Division =
        CASE WHEN @Denominator != 0 AND @Denominator is NOT NULL AND  @Numerator != 0 AND @Numerator is NOT NULL THEN
        @Numerator / @Denominator
        ELSE
            0
        END
    RETURN
END
GO

Exec ##fn_Divide 6,4

यह दृष्टिकोण जो PROCEDURE के लिए एक वैश्विक चर का उपयोग करता है, आपको न केवल आपकी लिपियों में, बल्कि आपकी गतिशील SQL आवश्यकताओं में भी फ़ंक्शन का उपयोग करने की अनुमति देता है।

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