98 votes

Existe-t-il un LastIndexOf dans le serveur SQL ?

J'essaie d'analyser une valeur à partir d'une chaîne de caractères, ce qui implique l'obtention de l'attribut dernier indice d'un chaîne de caractères . Actuellement, je suis en train de faire un horrible hack qui consiste à inverser une chaîne de caractères :

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

Pour moi, ce code est presque illisible. Je viens de passer à SQL Server 2016 et j'espère qu'il existe un meilleur moyen. En existe-t-il une ?

2 votes

Pouvez-vous montrer quelques exemples de votre chaîne ?

0 votes

Pour moi aussi, c'est non seulement illisible et impossible de deviner ce que vous essayez d'obtenir sans données échantillons :)

8 votes

J'adore Stack Overflow où la première réaction des gens est de demander plus d'informations alors que la question ne nécessite pas plus d'informations pour la résoudre :)

245voto

Gordon Linoff Points 213350

Si vous voulez tout ce qui se trouve après le dernier _ puis utiliser :

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

Si vous voulez tout avant, alors utilisez left() :

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

2 votes

J'ai dû changer la première expression en : right(db_name(), charindex('_', reverse(db_name()) + '_') - 1) pour que ça marche ! Sinon, c'est génial !

1 votes

La gauche devrait également avoir un décalage analogue au "-1" de la droite. Il devrait être : select left(db_name(), len(db_name()) - charindex('_', reverse(db_name()) + '_') + 1) (J'ai essayé d'éditer, mais le changement devait être d'au moins 6 caractères).

1 votes

La partie "+ '_'`" sert-elle à gérer le cas où _ ne figure pas dans le nom de la base de données ?

26voto

user2771704 Points 492

Écriture de 2 fonctions, 1 à retourner LastIndexOf pour le caractère sélectionné.

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

et 1 pour retourner une chaîne avant ce LastIndexOf. Peut-être cela sera-t-il utile à quelqu'un.

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

8voto

Juan Carlos Oropeza Points 34931

Non, le serveur SQL n'a pas de LastIndexOf.

Voici les chaînes disponibles fonctions

Mais vous pouvez toujours créer votre propre fonction

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

4voto

TheGameiswar Points 21

Une fois que vous avez l'un des diviser les chaînes de caractères à partir d'ici ,vous pouvez le faire d'une manière basée sur un ensemble comme ceci

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

4voto

chha Points 180
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
  • Permet d'utiliser des délimiteurs à plusieurs caractères tels que ", " (espace virgule).
  • Renvoie 0 si le délimiteur n'est pas trouvé.
  • Prend un NTEXT pour des raisons de confort, car les NVARCHAR(MAX)s sont implicitement convertis en NTEXT mais pas l'inverse.
  • Gère correctement les délimiteurs avec des espaces en tête ou en queue !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X