FOR XML, karakter (0x0000) içerdiğinden verileri serileştiremedi


18

Büyük bir sorgu var (gerekirse ben burada yayınlayacağım) ve bu hatayı alıyorum:

Msg 6841, Seviye 16, Durum 1, Satır 1
FOR XML, XML'de izin verilmeyen bir karakter (0x0000) içerdiğinden 'NoName' düğümü için verileri serileştiremedi. FOR XML kullanarak bu verileri almak için, ikili, varbinary veya görüntü veri türüne dönüştürün ve BINARY BASE64 yönergesini kullanın.

Kullandığım tek parça FOR XMLburada:

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

Peki, nedir node noname? ve bu değeri nasıl arayabilirim:(0x0000)

Bu alt sorgulardan biridir (FOR XML için tek bölüm):

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...

Yanıtlar:


10

Çizgi:

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

Olmalı:

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

11

Bunu yaptığımda aynı hatayı alıyorum:

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

Bu nedenle, içeriğin nerede olduğunu DescFuncaoveya DescTempoExperiencia(üzgünüm, tablo diğer adını kullanmıyorsanız, hangi tablodan geldiklerini söylemek imkansızdır) bulun CHAR(0)ve bunları düzeltin. Örneğin:

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

Sorguda bu satırları filtrelemek yeterli değildir, çünkü XML yöntemlerinin hangi noktada işe yarayacağını bilmiyorsunuz, ancak şunları da deneyebilirsiniz:

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

Tabii ki, kaynak verileri bir kez düzeltmek, bu değiştirme rutinlerini her seferinde çalıştırmaktan çok daha verimli olacaktır .

Bu soruna neden olan tek karakter bu olmayabilir. 0x0001-> 0x0008da aynı hatayı oluşturur. Yani orada da bu karakterlere sahipseniz, nereden geldiklerini araştırmalı ve kaynağı düzeltmelisiniz.


1
Çok fazla emojisi olan veriler için ne dersiniz?
devinbost

10

Ben ASCII karakterleri 0-255 ile bu test ve karakterler için bu hatayı almaya öğrendim: 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.

Geçici çözümlerden biri , TYPEXML ifadenizden kaldırmaktır .

Başka bir yol da select deyimindeki bu karakterleri kaldırmaktır:

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

Bu replace ifadeleriyle de bir işlev oluşturabilirsiniz.


Bu geçici çözüm, xml bloğu için bu hatayla başarısız olan büyük karmaşık ortak tablo ifadesinde nerede olduğunu bulmama yardımcı oldu.
Keith John Hutchison

2
Bu komut dosyası (acı verici şekilde yavaş olsa da) yararlıdır, ancak emoji karakterleri (0xD83D gibi) üzerinde çalışmaz ve en azından verilerimde .... olabileceğinden şüpheleniyorum. : '(Veya şunu söylemeliyim: 0x1F62D
devinbost

1

Translate () (SQL Server 2017 ++) kullanarak @jumxozizi'den yanıt en iyileştirme. Aşağıdaki kod bu karakterleri noktalarla değiştirecektir.

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

Bunları soymak için önce onları char (0) olarak çevirebilir () ve sonra bir replace () ile sarabilirsiniz.

Fikirden: /programming//a/55906638/538763

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.