2011-01-24 13 views
7

Tengo una consulta concatenación:VARCHAR (MAX) actuando raro al concatenar cadena

DECLARE @path NVARCHAR(max) 
SELECT @path = ISNULL(@path + '/', '') + url_segment 
    FROM navigation_self_and_parents(2813) ORDER BY depth ASC 
SELECT @path 

navigation_self_and_parents(2813) vuelve

id par_id title  url_segment sequence  depth 
2813 2816 testing1234 testing1234 0    0 
2816 2809 U   /fixedurl  0    -1 
2809 NULL E   E    0    -2 

Mi consulta concatenación devuelve

'testing1234'    when using `NVARCHAR(MAX)` and 
'E//fixedurl/testing1234' when using `NVARCHAR(4000)`

Mi La mejor suposición es que el uso de NVARCHAR(MAX) hace que se vuelva a escribir @path cada vez que se configura y, por lo tanto, perder los contenidos configurados antes de volver a escribir o que se tipea la primera vez que se configura y las llamadas concatenadas subsiguientes fallan silenciosamente.

Sin embargo, me encantaría comprender realmente la causa raíz de este comportamiento.

ACTUALIZACIÓN

navigation_self_and_parents:

USE [SomeDatabase] 
GO 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
ALTER FUNCTION [dbo].[navigation_self_and_parents] 
( 
    @id int 
) 
RETURNS TABLE 
AS 
RETURN 
(
    WITH navigation_self_and_parents (id, parent_id, title, url_segment, sequence_number, depth) 
    AS 
    (
     SELECT id, parent_id, title, url_segment, sequence_number, 0 FROM navigation_node WHERE [email protected] 
     UNION ALL 

     SELECT n.id, n.parent_id, n.title, n.url_segment, n.sequence_number, depth - 1 From navigation_node as n 
     INNER JOIN navigation_self_and_parents as rn 
     ON n.id = rn.parent_id 
    ) 
    SELECT * FROM navigation_self_and_parents 
) 

navigation_node DDL:

CREATE TABLE [dbo].[navigation_node](
    [id] [int] IDENTITY(1,1) NOT NULL, 
    [title] [nvarchar](128) NULL, 
    [url_segment] [nvarchar](max) NULL, 
    [hidden] [bit] NOT NULL, 
    [page_id] [int] NULL, 
    [parent_id] [int] NULL, 
    [sequence_number] [int] NOT NULL, 
    [createdOn] [datetime] NOT NULL, 
    [updatedOn] [datetime] NULL, 
    [navigation_type_id] [int] NULL, 
    ...snap 
+0

¿Cuál es el tipo de 'url_segment'? –

+0

He tenido resultados similares con este enfoque para concatenar antes. (donde termina solo con el valor de una fila en lugar de todo) Nunca me he dado cuenta de que 'datatype' ha jugado un papel. Algunas veces necesita ajustar un poco la consulta para obtener el plan de ejecución requerido. ¿Puedes publicar ambos planes? (O, por supuesto, simplemente podría utilizar XML PATH tal como está en SQL Server 2005, que está documentado para funcionar) Vea también http://support.microsoft.com/kb/287515/en-us –

+0

@El Ronnoco pregunta actualizada con más detalles. –

Respuesta

4

Este enfoque de la concatenación de cadenas suele funcionar, pero no está garantizada.

La línea oficial en the KB article for a similar issue es que "el comportamiento correcto para una consulta de concatenación agregada no está definido".

Debe haber alguna diferencia sutil entre los planes. Puede modificar la consulta para eliminar la diferencia y obtener el plan de ejecución requerido o puede/debería, por supuesto, simplemente usar XML PATH como lo está en SQL Server 2005 y está documentado que funciona.

+0

@Martin - No lo he visto. El enlace se refiere al uso de funciones en consultas globales, lo que tiene sentido. ¿Pero eso aplica aquí? – RichardTheKiwi

+0

@cyberkiwi - ¿Miraste el código en el enlace? No usa ningún agregado. 'SELECT @ Str1 = @ Str1 + C1 FROM T1 ORDER BY LTRIM (RTRIM (C1))' –

+0

@Martin - FYI está 'agregando' el texto en una variable. El orden implica las funciones LTRIM, RTRIM – RichardTheKiwi

Cuestiones relacionadas