Existe uma maneira direta de encontrar o índice da última ocorrência de uma string usando SQL? Estou usando o SQL Server 2000 agora. Basicamente, preciso da funcionalidade que o System.String.LastIndexOf
método .NET fornece. Um pouco de pesquisa revelou isso - Função para recuperar o último índice - mas isso não funciona se você passar uma expressão de coluna "texto". Outras soluções encontradas em outros lugares funcionam apenas desde que o texto que você está procurando tenha 1 caractere.
Provavelmente terei que preparar uma função. Se eu fizer isso, vou postá-lo aqui para que vocês possam ver e talvez fazer uso.
DATALENGTH
retorna o número de bytes, não caracteres. Portanto,DATALENGTH
retorna 2 x o número de caracteres em uma string paraNVARCHAR
strings.LEN
, no entanto, retorna o número de caracteres, menos qualquer espaço em branco à direita . Eu nunca utilizarDATALENGTH
para o cálculo do comprimento de caracteres, a menos espaços em branco é significativo e eu sei com certeza que os meus tipos de dados são consistentes, quer sejamVARCHAR
ouNVARCHAR
Maneira simples? Não, mas eu usei o contrário. Literalmente.
Em rotinas anteriores, para encontrar a última ocorrência de uma determinada string, usei a função REVERSE (), seguida de CHARINDEX, seguida novamente por REVERSE para restaurar a ordem original. Por exemplo:
mostra como extrair os nomes dos arquivos de banco de dados reais de seus "nomes físicos", não importa quão profundamente aninhados nas subpastas. Isso procura apenas um caractere (a barra invertida), mas você pode criar isso para cadeias de pesquisa mais longas.
A única desvantagem é que não sei como isso funcionará nos tipos de dados TEXT. Estou no SQL 2005 há alguns anos e não estou mais familiarizado com o trabalho com o TEXT - mas me lembro que você poderia usar ESQUERDA e DIREITA nele?
Philip
fonte
A maneira mais simples é ....
fonte
[expr]
símbolo for maior que 1, você também precisará revertê-lo!Se você estiver usando o Sqlserver 2005 ou superior, o uso da
REVERSE
função muitas vezes é prejudicial ao desempenho, o código abaixo é mais eficiente.fonte
fonte
Pergunta antiga, mas ainda válida, então aqui está o que eu criei com base nas informações fornecidas por outras pessoas aqui.
fonte
Isso funcionou muito bem para mim.
fonte
funcionou melhor para mim
fonte
Hmm, eu sei que esse é um thread antigo, mas uma tabela de registro poderia fazer isso no SQL2000 (ou em qualquer outro banco de dados):
Uma tabela de registro é apenas uma tabela de números incrementados.
O
substring(@str, _Tally.n, 1) = @delim
obtém a posição de cada delimitador, então você apenas obtém a posição máxima nesse conjunto.As tabelas de registro são incríveis. Se você não os tiver usado antes, há um bom artigo no SQL Server Central (registro gratuito ou use Bug Me Not ( http://www.bugmenot.com/view/sqlservercentral.com )).
* EDIT: Removido
n <= LEN(TEXT_FIELD)
, pois você não pode usar LEN () no tipo TEXT. Enquanto ossubstring(...) = @delim
restos que o resultado ainda está correto.fonte
Inverta sua string e sua substring e procure a primeira ocorrência.
fonte
Algumas das outras respostas retornam uma string real, enquanto eu precisava mais saber o índice real int. E as respostas que fazem isso parecem complicar demais as coisas. Usando algumas das outras respostas como inspiração, fiz o seguinte ...
Primeiro, criei uma função:
Em seguida, na sua consulta, você pode simplesmente fazer o seguinte:
O acima deve retornar 23 (o último índice de ':')
Espero que isso tenha tornado um pouco mais fácil para alguém!
fonte
Sei que essa é uma pergunta de vários anos, mas ...
Ativado
Access 2010
, você pode usarInStrRev()
para fazer isso. Espero que isto ajude.fonte
Esta resposta usa o MS SQL Server 2008 (não tenho acesso ao MS SQL Server 2000), mas a maneira como a vejo de acordo com o OP são três situações a serem consideradas. Pelo que tentei, nenhuma resposta aqui abrange todos os três:
0
A função que criei tem 2 parâmetros:
@String NVARCHAR(MAX)
: A sequência a ser pesquisada@FindString NVARCHAR(MAX)
: Um único caractere ou uma sub-string para obter o último índice de@String
Ele retorna um
INT
que seja o índice de positividade de@FindString
em@String
ou0
o que significa que@FindString
não está no@String
Aqui está uma explicação do que a função faz:
@ReturnVal
para0
indicar que@FindString
não está em@String
@FindString
no@String
usandoCHARINDEX()
@FindString
in@String
for0
,@ReturnVal
é deixado como0
@FindString
in@String
for> 0
,@FindString
for in@String
, ele calculará o último índice de@FindString
in@String
usandoREVERSE()
@ReturnVal
que é um número positivo que é o último índice de@FindString
in@String
ou0
indica que@FindString
não está em@String
Aqui está o script da função create (pronto para copiar e colar):
Aqui está um pouco que testa convenientemente a função:
Eu executei isso apenas no MS SQL Server 2008 porque não tenho acesso a nenhuma outra versão, mas pelo que examinei isso deve ser bom para 2008 ou mais.
Aproveitar.
fonte
Sei que será ineficiente, mas você já pensou em lançar o
text
campo paravarchar
poder usar a solução fornecida pelo site encontrado? Sei que essa solução criaria problemas, pois você poderia truncar o registro se o comprimento notext
campo exceder o comprimento do seuvarchar
(para não mencionar que não teria muito desempenho).Como seus dados estão dentro de um
text
campo (e você está usando o SQL Server 2000), suas opções são limitadas.fonte
Se você deseja obter o índice do último espaço em uma sequência de palavras, pode usar esta expressão RIGHT (nome, (CHARINDEX ('', REVERSE (nome), 0)) para retornar a última palavra na sequência. é útil se você deseja analisar o sobrenome de um nome completo que inclua iniciais para o nome e / ou o nome do meio.
fonte
@indexOf = <whatever characters you are searching for in your string>
@LastIndexOf = LEN([MyField]) - CHARINDEX(@indexOf, REVERSE([MyField]))
Não foi testado, pode ser desativado em um por causa do índice zero, mas funciona em
SUBSTRING
função ao cortar os@indexOf
caracteres até o final da sua stringSUBSTRING([MyField], 0, @LastIndexOf)
fonte
Esse código funciona mesmo se a substring contiver mais de 1 caractere.
fonte
Eu precisava encontrar a enésima última posição de uma barra invertida em um caminho de pasta. Aqui está a minha solução.
Aqui estão meus casos de teste que passam
fonte
Para obter a peça antes da última ocorrência do delimitador (funciona apenas
NVARCHAR
devido aoDATALENGTH
uso):fonte
Esta resposta atende aos requisitos do OP. especificamente, permite que a agulha tenha mais do que um único caractere e não gera um erro quando a agulha não é encontrada no palheiro. Pareceu-me que a maioria (todas?) Das outras respostas não lidou com esses casos extremos. Além disso, adicionei o argumento "Posição inicial" fornecido pela função CharIndex do servidor MS SQL nativo. Tentei espelhar exatamente a especificação do CharIndex, exceto para processar da direita para a esquerda, em vez da esquerda para a direita. por exemplo, retornarei nulo se a agulha ou o palheiro for nulo e retornarei zero se a agulha não for encontrada no palheiro. Uma coisa que eu não conseguia entender é que, com a função incorporada, o terceiro parâmetro é opcional. Com as funções definidas pelo usuário do SQL Server, todos os parâmetros devem ser fornecidos na chamada, a menos que a função seja chamada usando "EXEC" . Embora o terceiro parâmetro deva ser incluído na lista de parâmetros, você pode fornecer a palavra-chave "padrão" como um espaço reservado para ele sem precisar atribuir um valor (consulte os exemplos abaixo). Como é mais fácil remover o terceiro parâmetro dessa função, se não for desejado, do que seria adicioná-lo, se necessário, eu o incluí aqui como ponto de partida.
fonte
Me deparei com esse segmento enquanto procurava uma solução para meu problema semelhante, que tinha exatamente o mesmo requisito, mas era para um tipo diferente de banco de dados que também não possuía o
REVERSE
função.No meu caso, isso era para um banco de dados OpenEdge (Progress) , que possui uma sintaxe um pouco diferente. Isso
INSTR
disponibilizou para mim a função que a maioria dos bancos de dados digitados Oracle oferece .Então, eu vim com o seguinte código:
No entanto, para minha situação específica (sendo o banco de dados OpenEdge (Progress) ), isso não resultou no comportamento desejado, pois a substituição do caractere por um caractere vazio deu o mesmo comprimento que a string original. Isso não faz muito sentido para mim, mas eu pude ignorar o problema com o código abaixo:
Agora entendo que esse código não resolverá o problema do T-SQL porque não há alternativa à
INSTR
função que oferece oOccurence
propriedade.Apenas para ser aprofundado, adicionarei o código necessário para criar esta função escalar, para que possa ser usada da mesma maneira que fiz nos exemplos acima.
Para evitar o óbvio, quando a
REVERSE
função está disponível, você não precisa criar essa função escalar e pode obter o resultado necessário da seguinte maneira:fonte