web-dev-qa-db-fra.com

FOR XML n'a pas pu sérialiser les données car elles contiennent du caractère (0x0000)

J'ai une grosse requête (si nécessaire je la posterai ici) et j'obtiens cette erreur:

Msg 6841, niveau 16, état 1, ligne 1
FOR XML n'a pas pu sérialiser les données pour le noeud 'NoName' car il contient un caractère (0x0000) qui n'est pas autorisé en XML. Pour récupérer ces données à l'aide de FOR XML, convertissez-les en type de données binaire, varbinaire ou image et utilisez la directive BINARY BASE64.

La seule partie que j'utilise FOR XML est là:

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

Mais comment ça node noname? et comment puis-je rechercher cette valeur: (0x0000)

C'est l'une des sous-requêtes (la seule partie que j'ai pour XML):

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...
20
Racer SQL

La ligne:

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

Devrait être:

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

J'obtiens la même erreur lorsque je fais cela:

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

Donc, trouvez toutes les instances de DescFuncao ou DescTempoExperiencia (désolé, vous n'utilisez pas l'alias de table, il est donc impossible de dire de quelle table elles proviennent) d'où le contenu contient CHAR(0), et corrigez-les. Par exemple:

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

Il ne suffit pas de filtrer ces lignes dans votre requête, car vous ne savez pas à quel moment les méthodes XML fonctionneront, mais vous pouvez également essayer:

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

Bien sûr, la fixation des données source ne fois sera beaucoup plus efficace que l'exécution de ces routines de remplacement à chaque fois.

Notez que ce n'est peut-être pas le seul caractère spécifique à l'origine de ce problème. 0x0001 -> 0x0008 Générera également la même erreur. Donc, si vous avez aussi ces personnages là-dedans, vous devriez rechercher d'où ils viennent et corriger la source.

12
Aaron Bertrand

J'ai testé cela avec ASCII caractères 0-255 et j'ai découvert que vous obtenez cette erreur pour les caractères: 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.

Une solution consiste à supprimer , TYPE à partir de votre instruction XML.

Une autre façon consiste à supprimer ces caractères dans l'instruction select:

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),'')

Vous pouvez également créer une fonction avec ces instructions replace.

11
jumxozizi

Optimisation de la réponse de @jumxozizi à l'aide de translate () (SQL Server 2017 ++). Le code ci-dessous remplacera ces caractères par des points.

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

Pour les supprimer à la place, on pourrait d'abord les traduire () en char (0) puis les envelopper avec replace ().

De l'idée: https://stackoverflow.com/a/55906638/53876

2
crokusek