2011-01-24 6 views
7

Mam zapytanie złączenie:VARCHAR (MAX) dziwnie, gdy łącząc ciąg

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

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 

Moje zapytanie złączenie zwraca

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

My najlepiej domyślić się, że przy użyciu NVARCHAR(MAX) konieczne jest ponowne wpisanie @path za każdym razem, gdy jest ona ustawiana, a tym samym utrata zestawu zawartości przed przepisaniem lub jest wpisana przy pierwszym ustawieniu, a następnie łączenie się po cichu kończy się.

Chciałbym jednak zrozumieć pierwotną przyczynę tego zachowania.

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

Jaki jest typ 'url_segment'? –

+0

Mam podobne wyniki z tym podejściem do konkatenacji wcześniej. (gdzie kończy się tylko wartością z jednego wiersza, a nie ze wszystkich) Nigdy nie zauważyłem, że 'datatype' odegrał pewną rolę. Czasami trzeba trochę zmodyfikować zapytanie, aby uzyskać wymagany plan wykonania. Czy możesz zamieścić oba plany? (Można oczywiście użyć tylko PATH XML, jak w SQL Server 2005, który jest udokumentowany do działania) Zobacz również http://support.microsoft.com/kb/287515/en-us –

+0

@El Ronnoco zaktualizowane pytanie z więcej Detale. –

Odpowiedz

4

Takie podejście do łańcuchów znaków robi zazwyczaj pracują, ale nie jest gwarantowana.

Oficjalny wiersz w the KB article for a similar issue mówi, że "Prawidłowe zachowanie dla zagregowanego zapytania o konkatenację jest niezdefiniowane."

Musi istnieć subtelna różnica między planami. Możesz zmodyfikować zapytanie, aby usunąć różnicę i uzyskać wymagany plan wykonania, lub możesz/powinien po prostu użyć XML PATH, tak jak w SQL Server 2005, co zostało udokumentowane.

+0

@Martin - Nie widziałem, żeby to się nie udawało. Odnośnik odnosi się do używania funkcji w zapytaniach zbiorczych, co ma sens. Ale czy ma to tutaj zastosowanie? – RichardTheKiwi

+0

@cyberkiwi - Czy spojrzałeś na kod w linku? Nie używa żadnych agregatów. 'SELECT @ Str1 = @ Str1 + C1 Z T1 ZAMÓWIENIE PRZEZ LTRIM (RTRIM (C1))' –

+0

@Martin - FYI to "agregacja" tekstu do jednej zmiennej. Zamówienie obejmuje funkcje LTRIM, RTRIM – RichardTheKiwi

Powiązane problemy