mi sono imbattuto in questa discussione durante la ricerca di una soluzione al mio problema simile che ha avuto esattamente la stessa esigenza, ma è stato per un diverso tipo di database che è stato anche a mancare la funzione REVERSE
.
Nel mio caso questo era per un OpenEdge (Progress) database, che ha una sintassi leggermente diversa. Ciò ha reso disponibile la funzione INSTR
a most Oracle typed databases offer.
Così mi si avvicinò con il 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 OpenEdge (Progress) database) questo non ha comportato nel comportamento desiderato, perché la sostituzione del personaggio con un carattere vuoto ha 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 qui sotto:
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 un'alternativa alla funzione INSTR
che offre la proprietà Occurence
.
Giusto per essere accurato aggiungo il codice necessario per creare questa funzione scalare in modo che possa essere utilizzata allo stesso modo come ho fatto negli esempi sopra.
-- 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 funzione REVERSE
è disponibile non è necessario per creare questa funzione scalare e si può solo ottenere il risultato richiesto in questo modo:
SELECT
LEN(foo.filepath) - CHARINDEX('/', REVERSE(foo.filepath))+1 AS LastIndexOfSlash
FROM foo
Sì, è piuttosto imbarazzante. Sembra che dovrebbe essere semplice, solo che non lo è! – Raj
... ecco perché SQL 2005 ha varchar (max) per consentire le normali funzioni – gbn
Ah! così "varchar (max)" è una cosa di SQL 2005, che spiega perché non ha funzionato quando l'ho provato su SQL 2000. – Raj