मेरे पास एक ऐसा फ़ंक्शन है जो एक स्ट्रिंग को विभाजित करता है (स्पष्टता के अंत में चिपकाया जाता है)। यह फ़ंक्शन अकेले उपयोग किए जाने पर अपेक्षित कार्य करता है। उदाहरण:"WHERE ... IN" खंड में शामिल होने पर udf में अजीब त्रुटि
SELECT * FROM TableA WHERE TableA.id IN
(
SELECT value
FROM dbo.mg_fn_Split('2#1','#')
)
मैं:
SELECT value
FROM dbo.mg_fn_Split('2#1','#')
रिटर्न
-- value --
-- 2 --
-- 1 --
-----------
लेकिन जब इस उदाहरण (TableA के बारे में अधिक बाद में) में एक "कहां में" खंड में इस्तेमाल किया, के रूप में त्रुटि: "बाएं या सबस्ट्रिंग फ़ंक्शन को पास किया गया अमान्य लंबाई पैरामीटर।"
टेबलए का उपयोग उदाहरण के रूप में किया जाता है। विभिन्न तालिकाओं का उपयोग करना (माना जाता है कि उनके पास आईडी कॉलम है) कभी-कभी सही परिणाम देता है, जबकि अन्य तालिकाओं पर मुझे त्रुटि मिलती है।
मुझे लगता है कि इसे निष्पादन के आदेश के साथ कुछ करना है, लेकिन मैं अभी भी यह देखने में असफल रहा कि फ़ंक्शन "भ्रष्ट" क्या हो सकता है।
मैं "क्या हो रहा है" स्पष्टीकरण की तलाश में हूं, न कि "इसके बजाय इसका उपयोग करें"। मुझे पता है कि परिणाम प्राप्त करने के लिए मैं उदाहरण के लिए जॉइन का उपयोग कर सकता हूं।
समारोह परिभाषा:
-- Description: Returns a table containing the results of a string-split operation.
-- Params:
-- DelimitedList: The string to split
-- Delimiter: The delimiter char, defaults to ','
-- Columns:
-- Position - The char index of the item
-- Value - The actual item
-- =============================================
CREATE Function [dbo].[mg_fn_Split]
(
@DelimitedList nvarchar(max)
, @Delimiter nvarchar(2) = ','
)
RETURNS TABLE
AS
RETURN
(
With CorrectedList As
(
Select Case When Left(@DelimitedList, Len(@Delimiter)) <> @Delimiter Then @Delimiter Else '' End
+ @DelimitedList
+ Case When Right(@DelimitedList, Len(@Delimiter)) <> @Delimiter Then @Delimiter Else '' End
As List
, Len(@Delimiter) As DelimiterLen
)
, Numbers As
(
Select TOP(Coalesce(DataLength(@DelimitedList)/2,0)) Row_Number() Over (Order By c1.object_id) As Value
From sys.columns As c1
Cross Join sys.columns As c2
)
Select CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen As Position
, Substring (
CL.List
, CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen
, CharIndex(@Delimiter, CL.list, N.Value + 1)
- (CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen)
) As Value
From CorrectedList As CL
Cross Join Numbers As N
Where N.Value <= DataLength(CL.List)/2
And Substring(CL.List, N.Value, CL.DelimiterLen) = @Delimiter
)
संपादित करें: मैं इस प्रदर्शन करने के लिए एक बेला सेट कर लेते हैं: http://sqlfiddle.com/#!3/9f9ff/3
इनलाइन यूडीएफ क्वेरी में विस्तारित हो गए हैं, इसलिए शायद कुछ शामिल संचालन या फ़िल्टर का मूल्यांकन एक अलग क्रम में किया जा रहा है जिसकी आपने अपेक्षा नहीं की थी। –
जॉइन का उपयोग न करने का कारण क्या है? आईएमएचओ यदि संभव हो तो एसक्यूएल कमांड से स्ट्रिंग पार्सिंग छोड़ना सबसे अच्छा है। –
मैं मार्टिन की टिप्पणी से सहमत हूं, मेरा मानना है कि आपके फ़ंक्शन के लिए आपका WHERE क्लॉज टेबलए से आपके चयन * पर धक्का दिया जा रहा है। यदि आप निम्नलिखित और सबस्ट्रिंग (CL.List, N.Value, CL.DelimiterLen) = @ आपके फ़ंक्शन में डिलीमीटर को टिप्पणी करते हैं तो आपको -1 के मूल्यांकन वाले आपके सबस्ट्रिंग मानों में से एक के कारण प्रदर्शित एक ही समस्या मिल जाएगी। –