Tengo la siguiente tabla de prueba en SQL Server 2005:
CREATE TABLE [dbo].[TestTable]
(
[ID] [int] NOT NULL,
[TestField] [varchar](100) NOT NULL
)
Poblado con:
INSERT INTO TestTable (ID, TestField) VALUES (1, 'A value'); -- Len = 7
INSERT INTO TestTable (ID, TestField) VALUES (2, 'Another value '); -- Len = 13 + 6 spaces
Cuando trato de encontrar la longitud de TestField con la función SQL Server LEN (), no cuenta los espacios finales, por ejemplo:
-- 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
¿Cómo incluyo los espacios finales en el resultado de la longitud?
sql-server
Jason Snelders
fuente
fuente
Respuestas:
Esto está claramente documentado por Microsoft en MSDN en http://msdn.microsoft.com/en-us/library/ms190329(SQL.90).aspx , que dice LEN "devuelve el número de caracteres de la expresión de cadena especificada, excluyendo espacios en blanco finales ". Sin embargo, es un detalle fácil de pasar por alto si no tiene cuidado.
En su lugar, debe utilizar la función DATALENGTH; consulte http://msdn.microsoft.com/en-us/library/ms173486(SQL.90).aspx , que "devuelve el número de bytes utilizados para representar cualquier expresión".
Ejemplo:
fuente
DATALENGTH
También deberá dividir el resultado entre 2 si la expresión que se está probando es un tipo de carácter ancho (Unicode; nchar, nvarchar o ntext), ya que el resultado está en bytes , no en caracteres .varchar
etc., esto puede depender de la clasificación y ni siquiera una división directa entre 2 es confiable. Vea el ejemplo aquíLEN(REPLACE(expr, ' ', '_'))
. Esto debería funcionar con cadenasvarchar
ynvarchar
y que contienen caracteres de control unicode especiales.DATALENGTH()
no debe considerarse una forma alternativa de contar caracteres porque cuenta bytes en lugar de caracteres y esto es importante cuando se representa la misma cadena enVARCHAR
/NVARCHAR
.Puedes usar este truco:
LEN (Str + 'x') - 1
fuente
Yo uso este método:
Prefiero esto sobre DATALENGTH porque funciona con diferentes tipos de datos, y lo prefiero a agregar un carácter al final porque no tiene que preocuparse por el caso de borde donde su cadena ya está en la longitud máxima.
Nota: probaría el rendimiento antes de usarlo en un conjunto de datos muy grande; aunque solo lo probé contra 2M filas y no fue más lento que LEN sin REPLACE ...
fuente
Usted consigue que alguien presente un informe de error / solicitud de mejora de SQL Server porque casi todas las soluciones enumeradas para este problema increíblemente simple aquí tienen alguna deficiencia o son ineficientes. Esto todavía parece ser cierto en SQL Server 2012. La función de recorte automático puede provenir de ANSI / ISO SQL-92 pero parece haber algunos agujeros (o falta de contarlos).
Vota "Agregar configuración para que LEN cuente los espacios en blanco finales" aquí:
https://feedback.azure.com/forums/908035-sql-server/suggestions/34673914-add-setting-so-len-counts-trailing-whitespace
Enlace de conexión retirado: https://connect.microsoft.com/SQLServer/feedback/details/801381
fuente
datalength
solución es aún peor a partir de SQL Server 2012, ya que ahora admite pares sustitutos en UTF-16, lo que significa que un carácter puede usar hasta 4 bytes. Realmente es hora de que arreglen lalen
función para cumplir con ANSI, o al menos proporcionen una función dedicada para contar caracteres, incluidos los espacios finales.Hay problemas con las dos respuestas más votadas. La respuesta recomendada
DATALENGTH
es propensa a errores del programador. El resultado deDATALENGTH
debe dividirse por 2 paraNVARCHAR
tipos, pero no paraVARCHAR
tipos. Esto requiere conocimiento del tipo que está obteniendo, y si ese tipo cambia, debe cambiar diligentemente los lugares que utilizóDATALENGTH
.También hay un problema con la respuesta más votada (que admito que era mi forma preferida de hacerlo hasta que este problema me mordió). Si lo que obtiene la longitud es de tipo
NVARCHAR(4000)
, y en realidad contiene una cadena de 4000 caracteres, SQL ignorará el carácter agregado en lugar de emitir implícitamente el resultadoNVARCHAR(MAX)
. El resultado final es una longitud incorrecta. Lo mismo ocurrirá con VARCHAR (8000).Lo que he encontrado funciona, es casi tan rápido como lo viejo
LEN
, es más rápido queLEN(@s + 'x') - 1
para cadenas grandes y no asume que el ancho del carácter subyacente es el siguiente:Esto obtiene la longitud de datos y luego se divide por la longitud de datos de un solo carácter de la cadena. El agregado de 'x' cubre el caso donde la cadena está vacía (lo que daría una división por cero en ese caso). Esto funciona si
@s
esVARCHAR
oNVARCHAR
. Hacer elLEFT
de 1 carácter antes de agregar se afeita en algún momento cuando la cadena es grande. Sin embargo, el problema con esto es que no funciona correctamente con cadenas que contienen pares suplentes.Hay otra forma mencionada en un comentario para la respuesta aceptada, usando
REPLACE(@s,' ','x')
. Esa técnica da la respuesta correcta, pero es un par de órdenes de magnitud más lenta que las otras técnicas cuando la cuerda es grande.Dados los problemas introducidos por los pares sustitutos en cualquier técnica que utilice
DATALENGTH
, creo que el método más seguro que da respuestas correctas que conozco es el siguiente:Esto es más rápido que la
REPLACE
técnica y mucho más rápido con cuerdas más largas. Básicamente, esta técnica es laLEN(@s + 'x') - 1
técnica, pero con protección para el caso de borde donde la cadena tiene una longitud de 4000 (para nvarchar) u 8000 (para varchar), de modo que la respuesta correcta se da incluso para eso. También debe manejar correctamente las cadenas con pares sustitutos.fuente
N'x𤭢x' COLLATE Latin1_General_100_CI_AS_SC
da 4, mientras queLEN
da 3.También debe asegurarse de que sus datos se guarden realmente con los espacios en blanco finales. Cuando ANSI PADDING está APAGADO (no predeterminado):
fuente
LEN corta los espacios finales de forma predeterminada, así que encontré que esto funcionó a medida que los mueve al frente
(LEN (REVERSE (TestField))
Entonces, si quisieras, podrías decir
No use esto para espacios principales, por supuesto.
fuente
declare @TestField varchar(10);
SET @TestField = ' abc '; -- Length with spaces is 5.
select LEN(REVERSE(@TestField)) -- Returns 4
select LEN(@TestField) -- Returns 4
Debe definir una función CLR que devuelva el campo Longitud de cadena, si no le gusta la concatenación de cadenas. Yo uso
LEN('x' + @string + 'x') - 2
en mis casos de uso de producción.fuente
Si no le gustan las
DATALENGTH
preocupaciones debido a n / varchar, ¿qué tal:que es solo
envuelto con protección de división por cero.
Al dividir por DATALENGTH de un solo carácter, obtenemos la longitud normalizada.
(Por supuesto, todavía hay problemas con los pares sustitutos si eso es una preocupación).
fuente
use SELECT DATALENGTH ('cadena')
fuente