2010-05-13 13 views
16

Me pregunto cuál es el literal de Null character (por ejemplo, '\ 0') en TSQL.¿Cuál es el literal de carácter nulo en TSQL?

Nota: no es un valor de campo NULO, pero el carácter nulo (see link).

Tengo una columna con una mezcla de caracteres típico y nulo. Estoy tratando de reemplazar el carácter nulo con un valor diferente. Yo hubiera pensado que el siguiente iba a funcionar, pero es unsuccessfull:

select REPLACE(field_with_nullchar, char(0), ',') from FOO where BAR = 20 
+0

¿Carácter nulo? Proporcione un ejemplo, porque el valor completo de la columna sería nulo: use COALESCE. –

+1

El OP se refiere al carácter nulo de estilo C (decimal 0) que se utiliza para terminar cadenas de estilo C. –

+3

Parece que de alguna manera tiene (n) columnas varchar con terminadores nulos incorporados, y quiere reemplazarlas para que el valor de la cadena no se corte allí cuando la recupera. – GalacticCowboy

Respuesta

15

Hay dos comportamientos diferentes en el Cade Roux's answer: la sustitución tiene éxito (cuando se utiliza intercalación de SQL) y sin éxito (se utiliza la intercalación de Windows). La razón es en el tipo de colación utilizada.

Este comportamiento fue submitted a Microsoft hace casi 4 años:

Q: Al tratar un reemplazar un carácter NUL con replace(), esto funciona es el valor tiene una intercalación de SQL, pero no es una intercalación de Windows .

A: Esto se debe al hecho de que 0x0000 es un carácter indefinido en Windows colaciones. Todos los caracteres indefinidos se ignoran durante la comparación, clasificación, y coincidencia de patrón. Tan abrasivo para 'a' + char (0) realmente está buscando 'a', y la búsqueda de char (0) es equivalente a una cadena vacía.

La manera de manejar carácter indefinido es un poco confuso, pero esta es la forma en que Windows definido para ordenarlos, y SQL Server se ajusta a la API de Windows en general.

En la intercalación de SQL, no existe la noción de caracteres no definidos. A cada código punto se le asigna un peso, por eso no vemos un problema allí.

pero, por desgracia, todavía no está documentado.

Por lo tanto, parece que la única solución es cambiar la intercalación a la intercalación de SQL (por ejemplo, también se puede usar SQL_Latin1_General_CP1_CI_AS).

* me quité la respuesta anterior como innecesaria

+5

Exactamente. Él ha incorporado terminadores de cadena (NULL en el sentido C, no SQL) y quiere arreglarlos. – GalacticCowboy

9

Parece que el terminador de estilo C es un terminador en SQL, así:

SELECT REPLACE(bad, CHAR(0), ' ') 
FROM (
     SELECT 'a' + CHAR(0) + 'b' AS bad 
     ) AS X 

parece que es también dependiente de Colación:

SELECT REPLACE(CAST(bad COLLATE SQL_Latin1_General_CP1_CI_AS AS varchar(10)), CHAR(0), ' ') 
FROM (
     SELECT 'a' + CHAR(0) + 'b' AS bad 
     ) AS X 

funciona según lo esperado, en comparación con:

SELECT REPLACE(CAST(bad COLLATE Latin1_General_CI_AS AS varchar(10)), CHAR(0), ' ') 
FROM (
     SELECT 'a' + CHAR(0) + 'b' AS bad 
     ) AS X 
0

¿Estás seguro de que son personajes nulos? ¿Cómo los conseguiste allí?

Parece que SQL Server los trata como terminadores de cadena. Esta consulta:

select 'aaa' + char(0) + 'bbb' 

devoluciones aaa para mí (en SQL Server 2008).

Edit: Above is wrong - es solo la cuadrícula de resultados que los trata de esa manera. Se muestran en modo de texto.

+3

¿Ha mirado los resultados en modo texto? Cuando lo ejecuto en modo cuadrícula, aparece como "aaa", pero en el modo de texto para el conjunto de resultados se muestra "aaa bbb" –

+0

@Tom - oh, tienes razón. Aclamaciones. – Blorgbeard

0

Acabo de ejecutar la prueba a continuación en mi servidor (2008) y fue un éxito. Puede tener que ver con una configuración ANSI. Intentaré cambiar algunas configuraciones aquí y ver si puedo reproducir tu problema.

DECLARE @test_null_char VARCHAR(20) 

SET @test_null_char = 'aaa' + CHAR(0) + 'bbb' 

SELECT @test_null_char -- Returns "aaa bbb" 

SET @test_null_char = REPLACE(@test_null_char, CHAR(0), 'ccc') 

SELECT @test_null_char -- Returns "aaacccbbb" 
0

Un VARBINARY elenco debería funcionar con cualquier cotejo

SELECT 
    REPLACE(CAST(CAST(fld AS VARCHAR(5)) AS VARBINARY(5)), 0x0, ',') 
FROM 
    (SELECT 'QQ' + CHAR(0) + 'WW' COLLATE Latin1_General_CI_AS AS fld) AS T 

SELECT 
    REPLACE(CAST(CAST(fld AS VARCHAR(5)) AS VARBINARY(5)), 0x0, ',') 
FROM 
    (SELECT 'QQ' + CHAR(0) + 'WW' COLLATE SQL_Latin1_General_CP1_CI_AS AS fld) AS T 

>>QQ,WW 
>>QQ,WW 
0

que estaba teniendo el mismo problema y lo resolvió mediante nullif para mí.

Select nullif(field_with_nullchar,'') from FOO where BAR = 20 
Cuestiones relacionadas