Ich versuche, einen Wert aus einer Zeichenfolge zu analysieren, die den letztenIndex einer Zeichenfolge enthält. Derzeit mache ich einen schrecklichen Hack, bei dem eine Saite umgekehrt wird:
SELECT REVERSE(SUBSTRING(REVERSE(DB_NAME()), 1,
CHARINDEX('_', REVERSE(DB_NAME()), 1) - 1))
Für mich ist dieser Code kaum lesbar. Ich habe gerade ein Upgrade auf SQL Server 2016 durchgeführt und hoffe, dass es einen besseren Weg gibt.
Wenn Sie alles nach dem letzten _
wünschen, verwenden Sie:
select right(db_name(), charindex('_', reverse(db_name()) + '_') - 1)
Wenn Sie alles vorher wollen, verwenden Sie left()
:
select left(db_name(), len(db_name()) - charindex('_', reverse(db_name()) + '_'))
Schrieb 2 Funktionen, 1, um LastIndexOf für das ausgewählte Zeichen zurückzugeben.
CREATE FUNCTION dbo.LastIndexOf(@source nvarchar(80), @pattern char)
RETURNS int
BEGIN
RETURN (LEN(@source)) - CHARINDEX(@pattern, REVERSE(@source))
END;
GO
und 1, um eine Zeichenfolge vor diesem LastIndexOf zurückzugeben. Vielleicht wird es jemandem nützlich sein.
CREATE FUNCTION dbo.StringBeforeLastIndex(@source nvarchar(80), @pattern char)
RETURNS nvarchar(80)
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
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
Sobald Sie eine der Split-Strings von hier haben, können Sie dies auf eine bestimmte Art und Weise tun.
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
Nein, der SQL-Server verfügt nicht über LastIndexOf.
Dies sind die verfügbaren Zeichenketten Funktionen
Sie können jedoch jederzeit Ihre eigene Funktion erstellen
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
Ich bin auf diesen Thread gestoßen, als ich nach einer Lösung für mein ähnliches Problem gesucht habe, die genau die gleiche Anforderung hatte, aber für eine andere Art von Datenbank gedacht war, der die REVERSE
-Funktion fehlte.
In meinem Fall war dies eine OpenEdge (Progress) Datenbank, die eine etwas andere Syntax hat. Dadurch wurde die Funktion INSTR
für mich verfügbar, die die meisten von Oracle typisierten Datenbanken anbieten.
Also kam mir folgender Code:
SELECT
INSTR(foo.filepath, '/',1, LENGTH(foo.filepath) - LENGTH( REPLACE( foo.filepath, '/', ''))) AS IndexOfLastSlash
FROM foo
In meiner speziellen Situation (die Datenbank OpenEdge (Progress)) führte dies jedoch nicht zu dem gewünschten Verhalten, da das Ersetzen des Zeichens durch ein leeres Zeichen dieselbe Länge wie der ursprüngliche String ergab. Das macht für mich nicht viel Sinn, aber ich konnte das Problem mit dem folgenden Code umgehen:
SELECT
INSTR(foo.filepath, '/',1, LENGTH( REPLACE( foo.filepath, '/', 'XX')) - LENGTH(foo.filepath)) AS IndexOfLastSlash
FROM foo
Jetzt verstehe ich, dass dieser Code das Problem für T-SQL nicht lösen kann, da es keine Alternative zur INSTR
-Funktion gibt, die die Occurence
-Eigenschaft anbietet.
Um gründlich zu sein, füge ich den Code hinzu, der zum Erstellen dieser Skalarfunktion benötigt wird, damit er auf dieselbe Weise wie in den obigen Beispielen verwendet werden kann. Und wird genau das tun, was das OP wollte, als LastIndexOf -Methode für SQL Server.
-- 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
Um das Offensichtliche zu vermeiden, müssen Sie, wenn die Funktion REVERSE
verfügbar ist, diese Skalarfunktion nicht erstellen. Sie können das erforderliche Ergebnis wie folgt erhalten:
SELECT
LEN(foo.filepath) - CHARINDEX('\', REVERSE(foo.filepath))+1 AS LastIndexOfSlash
FROM foo