T-SQL का उपयोग करके उप-स्ट्रिंग की अंतिम घटना का सूचकांक खोजें


128

वहाँ एसक्यूएल का उपयोग कर एक स्ट्रिंग की अंतिम घटना का सूचकांक खोजने का एक सीधा तरीका है? मैं अभी SQL Server 2000 का उपयोग कर रहा हूं। मुझे मूल रूप से कार्यक्षमता की आवश्यकता है जो .NET System.String.LastIndexOfविधि प्रदान करती है। एक छोटे से googling ने यह प्रकट किया - अंतिम इंडेक्स प्राप्त करने के लिए फ़ंक्शन - लेकिन वह काम नहीं करता है यदि आप "टेक्स्ट" कॉलम की अभिव्यक्ति में पास होते हैं। अन्य समाधान जो कहीं और पाए जाते हैं वे केवल इतने लंबे समय तक काम करते हैं जब आप जिस पाठ को खोज रहे हैं वह 1 वर्ण लंबा है।

मुझे संभवतः एक समारोह पकाना होगा। यदि मैं ऐसा करता हूं, तो मैं इसे यहां पोस्ट करूंगा ताकि आप लोग इसे देख सकें और शायद इसका उपयोग कर सकें।

जवाबों:


33

आप पाठ डेटा प्रकार के कार्यों की छोटी सूची तक सीमित हैं ।

मेरे सुझाव से सभी शुरू हो सकते हैं PATINDEX, लेकिन DATALENGTH-1, DATALENGTH-2, DATALENGTH-3जब तक आप परिणाम प्राप्त नहीं करते हैं, तब तक पीछे से काम करते हैं या शून्य पर समाप्त होते हैं (DATALENGTH-DATALENGTH)

यह वास्तव में कुछ ऐसा है जो SQL Server 2000बस नहीं संभाल सकता है।

अन्य उत्तरों के लिए संपादित करें : REVERSE उन कार्यों की सूची में नहीं है जिनका उपयोग SQL Server 2000 में पाठ डेटा के साथ किया जा सकता है


1
हाँ, यह बहुत अजीब है। ऐसा लगता है कि यह सरल होना चाहिए, केवल यह नहीं है!
राज

... यही कारण है कि SQL 2005 में सामान्य कार्यों की अनुमति देने के लिए varchar (अधिकतम) है
gbn

1
आह! इसलिए "varchar (मैक्सिमम)" एक SQL 2005 चीज है, जो बताती है कि जब मैंने SQL 2000 पर इसे आजमाया तो यह काम क्यों नहीं किया।
राज

DATALENGTH मेरे लिए सही परिणाम का उत्पादन करने में विफल रहता है, हालांकि LENGTH काम करता है।
टकीला

@ Tequila और अन्य: DATALENGTHबाइट्स की संख्या देता है वर्ण नहीं। इसलिए, DATALENGTHस्ट्रिंग के लिए स्ट्रिंग में वर्णों की संख्या 2 x लौटाता है NVARCHARLENहालाँकि, वर्णों की संख्या, किसी भी अनुगामी व्हाट्सएप को घटा देता है । मैं कभी नहीं का उपयोग DATALENGTHवर्ण की गणना के लिए, जब तक कि पिछली श्वेत रिक्ति महत्वपूर्ण है और मुझे यकीन है कि मेरी डेटाटाइप्स संगत कर रहे हैं, चाहे वे हो के लिए पता है VARCHARयाNVARCHAR
rbsdca

175

सीधा रास्ता? नहीं, लेकिन मैंने रिवर्स का उपयोग किया है। सचमुच।

पूर्व दिनचर्या में, किसी दिए गए स्ट्रिंग की अंतिम घटना को खोजने के लिए, मैंने REVERSE () फ़ंक्शन का उपयोग किया, CHARINDEX का अनुसरण किया, मूल आदेश को पुनर्स्थापित करने के लिए REVERSE द्वारा फिर से अनुसरण किया गया। उदाहरण के लिए:

SELECT
   mf.name
  ,mf.physical_name
  ,reverse(left(reverse(physical_name), charindex('\', reverse(physical_name)) -1))
 from sys.master_files mf

दिखाता है कि वास्तविक डेटाबेस फ़ाइल नामों को उनके "भौतिक नामों" से कैसे निकाला जाए, चाहे सबफ़ोल्डरों में कितना भी गहरा घोंसला क्यों न हो। यह केवल एक वर्ण (बैकस्लैश) के लिए खोज करता है, लेकिन आप लंबे खोज स्ट्रिंग्स के लिए इसका निर्माण कर सकते हैं।

केवल नकारात्मक पक्ष यह है कि मुझे नहीं पता कि यह TEXT डेटा प्रकारों पर कितना अच्छा काम करेगा। मैं अब कुछ वर्षों के लिए SQL 2005 पर रहा हूँ, और अब TEXT के साथ काम करने में कोई बातचीत नहीं कर रहा हूँ - लेकिन मुझे लगता है कि आप LEFT और RIGHT का उपयोग कर सकते हैं?

फिलिप


1
क्षमा करें - मुझे पूरा यकीन है कि जब मैंने 2000 के साथ काम किया था, तो मैंने कभी भी वापस नहीं किया, और मेरे पास वर्तमान में किसी भी SQL 2000 इंस्टॉलेशन तक नहीं है।
फिलिप केली

प्रतिभाशाली! इस तरह से इस समस्या पर हमला करने के लिए कभी नहीं सोचा होगा!
जारेड

4
अच्छा है! मैंने अपनी आवश्यकताओं के लिए संशोधित किया: email.Substring (0, email.lastIndexOf ('@')) == SELECT LEFT (ईमेल, LEN (ईमेल) -CHARINDEX ('@', REVERSE (ईमेल)))
फ़्रेड्रिक जोहानसन

1
चालाक सामान इस तरह से प्रोग्रामिंग इतना मजेदार है!
क्रिस

क्यों नहीं एक अतिरिक्त रिवर्स के बजाय मूल पर बाएं के बजाय दाएं का उपयोग करें
फिल

108

सबसे सरल तरीका है…।

REVERSE(SUBSTRING(REVERSE([field]),0,CHARINDEX('[expr]',REVERSE([field]))))

3
+1 क्योंकि 'कोई अमान्य मिलान पैरामीटर' LEFT या SUBSTRING फ़ंक्शन में पास नहीं हुआ है, अगर कोई मैच नहीं मिला, तो
Xilmiki

12
यदि आपका [expr]प्रतीक 1 से अधिक लंबा है, तो आपको इसे उल्टा करने की भी आवश्यकता है!
एंड्रियस नरुसेवीसियस

60

यदि आप Sqlserver 2005 या इसके बाद के संस्करण का उपयोग कर रहे हैं, तो REVERSEकई बार फ़ंक्शन का उपयोग प्रदर्शन के लिए हानिकारक है, नीचे कोड अधिक कुशल है।

DECLARE @FilePath VARCHAR(50) = 'My\Super\Long\String\With\Long\Words'
DECLARE @FindChar VARCHAR(1) = '\'

-- Shows text before last slash
SELECT LEFT(@FilePath, LEN(@FilePath) - CHARINDEX(@FindChar,REVERSE(@FilePath))) AS Before
-- Shows text after last slash
SELECT RIGHT(@FilePath, CHARINDEX(@FindChar,REVERSE(@FilePath))-1) AS After
-- Shows the position of the last slash
SELECT LEN(@FilePath) - CHARINDEX(@FindChar,REVERSE(@FilePath)) AS LastOccuredAt

1
यह स्पष्ट रूप से स्पष्ट लग सकता है, लेकिन यदि आप किसी एकल वर्ण के बजाय एक स्ट्रिंग की खोज कर रहे हैं, तो आपको करना होगा: LEN (@FilePath) - CHARINDEX (REVERSE (@FindString), REPERSE (@FilePath))
pkExec

14
DECLARE @FilePath VARCHAR(50) = 'My\Super\Long\String\With\Long\Words'
DECLARE @FindChar VARCHAR(1) = '\'

SELECT LEN(@FilePath) - CHARINDEX(@FindChar,REVERSE(@FilePath)) AS LastOccuredAt

8

पुराना, लेकिन अभी भी मान्य प्रश्न है, इसलिए यहाँ दूसरों द्वारा प्रदान की गई जानकारी के आधार पर मैंने जो बनाया है, वह विधमान है।

create function fnLastIndexOf(@text varChar(max),@char varchar(1))
returns int
as
begin
return len(@text) - charindex(@char, reverse(@text)) -1
end

7

इसने मेरे लिए बहुत अच्छा काम किया।

REVERSE(SUBSTRING(REVERSE([field]), CHARINDEX(REVERSE('[expr]'), REVERSE([field])) + DATALENGTH('[expr]'), DATALENGTH([field])))

6
REVERSE(SUBSTRING(REVERSE(ap_description),CHARINDEX('.',REVERSE(ap_description)),len(ap_description)))  

मेरे लिए बेहतर काम किया


4

हम्म, मुझे पता है कि यह एक पुराना धागा है, लेकिन टैली टेबल SQL2000 (या किसी अन्य डेटाबेस) में ऐसा कर सकता है:

DECLARE @str CHAR(21),
        @delim CHAR(1)
 SELECT @str = 'Your-delimited-string',
        @delim = '-'

SELECT
    MAX(n) As 'position'
FROM
    dbo._Tally
WHERE
    substring(@str, _Tally.n, 1) = @delim

टैली टेबल केवल संख्या बढ़ाने की तालिका है।

substring(@str, _Tally.n, 1) = @delimप्रत्येक सीमांकक की स्थिति हो जाता है, तो आप सिर्फ इतना है कि सेट में अधिकतम स्थिति मिलता है।

टैली टेबल कमाल की हैं। यदि आपने पहले उनका उपयोग नहीं किया है, तो SQL सर्वर सेंट्रल पर एक अच्छा लेख है (फ्री रेग, या बस बग मी नॉट का उपयोग करें ( http://www.bugmenot.com/view/sqlservercentral.com )।

* संपादित करें: हटा दिया n <= LEN(TEXT_FIELD), क्योंकि आप पाठ प्रकार पर LEN () का उपयोग नहीं कर सकते। जब तक substring(...) = @delimअवशेष हालांकि परिणाम अभी भी सही है।


अच्छा लगा। मुझे लगता है कि यह प्रभावी रूप से एक ही समाधान है हालांकि gbn द्वारा स्वीकृत उत्तर के रूप में; आप केवल पूर्णांक 1, 2, 3 आदि को संग्रहीत करने के लिए एक तालिका का उपयोग कर रहे हैं जो कि DATALENGTH से घटाया गया है और पिछले चरित्र के बजाय पहले वर्ण से आगे पढ़ना है।
माइकल पेटिटो

2

अपनी स्ट्रिंग और अपने सबस्ट्रिंग दोनों को उलट दें, फिर पहले घटना को खोजें।


अच्छी बात। मेरे पास अभी 2000 नहीं है, और मुझे याद नहीं आ रहा है अगर मैं यह कर सकता था जब मैंने किया था।
एके

2

कुछ अन्य उत्तर वास्तविक स्ट्रिंग लौटाते हैं जबकि मुझे वास्तविक सूचकांक इंट को जानने की अधिक आवश्यकता होती है। और जो उत्तर देते हैं, वे अति-जटिल चीजों में लगते हैं। प्रेरणा के रूप में कुछ अन्य उत्तरों का उपयोग करते हुए, मैंने निम्नलिखित कार्य किया ...

सबसे पहले, मैंने एक समारोह बनाया:

CREATE FUNCTION [dbo].[LastIndexOf] (@stringToFind varchar(max), @stringToSearch varchar(max))
RETURNS INT
AS
BEGIN
    RETURN (LEN(@stringToSearch) - CHARINDEX(@stringToFind,REVERSE(@stringToSearch))) + 1
END
GO

फिर, अपनी क्वेरी में आप बस ऐसा कर सकते हैं:

declare @stringToSearch varchar(max) = 'SomeText: SomeMoreText: SomeLastText'

select dbo.LastIndexOf(':', @stringToSearch)

उपरोक्त को 23 (':' का अंतिम सूचकांक) वापस करना चाहिए

उम्मीद है कि यह किसी के लिए यह थोड़ा आसान बना दिया!


2

मुझे लगता है कि यह कई साल पुराना सवाल है, लेकिन ...

पर Access 2010, आप ऐसा करने के InStrRev()लिए उपयोग कर सकते हैं । उम्मीद है की यह मदद करेगा।


2

यह उत्तर MS SQL Server 2008 का उपयोग करता है (मेरे पास MS SQL Server 2000 तक पहुंच नहीं है), लेकिन जिस तरह से मैं इसे ओपी के अनुसार देखता हूं वह 3 स्थितियों को ध्यान में रखना है। मैंने जो कुछ भी उत्तर देने की कोशिश की है, उनमें से सभी 3 को शामिल किया गया है:

  1. किसी दिए गए स्ट्रिंग में खोज वर्ण का अंतिम सूचकांक लौटाएँ।
  2. किसी दिए गए स्ट्रिंग में खोज उप-स्ट्रिंग (केवल एक वर्ण से अधिक) के अंतिम सूचकांक को लौटाएं।
  3. यदि खोज चरित्र या उप-स्ट्रिंग दिए गए स्ट्रिंग रिटर्न में नहीं है 0

समारोह मैं 2 मापदंडों के साथ आया:

@String NVARCHAR(MAX) : खोजा जाने वाला तार

@FindString NVARCHAR(MAX) : या तो एक एकल वर्ण या अंतिम उप-सूचकांक प्राप्त करने के लिए @String

यह एक ऐसा रिटर्न देता है जो INTया तो सकारात्मक सूचकांक होता @FindStringहै @Stringया 0जिसका अर्थ होता है@FindString में नहीं होता है@String

यहां बताया गया है कि फ़ंक्शन क्या करता है:

  1. इंगित @ReturnValकरने के लिए प्रारंभिक 0है कि अंदर @FindStringनहीं है@String
  2. चेकों के सूचकांक @FindStringमें @Stringका उपयोग करकेCHARINDEX()
  3. तो के सूचकांक @FindStringमें @Stringहै 0,@ReturnVal के रूप में छोड़ दिया जाता है0
  4. यदि इंडेक्स @FindStringइन @Stringहै > 0, तो यह @FindStringइन @Stringके अंतिम इंडेक्स की गणना करता @FindStringहै@String का उपयोग करकेREVERSE()
  5. वह रिटर्न @ReturnValजो या तो एक पॉजिटिव नंबर है, जो अंतिम इंडेक्स @FindStringहै @Stringया 0यह दर्शाता है कि अंदर @FindStringनहीं है@String

यहाँ बनाएँ समारोह स्क्रिप्ट (कॉपी और पेस्ट तैयार):

CREATE FUNCTION [dbo].[fn_LastIndexOf] 
(@String NVARCHAR(MAX)
, @FindString NVARCHAR(MAX))
RETURNS INT
AS 
BEGIN
    DECLARE @ReturnVal INT = 0
    IF CHARINDEX(@FindString,@String) > 0
        SET @ReturnVal = (SELECT LEN(@String) - 
        (CHARINDEX(REVERSE(@FindString),REVERSE(@String)) + 
        LEN(@FindString)) + 2)  
    RETURN @ReturnVal
END

यहाँ थोड़ा सा है जो आसानी से फ़ंक्शन का परीक्षण करता है:

DECLARE @TestString NVARCHAR(MAX) = 'My_sub2_Super_sub_Long_sub1_String_sub_With_sub_Long_sub_Words_sub2_'
, @TestFindString NVARCHAR(MAX) = 'sub'

SELECT dbo.fn_LastIndexOf(@TestString,@TestFindString)

मैंने इसे केवल एमएस एसक्यूएल सर्वर 2008 पर चलाया है क्योंकि मेरे पास किसी अन्य संस्करण तक पहुंच नहीं है लेकिन जो मैंने इस पर ध्यान दिया है वह 2008+ के लिए कम से कम अच्छा होना चाहिए।

का आनंद लें।


1

मुझे पता है कि यह अक्षम होगा, लेकिन क्या आपने इस textक्षेत्र में कास्टिंग करने पर विचार किया है varcharताकि आप अपनी वेबसाइट पर दिए गए समाधान का उपयोग कर सकें? मुझे पता है कि यह समाधान मुद्दों को पैदा करेगा क्योंकि आप संभावित रूप से रिकॉर्ड को काट सकते हैं यदि textक्षेत्र में लंबाई आपकी लंबाई से अधिक है varchar(यह उल्लेख नहीं है कि यह बहुत अच्छा नहीं होगा)।

चूंकि आपका डेटा एक textफ़ील्ड के अंदर है (और आप SQL सर्वर 2000 का उपयोग कर रहे हैं) आपके विकल्प सीमित हैं।


हां, "varchar" के लिए कास्टिंग एक विकल्प नहीं है क्योंकि अक्सर संसाधित होने वाले डेटा को "varchar" में आयोजित किए जाने वाले अधिकतम से अधिक होता है। आपके उत्तर के लिए धन्यवाद!
राज

1

यदि आप शब्दों के एक स्ट्रिंग में अंतिम स्थान का सूचकांक प्राप्त करना चाहते हैं, तो आप स्ट्रिंग में अंतिम शब्द को वापस करने के लिए इस अभिव्यक्ति RIGHT (नाम, (CHARINDEX ('', REVERSE (नाम), 0)) का उपयोग कर सकते हैं। यदि आप किसी पूर्ण नाम के अंतिम नाम को पार्स करना चाहते हैं जो पहले और / या मध्य नाम के लिए प्रारंभिक नाम शामिल करना चाहता है।


1

@indexOf = <whatever characters you are searching for in your string>

@LastIndexOf = LEN([MyField]) - CHARINDEX(@indexOf, REVERSE([MyField]))

परीक्षण नहीं किया गया है, यह शून्य सूचकांक के कारण एक-एक करके बंद हो सकता है, लेकिन यह तब काम करता है SUBSTRINGजब @indexOfवर्णों से काटकर आपकी स्ट्रिंग के अंत तक

SUBSTRING([MyField], 0, @LastIndexOf)


1

यदि कोडरिंग में 1 से अधिक वर्ण हैं तो भी यह कोड काम करता है।

DECLARE @FilePath VARCHAR(100) = 'My_sub_Super_sub_Long_sub_String_sub_With_sub_Long_sub_Words'
DECLARE @FindSubstring VARCHAR(5) = '_sub_'

-- Shows text before last substing
SELECT LEFT(@FilePath, LEN(@FilePath) - CHARINDEX(REVERSE(@FindSubstring), REVERSE(@FilePath)) - LEN(@FindSubstring) + 1) AS Before
-- Shows text after last substing
SELECT RIGHT(@FilePath, CHARINDEX(REVERSE(@FindSubstring), REVERSE(@FilePath)) -1) AS After
-- Shows the position of the last substing
SELECT LEN(@FilePath) - CHARINDEX(REVERSE(@FindSubstring), REVERSE(@FilePath)) AS LastOccuredAt

0

मैं एक फ़ोल्डर पथ में एक backslash की नौवीं अंतिम स्थिति को खोजने की जरूरत है। यहाँ मेरा समाधान है।

/*
http://stackoverflow.com/questions/1024978/find-index-of-last-occurrence-of-a-sub-string-using-t-sql/30904809#30904809
DROP FUNCTION dbo.GetLastIndexOf
*/
CREATE FUNCTION dbo.GetLastIndexOf
(
  @expressionToFind         VARCHAR(MAX)
  ,@expressionToSearch      VARCHAR(8000)
  ,@Occurrence              INT =  1        -- Find the nth last 
)
RETURNS INT
AS
BEGIN

    SELECT  @expressionToSearch = REVERSE(@expressionToSearch)

    DECLARE @LastIndexOf        INT = 0
            ,@IndexOfPartial    INT = -1
            ,@OriginalLength    INT = LEN(@expressionToSearch)
            ,@Iteration         INT = 0

    WHILE (1 = 1)   -- Poor man's do-while
    BEGIN
        SELECT @IndexOfPartial  = CHARINDEX(@expressionToFind, @expressionToSearch)

        IF (@IndexOfPartial = 0) 
        BEGIN
            IF (@Iteration = 0) -- Need to compensate for dropping out early
            BEGIN
                SELECT @LastIndexOf = @OriginalLength  + 1
            END
            BREAK;
        END

        IF (@Occurrence > 0)
        BEGIN
            SELECT @expressionToSearch = SUBSTRING(@expressionToSearch, @IndexOfPartial + 1, LEN(@expressionToSearch) - @IndexOfPartial - 1)
        END

        SELECT  @LastIndexOf = @LastIndexOf + @IndexOfPartial
                ,@Occurrence = @Occurrence - 1
                ,@Iteration = @Iteration + 1

        IF (@Occurrence = 0) BREAK;
    END

    SELECT @LastIndexOf = @OriginalLength - @LastIndexOf + 1 -- Invert due to reverse
    RETURN @LastIndexOf 
END
GO

GRANT EXECUTE ON GetLastIndexOf TO public
GO

यहाँ मेरे परीक्षण के मामले हैं जो गुजरते हैं

SELECT dbo.GetLastIndexOf('f','123456789\123456789\', 1) as indexOf -- expect 0 (no instances)
SELECT dbo.GetLastIndexOf('\','123456789\123456789\', 1) as indexOf -- expect 20
SELECT dbo.GetLastIndexOf('\','123456789\123456789\', 2) as indexOf -- expect 10
SELECT dbo.GetLastIndexOf('\','1234\6789\123456789\', 3) as indexOf -- expect 5

0

परिसीमन की अंतिम घटना से पहले भाग प्राप्त करने के लिए (केवल उपयोग के NVARCHARकारण काम करता है DATALENGTH):

DECLARE @Fullstring NVARCHAR(30) = '12.345.67890.ABC';

DECLARE @Delimiter CHAR(1) = '.';

SELECT SUBSTRING(@Fullstring, 1, DATALENGTH(@Fullstring)/2 - CHARINDEX(@Delimiter, REVERSE(@Fullstring)));

0

यह उत्तर ओपी की आवश्यकताओं को पूरा करता है। विशेष रूप से यह सुई को एक एकल चरित्र से अधिक होने की अनुमति देता है और यह एक त्रुटि उत्पन्न नहीं करता है जब सुई को छेद में नहीं पाया जाता है। मुझे ऐसा लग रहा था कि अन्य उत्तरों के अधिकांश (सभी?) उन किनारे के मामलों को संभाल नहीं पाए। इससे परे कि मैंने मूल MS SQL सर्वर CharIndex फ़ंक्शन द्वारा प्रदान की गई "प्रारंभिक स्थिति" तर्क जोड़ा। मैंने CharIndex के लिए विनिर्देशन को ठीक से देखने की कोशिश की, बायें से दायें के बजाय बायें से दायें प्रोसेस को छोड़कर। उदाहरण के तौर पर मैं नल को लौटाता हूं अगर सुई या हैस्टैक शून्य है और मैं शून्य लौटता हूं यदि सुई हीस्टैक में नहीं मिली है। एक चीज जो मुझे नहीं मिल सकी वह यह है कि बिल्ट इन फंक्शन के साथ तीसरा पैरामीटर वैकल्पिक है। SQL सर्वर उपयोगकर्ता परिभाषित कार्यों के साथ, कॉल में सभी मापदंडों को तब तक प्रदान किया जाना चाहिए जब तक कि फ़ंक्शन को "EXEC" का उपयोग न किया जाए। । जबकि तीसरे पैरामीटर को पैरामीटर सूची में शामिल किया जाना चाहिए, आप इसके लिए एक प्लेसहोल्डर के रूप में कीवर्ड को "डिफ़ॉल्ट" प्रदान कर सकते हैं, बिना इसे मूल्य दिए (उदाहरण नीचे देखें)। चूंकि इस फ़ंक्शन से तीसरे पैरामीटर को निकालना आसान है, यदि वांछित नहीं है तो इसे जोड़ना होगा यदि आवश्यक हो तो मैंने इसे एक प्रारंभिक बिंदु के रूप में यहां शामिल किया है।

create function dbo.lastCharIndex(
 @needle as varchar(max),
 @haystack as varchar(max),
 @offset as bigint=1
) returns bigint as begin
 declare @position as bigint
 if @needle is null or @haystack is null return null
 set @position=charindex(reverse(@needle),reverse(@haystack),@offset)
 if @position=0 return 0
 return (len(@haystack)-(@position+len(@needle)-1))+1
end
go

select dbo.lastCharIndex('xyz','SQL SERVER 2000 USES ANSI SQL',default) -- returns 0
select dbo.lastCharIndex('SQL','SQL SERVER 2000 USES ANSI SQL',default) -- returns 27
select dbo.lastCharIndex('SQL','SQL SERVER 2000 USES ANSI SQL',1) -- returns 27
select dbo.lastCharIndex('SQL','SQL SERVER 2000 USES ANSI SQL',11) -- returns 1

0

मैं अपनी इसी समस्या के समाधान की खोज करते हुए इस सूत्र में आया था जिसकी आवश्यकता एक ही थी लेकिन एक अलग तरह के डेटाबेस के लिए जो REVERSEफ़ंक्शन की कमी थी ।

मेरे मामले में यह एक OpenEdge (प्रगति) डेटाबेस के लिए था, जिसमें थोड़ा अलग वाक्यविन्यास है। इसने INSTRमेरे लिए सबसे अधिक Oracle टाइप किए गए डेटाबेस उपलब्ध कराए ।

तो मैं निम्नलिखित कोड के साथ आया:

SELECT 
  INSTR(foo.filepath, '/',1, LENGTH(foo.filepath) - LENGTH( REPLACE( foo.filepath, '/',  ''))) AS IndexOfLastSlash 
FROM foo

हालांकि, मेरी विशिष्ट स्थिति (होने के लिए) OpenEdge (प्रगति) डेटाबेस ) यह वांछित व्यवहार में परिणाम नहीं हुआ, क्योंकि चरित्र को खाली चार के साथ बदलने से मूल स्ट्रिंग के समान लंबाई दी गई। यह मेरे लिए बहुत मायने नहीं रखता है लेकिन मैं नीचे दिए गए कोड के साथ समस्या को बायपास करने में सक्षम था:

SELECT 
  INSTR(foo.filepath, '/',1, LENGTH( REPLACE( foo.filepath, '/',  'XX')) - LENGTH(foo.filepath))  AS IndexOfLastSlash 
FROM foo

अब मैं समझता हूं कि यह कोड समस्या का समाधान नहीं करेगा T-SQL के क्योंकि जो INSTRफ़ंक्शन प्रदान करता है उसका कोई विकल्प नहीं हैOccurence संपत्ति है।

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

  -- Drop the function if it already exists
  IF OBJECT_ID('INSTR', 'FN') IS NOT NULL
    DROP FUNCTION INSTR
  GO

  -- User-defined function to implement Oracle INSTR in SQL Server
  CREATE FUNCTION INSTR (@str VARCHAR(8000), @substr VARCHAR(255), @start INT, @occurrence INT)
  RETURNS INT
  AS
  BEGIN
    DECLARE @found INT = @occurrence,
            @pos INT = @start;

    WHILE 1=1 
    BEGIN
        -- Find the next occurrence
        SET @pos = CHARINDEX(@substr, @str, @pos);

        -- Nothing found
        IF @pos IS NULL OR @pos = 0
            RETURN @pos;

        -- The required occurrence found
        IF @found = 1
            BREAK;

        -- Prepare to find another one occurrence
        SET @found = @found - 1;
        SET @pos = @pos + 1;
    END

    RETURN @pos;
  END
  GO

स्पष्ट से बचने के लिए, जब REVERSEफ़ंक्शन उपलब्ध है, तो आपको इस स्केलर फ़ंक्शन को बनाने की आवश्यकता नहीं है और आप बस इस तरह आवश्यक परिणाम प्राप्त कर सकते हैं:

SELECT
  LEN(foo.filepath) - CHARINDEX('/', REVERSE(foo.filepath))+1 AS LastIndexOfSlash 
FROM foo
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.