2016-08-17 34 views
14

मैं एक स्ट्रिंग से एक मान को पार्स करने का प्रयास कर रहा हूं जिसमें indexstring प्राप्त करना शामिल है। वर्तमान में, मैं एक भयानक हैक कि एक स्ट्रिंग पीछे शामिल कर रहा हूँ:क्या SQL सर्वर में LastIndexOf है?

SELECT REVERSE(SUBSTRING(REVERSE(DB_NAME()), 1, 
    CHARINDEX('_', REVERSE(DB_NAME()), 1) - 1)) 

इस कोड मेरे लिए लगभग पढ़ने योग्य नहीं है। मैंने अभी SQL सर्वर 2016 में अपग्रेड किया है और मुझे उम्मीद है कि एक बेहतर तरीका है। क्या वहां है?

+2

क्या आप अपनी स्ट्रिंग के कुछ उदाहरण दिखा सकते हैं? –

+0

मेरे लिए भी, यह केवल अपठनीय नहीं है और अनुमान लगाने में सक्षम नहीं है कि आप नमूना डेटा के बिना क्या हासिल करने की कोशिश कर रहे हैं :) – techspider

+2

प्यार स्टैक ओवरफ़्लो होना चाहिए जहां लोगों की पहली प्रतिक्रिया अधिक जानकारी मांगनी है, भले ही प्रश्न को और जानकारी की आवश्यकता न हो इसे हल करें :) –

उत्तर

36

तुम सब कुछ पिछले _ के बाद, तो उपयोग करना चाहते हैं:

select right(db_name(), charindex('_', reverse(db_name()) + '_') - 1) 

इससे पहले कि आप सब कुछ चाहते हैं, तो left() का उपयोग करें:

select left(db_name(), len(db_name()) - charindex('_', reverse(db_name()) + '_')) 
+0

@ डेनोथ। । । हाँ धन्यवाद। –

+0

मुझे पहली अभिव्यक्ति को बदलना पड़ा: 'दाएं (db_name(), charindex (' _ ', रिवर्स (db_name()) +' _ ') - 1)' यह काम करने के लिए! अन्यथा महान! – Egahn

1

एक बार जब आप split strings from here में से एक है, आप कर सकते हैं इसे इस तरह एक सेट आधारित तरीके से करें ..

declare @string varchar(max) 
set @string='C:\Program Files\Microsoft SQL Server\MSSQL\DATA\AdventureWorks_Data.mdf' 

;with cte 
as 
(select *,row_number() over (order by (select null)) as rownum 
from [dbo].[SplitStrings_Numbers](@string,'\') 
) 
select top 1 item from cte order by rownum desc 

**Output:** 
AdventureWorks_Data.mdf 
2

नहीं, एसक्यूएल सर्वर डी oesnt LastIndexOf है।

यह उपलब्ध स्ट्रिंग functions

हैं लेकिन जब मेरी समान समस्या जो सटीक था के लिए एक समाधान के लिए खोज

CREATE FUNCTION dbo.LastIndexOf(@source text, @pattern char) 
RETURNS 
AS  
BEGIN 
    DECLARE @ret text; 
    SELECT into @ret 
      REVERSE(SUBSTRING(REVERSE(@source), 1, 
      CHARINDEX(@pattern, REVERSE(@source), 1) - 1)) 
    RETURN @ret; 
END; 
GO 
1

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

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

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

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 संपत्ति प्रदान करता है।

बस पूरी तरह से होने के लिए मैं इस स्केलर फ़ंक्शन को बनाने के लिए आवश्यक कोड जोड़ूंगा ताकि इसका उपयोग उसी तरह किया जा सके जैसा मैंने उपर्युक्त उदाहरणों में किया था। और ठीक वही करेगा जो ओपी चाहता था, SQL सर्वर के लिए LastIndexOf विधि के रूप में कार्य करता है।

-- 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 
1

2 काम करता है, 1 लिखा चयनित चरित्र के लिए अंतिम IndexOf वापस करने के लिए।

CREATE FUNCTION dbo.LastIndexOf(@source nvarchar(20), @pattern char) 
RETURNS int 
BEGIN 
     RETURN (LEN(@source)) - CHARINDEX(@pattern, REVERSE(@source)) 
END; 
GO 

और 1 इस LastIndexOf से पहले एक स्ट्रिंग वापस करने के लिए। शायद यह किसी के लिए उपयोगी होगा।

CREATE FUNCTION dbo.StringBeforeLastIndex(@source nvarchar(20), @pattern char) 
RETURNS nvarchar(20) 
BEGIN 
     DECLARE @lastIndex int 
     SET @lastIndex = (LEN(@source)) - CHARINDEX(@pattern, REVERSE(@source)) 

    RETURN SUBSTRING(@source, 0, @lastindex + 1) 
    -- +1 because index starts at 0, but length at 1, so to get up to 11th index, we need LENGTH 11+1=12 
END; 
GO 
1
CREATE FUNCTION dbo.LastIndexOf(@text NTEXT, @delimiter NTEXT) 
RETURNS INT 
AS  
BEGIN 
    IF (@text IS NULL) RETURN NULL; 
    IF (@delimiter IS NULL) RETURN NULL; 
    DECLARE @Text2 AS NVARCHAR(MAX) = @text; 
    DECLARE @Delimiter2 AS NVARCHAR(MAX) = @delimiter; 
    DECLARE @Index AS INT = CHARINDEX(REVERSE(@Delimiter2), REVERSE(@Text2)); 
    IF (@Index < 1) RETURN 0; 
    DECLARE @ContentLength AS INT = (LEN('|' + @Text2 + '|') - 2); 
    DECLARE @DelimiterLength AS INT = (LEN('|' + @Delimiter2 + '|') - 2); 
    DECLARE @Result AS INT = (@ContentLength - @Index - @DelimiterLength + 2); 
    RETURN @Result; 
END 
  • की तरह "," (अल्पविराम अंतरिक्ष) बहु चरित्र सीमांकक के लिए अनुमति देता है।
  • यदि डिलीमीटर नहीं मिला है तो 0 लौटाता है।
  • आराम कारणों के लिए एक एनआईई लेता है क्योंकि एनवीएआरएआरएआर (MAX) को एनआईआर में निहित रूप से डाला जाता है लेकिन इसके विपरीत नहीं।
  • अग्रणी या पूंछ की जगह के साथ delimiters सही ढंग से संभालती है!
संबंधित मुद्दे