FOR XML konnte die Daten nicht serialisieren, da sie Zeichen enthalten (0x0000)

18

Ich habe eine große Frage (wenn nötig, werde ich sie hier posten) und bekomme diese Fehlermeldung:

Meldung 6841, Ebene 16, Status 1, Zeile 1
FOR XML konnte die Daten für den Knoten 'NoName' nicht serialisieren, da er ein Zeichen (0x0000) enthält, das in XML nicht zulässig ist. Um diese Daten mit FOR XML abzurufen, konvertieren Sie sie in einen Binär-, Varbinär- oder Image-Datentyp und verwenden Sie die BINARY BASE64-Direktive.

Der einzige Teil, den ich benutze, FOR XMList hier:

WHERE 
    (CodFuncionario = Results.CodFuncionario) 
FOR XML PATH(''), TYPE).value('(./text())[1]', 
    'VARCHAR(MAX)'), 1, 2, '') AS [Experiencia]

Aber was ist node noname? und wie kann ich diesen Wert suchen:(0x0000)

Dies ist eine der Unterabfragen (der einzige Teil, den ich für XML habe):

SELECT 
    [CodFuncionario],
    STUFF
    (
        (
            SELECT 
                ' / ' + 
            CAST
            (
                [DescFuncao] + '-' + 
                [DescTempoExperiencia] 
                AS VARCHAR(MAX)
            )...
FROM 
    [Linked_Server].db.dbo.tblFuncionarioExperiencia T0
INNER JOIN
    [Linked_Server].db.dbo.tblFuncao T1 On T0.codFuncao = T1.CodFuncao
INNER JOIN
    [Linked_Server].db.dbo.tblTempoExperiencia T2 ON T0.CodTempoExperiencia = T2.CodTempoExperiencia 
WHERE 
   (CodFuncionario = Results.CodFuncionario) 
   FOR XML PATH(''), TYPE).value('(./text())[1]', 'VARCHAR(MAX)'), 1, 2, '') AS [Experiencia]
  FROM 
      [Linked_Server].db.dbo.tblFuncionarioExperiencia Results  
  GROUP BY 
      CodFuncionario) as T2

  On T0.CodFuncionario = T2.CodFuncionario

Left Join...
Racer SQL
quelle

Antworten:

10

Die Linie:

...
SELECT 
    [CodFuncionario],
    STUFF
    (
        (
            SELECT 
                ' / ' + 
                CAST
                (
                    [DescFuncao] + '-' + 
                    [DescTempoExperiencia] 
                    AS VARCHAR(MAX)
                )...

Sollte sein:

...
SELECT 
    [CodFuncionario],
    STUFF
    (
        (
            SELECT 
                ' / ' + 
                CAST
                (
                    replace -- *** NEW! ***
                    (
                        [DescFuncao] + '-' + 
                        [DescTempoExperiencia],
                        char(0),
                        ''
                    ) 
                    AS VARCHAR(MAX)
                )...
Rob Farley
quelle
11

Ich erhalte den gleichen Fehler, wenn ich das mache:

DECLARE @foo VARCHAR(32) = CHAR(0); -- 0x0000
SELECT @foo FOR XML PATH, TYPE;

Finden Sie also alle Instanzen von DescFuncaooder DescTempoExperiencia(Sie verwenden leider kein Tabellen-Aliasing, daher können Sie nicht sagen, von welcher Tabelle sie stammen), wo der Inhalt enthalten istCHAR(0) , und korrigieren Sie sie. Beispielsweise:

UPDATE dbo.whatever 
  SET DescFuncao = REPLACE(DescFuncao, CHAR(0), '')
  WHERE DescFuncao LIKE '%' + CHAR(0) + '%';

Es reicht nicht aus, diese Zeilen in Ihrer Abfrage herauszufiltern, da Sie nicht wissen, wann die XML-Methoden funktionieren, aber Sie können auch Folgendes versuchen:

STUFF(( SELECT ' / ' + CAST(REPLACE([DescFuncao] + '-' 
  + [DescTempoExperiencia], CHAR(0), '') AS VARCHAR(MAX))

Das einmalige Reparieren der Quelldaten ist natürlich wesentlich effizienter als das Ausführen dieser Ersetzungsroutinen jedes Mal, wenn werden .

Beachten Sie, dass dies möglicherweise nicht das einzige bestimmte Zeichen ist, das dieses Problem verursacht. 0x0001-> 0x0008wird auch den gleichen Fehler erzeugen. Also, wenn Sie diese Charaktere auch dort haben, sollten Sie untersuchen, woher sie kommen, und die Quelle reparieren.

Aaron Bertrand
quelle
1
Was ist mit Daten mit vielen Emojis?
Devinbost
10

Ich habe dies mit ASCII-Zeichen 0-255 getestet und festgestellt, dass Sie diesen Fehler für Zeichen erhalten: 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x000B, 0x000C, 0x000E, 0x000F, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F .

Eine Problemumgehung ist das Entfernen , TYPE aus Ihrer XML-Anweisung .

Eine andere Möglichkeit besteht darin, diese Zeichen in der select-Anweisung zu entfernen:

REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( 
REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( 
REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( 
REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( 
REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( 
REPLACE( REPLACE( REPLACE( REPLACE( 
    < YOUR EXPRESSION TO BE CLEANED >
,char(0x0000),'') ,char(0x0001),'') ,char(0x0002),'') ,char(0x0003),'') ,char(0x0004),'') 
,char(0x0005),'') ,char(0x0006),'') ,char(0x0007),'') ,char(0x0008),'') ,char(0x000B),'') 
,char(0x000C),'') ,char(0x000E),'') ,char(0x000F),'') ,char(0x0010),'') ,char(0x0011),'') 
,char(0x0012),'') ,char(0x0013),'') ,char(0x0014),'') ,char(0x0015),'') ,char(0x0016),'') 
,char(0x0017),'') ,char(0x0018),'') ,char(0x0019),'') ,char(0x001A),'') ,char(0x001B),'') 
,char(0x001C),'') ,char(0x001D),'') ,char(0x001E),'') ,char(0x001F),'')

Mit diesen Anweisungen zum Ersetzen können Sie auch eine Funktion erstellen.

jumxozizi
quelle
Diese Problemumgehungsidee hat mir dabei geholfen, herauszufinden, wo in einem großen komplexen allgemeinen Tabellenausdruck, der für den XML-Block fehlgeschlagen ist, dieser Fehler aufgetreten ist.
Keith John Hutchison
2
Dieses Skript ist nützlich (wenn auch schmerzhaft langsam), funktioniert aber nicht bei Emoji-Zeichen (wie 0xD83D), und ich vermute, dass es möglicherweise viele davon gibt ... zumindest in meinen Daten. : '(Oder sollte ich sagen: 0x1F62D
devinbost
1

Optimieren der Antwort von @jumxozizi mithilfe von translate () (SQL Server 2017 ++). Der folgende Code ersetzt diese Zeichen durch Punkte.

declare
    @illegalChars nvarchar(4000) = 
        char(0) + char(1) + char(2) + char(3) + char(4) + char(5) + char(6) + char(7) + char(8) + char(11) + 
        char(12) + char(14) + char(15) + char(16) + char(17) + char(18) + char(19) + char(20) + char(21) + char(22) + 
        char(23) + char(24) + char(25) + char(26) + char(27) + char(28) + char(29) + char(30) + char(31);

select translate(input, @illegalChars, replicate('.', len(@illegalChars))) as Result

Um sie stattdessen zu entfernen, könnte man sie zuerst in char (0) übersetzen und diese dann mit einem replace () umschließen.

Aus der Idee: /programming//a/55906638/538763

crokusek
quelle