Quero colocar em maiúscula apenas a primeira letra de cada palavra de cada sentença em uma coluna SQL.
Por exemplo, se a sentença for:
'Eu gosto de filmes'
então eu preciso da saída:
'Eu gosto de filmes'
Inquerir:
declare @a varchar(15)
set @a = 'qWeRtY kEyBoArD'
select @a as [Normal text],
upper(@a) as [Uppercase text],
lower(@a) as [Lowercase text],
upper(left(@a,1)) + lower(substring(@a,2,len(@a))) as [Capitalize first letter only]
Aqui, coloquei maiúsculas, minúsculas e maiúsculas na primeira letra apenas na minha coluna (aqui coloquei apenas uma palavra aleatória).
Aqui estão meus resultados:
Existe alguma possibilidade de fazer isso?
Alguma possibilidade de obter resultados sem usar a função definida pelo usuário?
Eu preciso da saída Qwerty Keyboard
sql-server
sql-server-2014
Marin Mohanadas
fonte
fonte
Respostas:
Isso primeiro converte a string em XML, substituindo todos os espaços pela tag vazia
<X/>
. Em seguida, fragmenta o XML para obter uma palavra por linha usandonodes()
. Para obter as linhas de volta a um valor, ele usa ofor xml path
truque.fonte
for xml path
truque da concatenação. A menos que você opte pelo CLR, qual seria a melhor opção se a velocidade e a eficiência forem importantes.No SQL Server 2016, você pode fazer isso com o R, por exemplo
Se você deve ou não é uma pergunta diferente:)
fonte
Talvez eu esteja sendo bobo, mas verificando a consulta abaixo que escrevi em relação a algumas das fornecidas, isso parece ser um pouco mais eficiente (dependendo da indexação).
O código é um pouco estúpido, mas não existe um ditado que diz que se parece estúpido, mas funciona, então não é estúpido.
fonte
Outra opção é lidar com isso via SQLCLR. Existe até um método já disponível no .NET que faz isso: TextInfo.ToTitleCase (in
System.Globalization
). Este método fará maiúsculas a primeira letra de cada palavra e minúsculas as letras restantes. Diferentemente das outras propostas aqui, ele também ignora as palavras que estão em maiúsculas, assumindo que sejam siglas. Obviamente, se esse comportamento for desejado, seria fácil atualizar qualquer uma das sugestões do T-SQL para fazer isso também.Um benefício do método .NET é que ele pode letras maiúsculas que são caracteres suplementares. Por exemplo: DESERET SMALL LETTER OW possui um mapeamento em maiúsculas de DESERET CAPITAL LETTER OW (ambos aparecem como caixas quando eu os colo aqui) , mas a
UPPER()
função não altera a versão minúscula para maiúscula, mesmo quando o padrão de agrupamento para o banco de dados atual é definida comoLatin1_General_100_CI_AS_SC
. Isso parece consistente com a documentação do MSDN que não listaUPPER
eLOWER
no gráfico de funções que se comportam de maneira diferente ao usar um_SC
agrupamento: agrupamento e suporte a Unicode: caracteres suplementares .Retornos (ampliados para que você possa realmente ver o Personagem Suplementar):
Você pode ver a lista completa (e atual) de caracteres em minúsculas e mudar para maiúscula usando o seguinte recurso de pesquisa no Unicode.org (você pode ver os caracteres complementares rolando para baixo até chegar ao "DESERET" seção, ou apenas pressione Control-Fe pesquise essa palavra):
http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B%3AChanges_When_Titlecased%3DYes%3A%5D
Embora, para ser sincero, este não seja um grande benefício, pois é duvidoso que alguém esteja realmente usando algum dos Personagens Suplementares que podem ser escritos em título. De qualquer maneira, aqui está o código SQLCLR:
Aqui está a sugestão de @ MikaelEriksson - modificada levemente para manipular
NVARCHAR
dados e pular palavras que estão todas em maiúsculas (para corresponder melhor ao comportamento do método .NET) - junto com um teste dessa implementação T-SQL e de a implementação do SQLCLR:Outra diferença de comportamento é que essa implementação T-SQL específica se divide apenas em espaços, enquanto o
ToTitleCase()
método considera a maioria das não letras como separadores de palavras (daí a diferença no manuseio da parte "um & DOIS").Ambas as implementações lidam com a combinação correta de seqüências. Cada uma das letras acentuadas em "üvÜlA" é composta por uma letra base e uma diérese / trema combinada (os dois pontos acima de cada letra) e são convertidas corretamente para o outro caso nos dois testes.
Por fim, uma desvantagem inesperada da versão do SQLCLR é que, ao apresentar vários testes, encontrei um bug no código .NET relacionado ao manuseio das letras circuladas (que agora foi relatado no Microsoft Connect - UPDATE: Connect foi mudou-se para
/dev/null
- literalmente -, então talvez seja necessário reenviá-lo se o problema persistir). A biblioteca .NET trata as letras circuladas como separadores de palavras, e é por isso que não transforma o ""D" em "Ⓐdd" como deveria.Para sua informação
Uma função SQLCLR pré-concluída que encapsula o
TextInfo.ToTitleCase
método mencionado acima agora está disponível na versão gratuita do SQL # (que escrevi) como String_ToTitleCase e String_ToTitleCase4k .😺
fonte
Como alternativa à resposta de Mikael Eriksson , você pode considerar o uso do tratamento T-SQL proprietário da configuração de variáveis nas instruções de seleção de várias linhas.
No SQL Server, quando uma variável está sendo definida como parte de uma instrução SELECT, cada linha executará uma iteração da lógica definida.
As pessoas costumam usar esse método para concatenar seqüências de caracteres, embora não seja suportado e haja alguns problemas oficialmente documentados . O problema oficial está relacionado a características específicas de ORDER BY, e não precisamos disso aqui, talvez seja uma opção segura.
Aqui, iteramos sobre as 26 letras do alfabeto e as substituímos por uma versão em maiúscula se elas forem precedidas por um espaço. (Preparamos a sequência inicialmente colocando em maiúscula a primeira letra e deixando o restante em minúsculas, como você fez na sua pergunta.)
O SQL é um pouco complexo porque requer o uso de uma Tabela Tally - uma tabela de números - para gerar as 26 iterações de substituição que ele está fazendo. Você pode criar uma TVF (função definida pelo usuário) com valor de tabela útil para produzir essa tabela de números ou pode usar uma tabela física.
Uma desvantagem dessa opção é que ela não pode fazer parte de um TVF em linha, pois precisa envolver a configuração de uma variável. Portanto, se você quiser aplicar esse método a uma coluna da sua saída, precisará envolvê-lo em um TVF com várias instruções ou em uma função escalar definida pelo usuário.
No entanto, seu plano de consulta é muito mais simples e provavelmente é significativamente mais rápido que o método XML. Você pode argumentar que é mais fácil entender também (especialmente se você tiver sua própria tabela de contagem).
(Testei isso usando uma string muito maior e foram cerca de 6ms vs 14ms para a solução XML.)
Existem várias limitações adicionais com esta solução. Conforme escrito, ele pressupõe um agrupamento que não diferencia maiúsculas de minúsculas, embora você possa eliminar esse problema especificando um agrupamento ou executando o LCASE no termo da pesquisa, ao custo de algum desempenho. Ele também trata apenas de letras ASCII padrão e depende de sua localização no conjunto de caracteres , portanto, não faria nada com ñ.
fonte
Supondo que você esteja apenas procurando colocar letras maiúsculas em um espaço, aqui está outra maneira de fazê-lo.
fonte
Pode não ser à prova de balas, mas espero que seja uma contribuição útil para este tópico.
fonte
Abaixo está o procedimento que eu usei em um banco de dados Firebird para fazer isso. Provavelmente pode ser muito limpo, mas o trabalho foi feito para mim.
fonte
CTEs recursivas são muito boas para esse tipo de coisa.
Provavelmente não é particularmente eficiente para operações grandes, mas permite esse tipo de operação em uma instrução SQL select pura:
Resultado:
fonte
Eu gosto desta versão. É simples e pode ser usado para criar uma função, você só precisa ter a versão correta do SQL Server:
fonte
Espero que ajude ...
fonte
Dados de teste
Implementação
fonte