¿Hay una manera sencilla de encontrar el índice de la última aparición de una cadena usando SQL? Estoy usando SQL Server 2000 en este momento. Básicamente necesito la funcionalidad que System.String.LastIndexOf
proporciona el método .NET . Una pequeña búsqueda en Google reveló esto: Función para recuperar el último índice , pero eso no funciona si pasa una expresión de columna de "texto". Otras soluciones que se encuentran en otros lugares funcionan solo mientras el texto que está buscando tenga 1 carácter.
Probablemente tendré que preparar una función. Si lo hago, lo publicaré aquí para que lo puedan ver y tal vez usarlo.
DATALENGTH
devuelve el número de bytes, no caracteres. Por lo tanto,DATALENGTH
devuelve 2 veces el número de caracteres en una cadena paraNVARCHAR
cadenas.LEN
, sin embargo, devuelve el número de caracteres, menos cualquier espacio en blanco al final . Nunca lo usoDATALENGTH
para el cálculo de la longitud de los caracteres, a menos que el espacio en blanco final sea significativo y estoy seguro de que mis tipos de datos son consistentes, ya seanVARCHAR
oNVARCHAR
¿De manera directa? No, pero he usado lo contrario. Literalmente.
En rutinas anteriores, para encontrar la última ocurrencia de una cadena dada, utilicé la función REVERSE (), seguí CHARINDEX, seguido nuevamente por REVERSE para restaurar el orden original. Por ejemplo:
muestra cómo extraer los nombres de archivo de base de datos reales de sus "nombres físicos", sin importar cuán profundamente anidados en las subcarpetas. Esto solo busca un carácter (la barra invertida), pero puede aprovecharlo para cadenas de búsqueda más largas.
El único inconveniente es que no sé qué tan bien funcionará esto en los tipos de datos TEXT. He estado en SQL 2005 durante algunos años y ya no estoy familiarizado con el trabajo con TEXT, pero parece recordar que podría usar IZQUIERDA y DERECHA en él.
Philip
fuente
La forma más simple es ...
fuente
[expr]
es más largo que 1 símbolo, ¡también debes invertirlo!Si está utilizando Sqlserver 2005 o superior, el uso de la
REVERSE
función muchas veces es perjudicial para el rendimiento, el siguiente código es más eficiente.fuente
fuente
Pregunta antigua pero aún válida, así que aquí está lo que creé basado en la información proporcionada por otros aquí.
fuente
Esto funcionó muy bien para mí.
fuente
funcionó mejor para mí
fuente
Hmm, sé que este es un hilo antiguo, pero una tabla de conteo podría hacer esto en SQL2000 (o cualquier otra base de datos):
Una tabla de conteo es solo una tabla de números incrementales.
El
substring(@str, _Tally.n, 1) = @delim
obtiene la posición de cada delimitador, a continuación, que acaba de obtener la máxima posición en ese conjunto.Las tablas de conteo son increíbles. Si no los ha usado antes, hay un buen artículo sobre SQL Server Central (Free reg, o simplemente use Bug Me Not ( http://www.bugmenot.com/view/sqlservercentral.com )).
* EDITAR: eliminado
n <= LEN(TEXT_FIELD)
, ya que no puede usar LEN () en el tipo de TEXTO. Mientrassubstring(...) = @delim
permanezca, el resultado sigue siendo correcto.fuente
Invierta tanto su cadena como su subcadena, luego busque la primera aparición.
fuente
Algunas de las otras respuestas devuelven una cadena real, mientras que tenía más necesidad de conocer el índice real int. Y las respuestas que hacen eso parecen complicar demasiado las cosas. Usando algunas de las otras respuestas como inspiración, hice lo siguiente ...
Primero, creé una función:
Luego, en su consulta, simplemente puede hacer esto:
Lo anterior debería devolver 23 (el último índice de ':')
¡Espero que esto lo haya hecho un poco más fácil para alguien!
fuente
Me doy cuenta de que esta es una pregunta de varios años, pero ...
Encendido
Access 2010
, puede usarInStrRev()
para hacer esto. Espero que esto ayude.fuente
Esta respuesta usa MS SQL Server 2008 (no tengo acceso a MS SQL Server 2000), pero la forma en que lo veo de acuerdo con el OP son 3 situaciones a tener en cuenta. Por lo que he intentado, ninguna respuesta aquí cubre los 3 de ellos:
0
La función que se me ocurrió toma 2 parámetros:
@String NVARCHAR(MAX)
: La cadena a buscar@FindString NVARCHAR(MAX)
: Un solo carácter o una subcadena para obtener el último índice de en@String
Devuelve un
INT
que es el índice positivo de@FindString
in@String
o un0
significado que@FindString
no está en@String
Aquí hay una explicación de lo que hace la función:
@ReturnVal
para0
indicar que@FindString
no está en@String
@FindString
en@String
mediante el uso deCHARINDEX()
@FindString
in@String
es0
,@ReturnVal
se deja como0
@FindString
en@String
es> 0
,@FindString
es en@String
lo que calcula el último índice de@FindString
en@String
mediante el uso deREVERSE()
@ReturnVal
que es un número positivo que es el último índice de@FindString
in@String
o0
que indica que@FindString
no está en@String
Aquí está el script de función crear (copiar y pegar listo):
Aquí hay un poco que prueba convenientemente la función:
Solo ejecuté esto en MS SQL Server 2008 porque no tengo acceso a ninguna otra versión, pero por lo que he investigado, esto debería ser bueno para 2008+ al menos.
Disfrutar.
fuente
Sé que será ineficiente, pero ¿ha considerado enviar el
text
campo paravarchar
que pueda usar la solución proporcionada por el sitio web que encontró? Sé que esta solución crearía problemas, ya que potencialmente podría truncar el registro si la longitud en eltext
campo desbordara la longitud de suvarchar
(sin mencionar que no sería muy eficiente).Como sus datos están dentro de un
text
campo (y está utilizando SQL Server 2000), sus opciones son limitadas.fuente
Si desea obtener el índice del último espacio en una cadena de palabras, puede usar esta expresión DERECHA (nombre, (CHARINDEX ('', REVERSE (name), 0)) para devolver la última palabra en la cadena. es útil si desea analizar el apellido de un nombre completo que incluye las iniciales del primer y / o segundo nombre.
fuente
@indexOf = <whatever characters you are searching for in your string>
@LastIndexOf = LEN([MyField]) - CHARINDEX(@indexOf, REVERSE([MyField]))
No lo he probado, puede estar desactivado por uno debido al índice cero, pero funciona en
SUBSTRING
función cuando se corta desde los@indexOf
caracteres hasta el final de la cadenaSUBSTRING([MyField], 0, @LastIndexOf)
fuente
Este código funciona incluso si la subcadena contiene más de 1 carácter.
fuente
Necesitaba encontrar la enésima última posición de una barra diagonal inversa en una ruta de carpeta. Aquí está mi solución.
Aquí están mis casos de prueba que pasan
fuente
Para obtener la parte antes de la última aparición del delimitador (solo funciona
NVARCHAR
debido alDATALENGTH
uso):fuente
Esta respuesta cumple con los requisitos del OP. específicamente, permite que la aguja tenga más de un solo carácter y no genera un error cuando no se encuentra la aguja en el pajar. Me pareció que la mayoría (¿todas?) De las otras respuestas no manejaban esos casos extremos. Más allá de eso, agregué el argumento "Posición inicial" proporcionado por la función CharIndex del servidor MS SQL nativo. Traté de reflejar exactamente la especificación para CharIndex, excepto para procesar de derecha a izquierda en lugar de izquierda a derecha. Por ejemplo, devuelvo nulo si la aguja o el pajar son nulos y devuelvo cero si la aguja no se encuentra en el pajar. Una cosa que no pude evitar es que con la función incorporada el tercer parámetro es opcional. Con las funciones definidas por el usuario de SQL Server, todos los parámetros deben proporcionarse en la llamada a menos que la función se llame usando "EXEC" . Si bien el tercer parámetro debe incluirse en la lista de parámetros, puede proporcionar la palabra clave "default" como marcador de posición sin tener que asignarle un valor (consulte los ejemplos a continuación). Dado que es más fácil eliminar el tercer parámetro de esta función si no se desea que agregarlo si es necesario, lo he incluido aquí como punto de partida.
fuente
Encontré este hilo mientras buscaba una solución a mi problema similar que tenía exactamente el mismo requisito pero era para un tipo diferente de base de datos que también carecía de la
REVERSE
función.En mi caso, esto fue para una base de datos OpenEdge (Progress) , que tiene una sintaxis ligeramente diferente. Esto puso
INSTR
a mi disposición la función que ofrecen la mayoría de las bases de datos escritas de Oracle .Entonces se me ocurrió el siguiente código:
Sin embargo, para mi situación específica (que es la base de datos OpenEdge (Progress) ) esto no resultó en el comportamiento deseado porque reemplazar el carácter con un carácter vacío dio la misma longitud que la cadena original. Esto no tiene mucho sentido para mí, pero pude evitar el problema con el siguiente código:
Ahora entiendo que este código no resolverá el problema de T-SQL porque no hay alternativa a la
INSTR
función que ofrece laOccurence
propiedad.Solo para ser exhaustivo, agregaré el código necesario para crear esta función escalar para que pueda usarse de la misma manera que lo hice en los ejemplos anteriores.
Para evitar lo obvio, cuando la
REVERSE
función está disponible no necesita crear esta función escalar y simplemente puede obtener el resultado requerido de esta manera:fuente