Tengo una tabla con un par de miles de filas. Los campos de descripción y resumen son NTEXT y, a veces, tienen caracteres no ASCII en ellos. ¿Cómo puedo ubicar todas las filas con caracteres que no sean ASCII?¿Cómo puedo encontrar caracteres Unicode/no ASCII en un campo NTEXT en una tabla de SQL Server 2005?
¿Cómo puedo encontrar caracteres Unicode/no ASCII en un campo NTEXT en una tabla de SQL Server 2005?
Respuesta
Primero construya una cadena con todos los caracteres que no le interesen (el ejemplo usa el rango 0x20 - 0x7F, o 7 bits sin los caracteres de control.) Cada carácter tiene el prefijo |, para usar en la cláusula de escape luego.
-- Start with tab, line feed, carriage return
declare @str varchar(1024)
set @str = '|' + char(9) + '|' + char(10) + '|' + char(13)
-- Add all normal ASCII characters (32 -> 127)
declare @i int
set @i = 32
while @i <= 127
begin
-- Uses | to escape, could be any character
set @str = @str + '|' + char(@i)
set @i = @i + 1
end
El siguiente fragmento busca cualquier carácter que no esté en la lista. El% coincide con 0 o más caracteres. [] Coincide con uno de los caracteres dentro de [], por ejemplo, [abc] podría coincidir con a, bo c. El^niega la lista, por ejemplo [^ abc] coincidiría con cualquier cosa que no sea a, b, o c.
select *
from yourtable
where yourfield like '%[^' + @str + ']%' escape '|'
Se requiere que el carácter de escape porque de lo contrario la búsqueda de personajes como],% o _ ensuciaría la expresión similares.
Espero que esto sea útil, y gracias al comentario de JohnFX en la otra respuesta.
Probablemente no sea la mejor solución, pero tal vez una consulta como:
SELECT *
FROM yourTable
WHERE yourTable.yourColumn LIKE '%[^0-9a-zA-Z]%'
sustituir la expresión "0-9a-zA-Z" con algo que captura el conjunto ASCII completo (o un subconjunto de que su datos contiene).
¿No coincidiría esto solo con las filas que contienen un carácter ASCII, a diferencia de solo los caracteres ASCII? – Andomar
El^marcador en el frente de la expresión significa NO, entonces no. Obtendría cualquier fila que tuviera al menos un carácter que no estuviera en los rangos especificados. – JohnFx
¿Cómo puedo poner el conjunto ascii completo en esa expresión? son los datos HTML los que estoy viendo así que "/><'etc ... está ahí. – TheSoftwareJedi
Mi respuesta anterior confundía datos UNICODE/no UNICODE. Aquí hay una solución que debería funcionar para todas las situaciones, aunque todavía me encuentro con algunas anomalías. Parece que ciertos caracteres Unicode que no son ASCII para caracteres superíndices se confunden con el carácter numérico real. Es posible que pueda jugar con colaciones para evitar eso.
Espero que ya tengas una tabla de números en tu base de datos (pueden ser muy útiles), pero solo en caso de que haya incluido el código para llenarlo parcialmente también.
También podría ser necesario para jugar un poco con el rango numérico, ya que los caracteres Unicode pueden ir más allá de 255.
CREATE TABLE dbo.Numbers
(
number INT NOT NULL,
CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (number)
)
GO
DECLARE @i INT
SET @i = 0
WHILE @i < 1000
BEGIN
INSERT INTO dbo.Numbers (number) VALUES (@i)
SET @i = @i + 1
END
GO
SELECT *,
T.ID, N.number, N'%' + NCHAR(N.number) + N'%'
FROM
dbo.Numbers N
INNER JOIN dbo.My_Table T ON
T.description LIKE N'%' + NCHAR(N.number) + N'%' OR
T.summary LIKE N'%' + NCHAR(N.number) + N'%'
and t.id = 1
WHERE
N.number BETWEEN 127 AND 255
ORDER BY
T.id, N.number
GO
De la manera que lo entiendo, ASCII es de 7 bits y varchar de 8 bits. Entonces, varchar aún puede almacenar una gran cantidad de caracteres que no son ascii, como ä o é. – Andomar
Estoy viendo los mismos resultados. Esto no funciona – TheSoftwareJedi
ASCII extendido es de 8 bits, que es a lo que algunas personas se refieren cuando dicen "ASCII". También editaré la publicación para limitarla a ASCII normal. –
- Esta es una forma muy, muy ineficiente de hacerlo, pero debe estar bien para - Mesas pequeñas Utiliza una tabla auxiliar de números según Itzik Ben-Gan y simplemente - busca caracteres con el bit 7 establecido.
SELECT *
FROM yourTable as t
WHERE EXISTS (SELECT *
FROM msdb..Nums as NaturalNumbers
WHERE NaturalNumbers.n < LEN(t.string_column)
AND ASCII(SUBSTRING(t.string_column, NaturalNumbers.n, 1)) > 127)
Técnicamente, creo que un NCHAR (1) es un carácter ASCII válidos si & sólo si UNICODE (@NChar) < 256 y ASCII (@NChar) = UNICODE (@NChar) aunque eso no puede ser exactamente lo que pretendías Por lo tanto, esta sería una solución correcta:
;With cteNumbers as
(
Select ROW_NUMBER() Over(Order By c1.object_id) as N
From sys.system_columns c1, sys.system_columns c2
)
Select Distinct RowID
From YourTable t
Join cteNumbers n ON n <= Len(CAST(TXT As NVarchar(MAX)))
Where UNICODE(Substring(TXT, n.N, 1)) > 255
OR UNICODE(Substring(TXT, n.N, 1)) <> ASCII(Substring(TXT, n.N, 1))
Esto también debería ser muy rápido.
ASCII solo tiene 127. También sus números cte son raros: la solución final debe usar una tabla de números preexistente en lugar de la misma. De lo contrario, así es como lo haría. –
FYI: "No parecer raro" no es un criterio que realmente me importe a mí (oa la mayoría de los súper geeks de este sitio). Y la ventaja de no usar una tabla de números preexistente, es que funciona incluso si dicha tabla no existe previamente (lo que generalmente no sucede). Finalmente, si prueba mi solución, encontrará que es comparable y, a veces, incluso mejor que una tabla de números preexistente. – RBarryYoung
Realmente no quiero discutir: estoy de acuerdo con su solución. Pero "raro" es generalmente difícil de leer y no se puede mantener. Así es como lo dije en serio. Tampoco es DRY si alguna vez tienes dos consultas diferentes que necesitan números: tienes que escribir el cte no mantenible dos veces. Leer números de fila de una combinación de system_columns en sí mismo no es muy sencillo, pero leer números de una tabla de números sería muy sencillo de depurar. –
a veces he estado usando esta declaración "fundido" para encontrar caracteres "extraños"
select
*
from
<Table>
where
<Field> != cast(<Field> as varchar(1000))
Empecé con una solución de @ CC1960, pero encontró un caso de uso interesante que causó el error.Parece que SQL Server igualará ciertos caracteres Unicode a sus aproximaciones que no sean Unicode. Por ejemplo, SQL Server considera el carácter Unicode "coma de ancho completo" (http://www.fileformat.info/info/unicode/char/ff0c/index.htm) lo mismo que una coma ASCII estándar cuando se compara en una cláusula WHERE.
Para evitar esto, haga que SQL Server compare las cadenas como binarias. Pero recuerde, nvarchar y varchar binarios no coinciden (16 bits vs 8 bits), por lo que necesita para convertir su copia de seguridad varchar a nvarchar de nuevo antes de hacer la comparación binaria:
select *
from my_table
where CONVERT(binary(5000),my_table.my_column) != CONVERT(binary(5000),CONVERT(nvarchar(1000),CONVERT(varchar(1000),my_table.my_column)))
Si está buscando un caracter Unicode específico, puede usar algo como a continuación.
select Fieldname from
(
select Fieldname,
REPLACE(Fieldname COLLATE Latin1_General_BIN,
NCHAR(65533) COLLATE Latin1_General_BIN,
'CustomText123') replacedcol
from table
) results where results.replacedcol like '%CustomText123%'
Aquí ya go:
SELECT *
FROM Objects
WHERE
ObjectKey LIKE '%[^0-9a-zA-Z !"#$%&''()*+,\-./:;<=>[email protected]\[\^_`{|}~\]\\]%' ESCAPE '\'
- 1. Concatene ntext en SQL Server 2005
- 2. Cómo crear un tipo de tabla en SQL Server 2005
- 3. Servidor SQL: cómo encontrar el carácter hexadecimal en una tabla
- 4. ¿Cómo puedo configurar un campo calculado simple en SQL Server?
- 5. ¿Hay alguna manera de DISTINCT o agrupar por un texto (o ntext) en SQL Server 2005?
- 6. ¿Cómo encontrar la suma de múltiples columnas en una tabla en SQL Server 2005?
- 7. dividir una cadena en caracteres individuales en SQL Server 2005
- 8. ¿Cómo edito un campo de texto (o ntext) en SQL Server 2000 o 2005 usando la GUI?
- 9. ¿Cómo puedo transformar filas en columnas en SQL server 2005
- 10. Cómo puedo documentar tablas y campos en SQL Server 2005
- 11. ¿Cómo puedo crear un desencadenador deshabilitado en SQL Server 2005?
- 12. ¿Cómo puedo encontrar caracteres que no sean ASCII en MySQL?
- 13. Isoweek en SQL Server 2005
- 14. Indexar varchar en MS SQL Server 2005
- 15. cómo encontrar quién bloquea quién en SQL Server 2005
- 16. Encontrar y reemplazar el SQL Server en el campo TEXTO
- 17. Insertar imagen en el campo de imagen de SQL Server 2005 utilizando solo SQL
- 18. Cómo anexar a un campo de texto en t-sql SQL Server 2005
- 19. Tamaño del campo VARBINARIO en SQL Server 2005
- 20. SQL Server 2005 replicación
- 21. Crear una tabla temporal como una tabla actual en SQL Server 2005/2008
- 22. Cómo crear una restricción única compuesta en SQL Server 2005
- 23. Cuándo utilizar la tabla temporal en SQL Server 2005
- 24. Buscar una tabla en múltiples bases de datos SQL SERVER 2005
- 25. ¿Cómo contar cada registro en cada tabla en una base de datos de SQL Server 2005?
- 26. SQL Server 2005 ROW_NUMBER() sin ORDER BY
- 27. Cómo agrego/fusiono XML adicional en un campo XML existente en SQL Server 2005
- 28. ¿Cómo puedo encontrar un índice deshabilitado en SQL Server 2008?
- 29. ¿Dinámicamente nombrar índices en SQL Server 2005?
- 30. Consultas jerárquicas en SQL Server 2005
Es posible que desee agregar algunos (o todos) de los personajes por debajo de 32 y, sobre todo importante sería el retorno de carro (13), la línea de alimentación (10) y Tab (9). –
Buen punto agregado – Andomar
Encontré que su técnica es la forma más confiable de hacerlo en SQL-Server. – cusman