Mi sono imbattuto in questo thread durante la ricerca di una soluzione al mio problema simile che aveva gli stessi requisiti ma era per un diverso tipo di database che mancava anche la REVERSE
funzione.
Nel mio caso questo era per un database OpenEdge (Progress) , che ha una sintassi leggermente diversa. Ciò mi ha reso INSTR
disponibile la funzione offerta dalla maggior parte dei database tipizzati Oracle .
Quindi ho pensato al seguente codice:
SELECT
INSTR(foo.filepath, '/',1, LENGTH(foo.filepath) - LENGTH( REPLACE( foo.filepath, '/', ''))) AS IndexOfLastSlash
FROM foo
Tuttavia, per la mia situazione specifica (essendo il database OpenEdge (Progress) ) ciò non ha comportato il comportamento desiderato perché la sostituzione del carattere con un carattere vuoto ha dato la stessa lunghezza della stringa originale. Questo non ha molto senso per me, ma sono stato in grado di aggirare il problema con il codice seguente:
SELECT
INSTR(foo.filepath, '/',1, LENGTH( REPLACE( foo.filepath, '/', 'XX')) - LENGTH(foo.filepath)) AS IndexOfLastSlash
FROM foo
Ora capisco che questo codice non risolverà il problema per T-SQL perché non esiste alternativa alla INSTR
funzione che offre la Occurence
proprietà.
Per essere precisi, aggiungerò il codice necessario per creare questa funzione scalare in modo che possa essere usato allo stesso modo come ho fatto negli esempi precedenti.
-- 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
Per evitare l'ovvio, quando la REVERSE
funzione è disponibile non è necessario creare questa funzione scalare e si può semplicemente ottenere il risultato richiesto in questo modo:
SELECT
LEN(foo.filepath) - CHARINDEX('/', REVERSE(foo.filepath))+1 AS LastIndexOfSlash
FROM foo