Natknąłem się na ten wątek, szukając rozwiązania mojego podobnego problemu, które miało dokładnie takie same wymagania, ale dotyczyło innego rodzaju bazy danych, która również nie zawierała REVERSE
funkcji.
W moim przypadku był to plik bazy danych OpenEdge (Progress) , która ma nieco inną składnię. Dzięki temu INSTR
udostępniono mi funkcję, którą oferuje większość baz danych typu Oracle .
Więc wymyśliłem następujący kod:
SELECT
INSTR(foo.filepath, '/',1, LENGTH(foo.filepath) - LENGTH( REPLACE( foo.filepath, '/', ''))) AS IndexOfLastSlash
FROM foo
Jednak w mojej konkretnej sytuacji (będącej OpenEdge (Progress) danych ) nie spowodowało to pożądanego zachowania, ponieważ zastąpienie znaku pustym znakiem dało taką samą długość jak oryginalny ciąg. Nie ma to dla mnie większego sensu, ale udało mi się ominąć problem z poniższym kodem:
SELECT
INSTR(foo.filepath, '/',1, LENGTH( REPLACE( foo.filepath, '/', 'XX')) - LENGTH(foo.filepath)) AS IndexOfLastSlash
FROM foo
Teraz rozumiem, że ten kod nie rozwiąże problemu T-SQL ponieważ nie ma alternatywy dla INSTR
funkcji, która oferujeOccurence
właściwość.
Dla dokładności dodam kod potrzebny do utworzenia tej funkcji skalarnej, aby można było jej używać w taki sam sposób, jak w powyższych przykładach.
-- 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
Aby uniknąć oczywistego, gdy REVERSE
funkcja jest dostępna, nie musisz tworzyć tej funkcji skalarnej i możesz po prostu uzyskać wymagany wynik w następujący sposób:
SELECT
LEN(foo.filepath) - CHARINDEX('/', REVERSE(foo.filepath))+1 AS LastIndexOfSlash
FROM foo