2011-01-24 1 views
7

Ho una domanda concatenamento:VARCHAR (MAX) comporta in modo strano quando concatenazione stringa

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) rendimenti

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 

La mia domanda concatenamento restituisce

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

miola migliore ipotesi è che l'utilizzo di NVARCHAR(MAX) causi la riscrittura di @path ogni volta che viene impostata, perdendo così il contenuto impostato prima di ridigitare o che sia stata digitata la prima volta che viene impostata e quindi le successive concatenazioni delle chiamate falliscono.

Mi piacerebbe davvero capire la causa principale di questo comportamento.

UPDATE

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

Qual è il tipo di 'url_segment'? –

+0

Ho avuto risultati simili con questo approccio alla concatenazione precedente. (dove finisce solo con il valore di una riga anziché di tutti) Non ho mai notato che 'datatype' ha avuto un ruolo. A volte è necessario modificare leggermente la query per ottenere il piano di esecuzione richiesto. Puoi pubblicare entrambi i piani? (Oppure potresti semplicemente usare XML PATH come sei su SQL Server 2005 che è documentato per funzionare) Vedi anche http://support.microsoft.com/kb/287515/en-us –

+0

@El Ronnoco ha aggiornato la domanda con altro dettagli. –

risposta

4

Questo approccio alla concatenazione di stringhe fa di solito lavorare, ma non è garantito.

La riga ufficiale in the KB article for a similar issue è che "il comportamento corretto per una query di concatenazione aggregata non è definito".

Ci deve essere una sottile differenza tra i piani. È possibile modificare la query per rimuovere la differenza e ottenere il piano di esecuzione richiesto oppure è possibile/dovrebbe naturalmente utilizzare solo XML PATH come in SQL Server 2005 e questo è documentato per funzionare.

+0

@ Martin - Non l'ho visto fallire. Il collegamento si riferisce all'utilizzo di funzioni in query aggregate, il che ha senso. Ma si applica qui? – RichardTheKiwi

+0

@cyberkiwi - Hai visto il codice nel link? Non usa alcun aggregato. 'SELECT @ Str1 = @ Str1 + C1 FROM T1 ORDINA DA LTRIM (RTRIM (C1))' –

+0

@Martin - FYI è 'aggregare' il testo in una variabile. L'ordine coinvolge le funzioni LTRIM, RTRIM – RichardTheKiwi