Tenho a seguinte tabela de teste no SQL Server 2005:
CREATE TABLE [dbo].[TestTable]
(
[ID] [int] NOT NULL,
[TestField] [varchar](100) NOT NULL
)
Povoado com:
INSERT INTO TestTable (ID, TestField) VALUES (1, 'A value'); -- Len = 7
INSERT INTO TestTable (ID, TestField) VALUES (2, 'Another value '); -- Len = 13 + 6 spaces
Quando tento encontrar o comprimento de TestField com a função LEN () do SQL Server, ele não conta os espaços à direita - por exemplo:
-- Note: Also results the grid view of TestField do not show trailing spaces (SQL Server 2005).
SELECT
ID,
TestField,
LEN(TestField) As LenOfTestField, -- Does not include trailing spaces
FROM
TestTable
Como faço para incluir os espaços à direita no resultado do comprimento?
sql-server
Jason Snelders
fonte
fonte
Respostas:
Isso está claramente documentado pela Microsoft no MSDN em http://msdn.microsoft.com/en-us/library/ms190329(SQL.90).aspx , que declara LEN "retorna o número de caracteres da expressão de string especificada, excluindo espaços em branco à direita ". É, no entanto, um detalhe fácil de perder, se você não for cauteloso.
Em vez disso, você precisa usar a função DATALENGTH - consulte http://msdn.microsoft.com/en-us/library/ms173486(SQL.90).aspx - que "retorna o número de bytes usados para representar qualquer expressão".
Exemplo:
fonte
DATALENGTH
Você também precisará dividir o resultado por 2 se a expressão testada for um tipo de caractere largo (Unicode; nchar, nvarchar ou ntext), pois o resultado está em bytes , não em caracteres .varchar
etc., isso pode ser dependente do agrupamento e nem mesmo uma divisão direta por 2 é confiável. Veja o exemplo aquiLEN(REPLACE(expr, ' ', '_'))
. Isso deve funcionar comvarchar
envarchar
e strings contendo caracteres especiais de controle Unicode.DATALENGTH()
não deve ser considerado uma forma alternativa de contar caracteres porque conta bytes em vez de caracteres e isso é importante ao representar a mesma string emVARCHAR
/NVARCHAR
.Você pode usar este truque:
LEN (Str + 'x') - 1
fonte
Eu uso este método:
Eu prefiro isso em vez de DATALENGTH porque funciona com diferentes tipos de dados, e eu prefiro adicionar um caractere ao final porque você não precisa se preocupar com o caso extremo em que sua string já está no comprimento máximo.
Nota: Eu testaria o desempenho antes de usá-lo em um conjunto de dados muito grande; embora eu o tenha testado em 2 milhões de linhas e não tenha sido mais lento do que LEN sem REPLACE ...
fonte
Você pede a alguém para registrar uma solicitação de aprimoramento / relatório de bug do SQL Server porque quase todas as soluções alternativas listadas para esse problema incrivelmente simples aqui têm alguma deficiência ou são ineficientes. Isso ainda parece ser verdade no SQL Server 2012. O recurso de corte automático pode se originar do ANSI / ISO SQL-92, mas parece haver algumas lacunas (ou a falta de contá-las).
Vote em "Adicionar configuração para que LEN conte os espaços em branco à direita" aqui:
https://feedback.azure.com/forums/908035-sql-server/suggestions/34673914-add-setting-so-len-counts-trailing-whitespace
Retired Connect link: https://connect.microsoft.com/SQLServer/feedback/details/801381
fonte
datalength
solução é ainda pior a partir do SQL server 2012, pois agora ele oferece suporte a pares substitutos em UTF-16, o que significa que um caractere pode usar até 4 bytes. Está na hora de eles corrigirem alen
função de conformidade com ANSI, ou pelo menos fornecer uma função dedicada para contagem de caracteres incluindo espaços à direita.Existem problemas com as duas respostas mais votadas. A resposta recomendando
DATALENGTH
está sujeita a erros do programador. O resultado deDATALENGTH
deve ser dividido por 2 paraNVARCHAR
tipos, mas não paraVARCHAR
tipos. Isso requer conhecimento do tipo do qual você está obtendo o comprimento e, se esse tipo mudar, você terá que alterar diligentemente os locais que usouDATALENGTH
.Também há um problema com a resposta mais votada (que, admito, era minha maneira preferida de fazer isso até que esse problema me mordesse). Se o que você está obtendo com o comprimento for do tipo
NVARCHAR(4000)
e, na verdade, contiver uma string de 4.000 caracteres, o SQL irá ignorar o caractere anexado em vez de lançar implicitamente o resultadoNVARCHAR(MAX)
. O resultado final é um comprimento incorreto. O mesmo acontecerá com VARCHAR (8000).O que eu descobri que funciona, é quase tão rápido quanto o normal
LEN
, é mais rápido do queLEN(@s + 'x') - 1
para strings grandes e não assume que a largura do caractere subjacente seja a seguinte:Isso obtém o comprimento de dados e, em seguida, divide pelo comprimento de dados de um único caractere da string. O apêndice de 'x' cobre o caso em que a string está vazia (o que resultaria em uma divisão por zero nesse caso). Isso funciona se
@s
éVARCHAR
ouNVARCHAR
. Fazer oLEFT
de 1 caractere antes do acréscimo corta algum tempo quando a string é grande. O problema com isso, porém, é que não funciona corretamente com strings contendo pares substitutos.Há outra forma mencionada em um comentário para a resposta aceita, usando
REPLACE(@s,' ','x')
. Essa técnica dá a resposta correta, mas é algumas ordens de magnitude mais lenta do que as outras técnicas quando a corda é grande.Dados os problemas introduzidos por pares substitutos em qualquer técnica que use
DATALENGTH
, acho que o método mais seguro que dá respostas corretas que conheço é o seguinte:Isso é mais rápido do que a
REPLACE
técnica e muito mais rápido com cordas mais longas. Basicamente esta técnica é aLEN(@s + 'x') - 1
técnica, mas com proteção para o caso extremo onde a string tem um comprimento de 4000 (para nvarchar) ou 8000 (para varchar), de forma que a resposta correta é dada até mesmo para isso. Ele também deve lidar com strings com pares substitutos corretamente.fonte
N'x𤭢x' COLLATE Latin1_General_100_CI_AS_SC
dá 4, enquantoLEN
dá 3.Você também precisa garantir que seus dados sejam realmente salvos com os espaços em branco à direita. Quando ANSI PADDING está OFF (não padrão):
fonte
LEN corta espaços à direita por padrão, então descobri que isso funcionou conforme você os move para a frente
(LEN (REVERSE (TestField))
Então, se você quiser, você pode dizer
Não use isso para espaços iniciais, é claro.
fonte
declare @TestField varchar(10);
SET @TestField = ' abc '; -- Length with spaces is 5.
select LEN(REVERSE(@TestField)) -- Returns 4
select LEN(@TestField) -- Returns 4
Você deve definir uma função CLR que retorna o campo Comprimento da string, se você não gosta de concatinação de string. Eu uso
LEN('x' + @string + 'x') - 2
em meus casos de uso de produção.fonte
Se você não gosta de
DATALENGTH
devido a questões de n / varchar, que tal:que é apenas
embalado com proteção de divisão por zero.
Dividindo pelo DATALENGTH de um único caractere, obtemos o comprimento normalizado.
(Claro, ainda tem problemas com pares substitutos, se isso for uma preocupação.)
fonte
use SELECT DATALENGTH ('string')
fonte