Hay algunas cosas a tener en cuenta aquí:
-
Si desea ver exactamente qué carácter está allí, puede convertir el valor a
VARBINARY
lo que le dará el valor hexadecimal/binario de todos los caracteres de la cadena y no existe el concepto de caracteres "ocultos" en hexadecimal:DECLARE @PostalCode NVARCHAR(20); SET @PostalCode = N'053000'+ NCHAR(0x2008); -- 0x2008 = "Punctuation Space" SELECT @PostalCode AS [NVarCharValue], CONVERT(VARCHAR(20), @PostalCode) AS [VarCharValue], CONVERT(VARCHAR(20), RTRIM(@PostalCode)) AS [RTrimmedVarCharValue], CONVERT(VARBINARY(20), @PostalCode) AS [VarBinaryValue];
Devoluciones:
NVarCharValue VarCharValue RTrimmedVarCharValue VarBinaryValue 053000 053000? 053000? 0x3000350033003000300030000820
NVARCHAR
los datos se almacenan como UTF-16, que funciona en conjuntos de 2 bytes. Mirando los últimos 4 dígitos hexadecimales para ver cuál es el conjunto oculto de 2 bytes, vemos "0820". Dado que Windows y SQL Server son UTF-16 Little Endian (es decir, UTF-16LE), los bytes están en orden inverso. Volteando los últimos 2 bytes --08
y20
-- obtenemos "2008", que es el "Espacio de puntuación" que agregamos a través deNCHAR(0x2008)
.Además, tenga en cuenta que
RTRIM
no ayudó en absoluto aquí. -
De manera simplista, puede simplemente reemplazar los signos de interrogación con nada:
SELECT REPLACE(CONVERT(VARCHAR(20), [PostalCode]), '?', '');
-
Más importante aún, debe convertir el
[PostalCode]
campo aVARCHAR
para que no almacene estos caracteres. Ningún país usa letras que no estén representadas en el conjunto de caracteres ASCII y que no sean válidas para el tipo de datos VARCHAR, al menos por lo que he leído (consulte la sección inferior para obtener referencias). De hecho, lo que está permitido es un subconjunto bastante pequeño de ASCII, lo que significa que puede filtrar fácilmente al entrar (o simplemente hacer lo mismoREPLACE
como se muestra arriba al insertar o actualizar):ALTER TABLE [table] ALTER COLUMN [PostalCode] VARCHAR(20) [NOT]? NULL;
Asegúrese de verificar el
NULL
actual /NOT NULL
ajuste para la columna y hágalo igual en la instrucción ALTER anterior; de lo contrario, podría cambiarse ya que el valor predeterminado esNULL
si no se especifica. -
Si no puede cambiar el esquema de la tabla y necesita hacer una "limpieza" periódica de los datos incorrectos, puede ejecutar lo siguiente:
;WITH cte AS ( SELECT * FROM TableName WHERE [PostalCode] <> CONVERT(NVARCHAR(50), CONVERT(VARCHAR(50), [PostalCode])) ) UPDATE cte SET cte.[PostalCode] = REPLACE(CONVERT(VARCHAR(50), [PostalCode]), '?', '');
Tenga en cuenta que la consulta anterior no está diseñada para funcionar de manera eficiente si la tabla tiene millones de filas. En ese momento, tendría que manejarse en conjuntos más pequeños a través de un bucle.
Como referencia, aquí está el artículo de wikipedia para Código postal , que actualmente establece que los únicos caracteres que se usan son:
Y con respecto al tamaño máximo del campo, aquí está la Wikipedia Lista de códigos postales