UNTUK XML tidak dapat mengelompokkan data karena mengandung karakter (0x0000)

18

Saya punya pertanyaan besar (jika perlu saya akan posting di sini) dan saya mendapatkan kesalahan ini:

Msg 6841, Level 16, Negara 1, Baris 1
UNTUK XML tidak dapat membuat serialisasi data untuk simpul 'NoName' karena mengandung karakter (0x0000) yang tidak diizinkan dalam XML. Untuk mengambil data ini menggunakan UNTUK XML, mengonversinya menjadi tipe data biner, varbinary atau gambar dan menggunakan direktif BINARY BASE64.

Satu-satunya bagian yang saya gunakan FOR XMLada di sini:

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

Tapi apa itu node noname? dan bagaimana saya bisa mencari nilai ini:(0x0000)

Ini adalah salah satu subqueries (satu-satunya bagian yang saya miliki UNTUK 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...
SQL pembalap
sumber

Jawaban:

10

Garis:

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

Seharusnya:

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

Saya mendapatkan kesalahan yang sama ketika saya melakukan ini:

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

Jadi, temukan semua contoh DescFuncaoatau DescTempoExperiencia(maaf, Anda tidak menggunakan tabel aliasing, jadi tidak mungkin untuk mengetahui dari mana tabel itu berasal) di mana isinya berisi CHAR(0), dan memperbaikinya. Sebagai contoh:

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

Tidak cukup untuk memfilter baris-baris itu dalam kueri Anda, karena Anda tidak tahu pada titik mana metode XML akan berfungsi, tetapi Anda juga dapat mencoba:

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

Tentu saja, memperbaiki data sumber sekali akan jauh lebih efisien daripada menjalankan rutinitas penggantian ini setiap waktu .

Catatan, ini mungkin bukan satu-satunya karakter spesifik yang menyebabkan masalah ini. 0x0001-> 0x0008juga akan menghasilkan kesalahan yang sama. Jadi jika Anda memiliki karakter-karakter itu di sana juga, Anda harus menyelidiki dari mana mereka berasal, dan memperbaiki sumbernya.

Aaron Bertrand
sumber
1
Bagaimana dengan data dengan banyak emoji?
devinbost
10

Saya menguji dengan karakter ASCII 0-255 dan menemukan bahwa Anda mendapatkan error ini untuk karakter: 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.

Salah satu solusinya adalah menghapus , TYPEdari pernyataan XML Anda.

Cara lain adalah menghapus karakter-karakter itu dalam pernyataan pilih:

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

Anda juga bisa membuat fungsi dengan pernyataan ganti ini.

jumxozizi
sumber
Gagasan penyelesaian ini membantu saya menemukan di mana dalam ekspresi tabel umum kompleks besar yang untuk blok xml gagal dengan kesalahan ini.
Keith John Hutchison
2
Skrip ini berguna (meskipun sangat lambat), tetapi tidak bekerja pada karakter emoji (seperti 0xD83D), dan saya menduga mungkin ada banyak .... paling tidak dalam data saya. : '(Atau haruskah saya katakan: 0x1F62D
devinbost
1

Mengoptimalkan jawaban dari @jumxozizi dengan menggunakan translate () (SQL Server 2017 ++). Kode di bawah ini akan menggantikan karakter tersebut dengan titik.

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

Untuk menghapusnya, orang dapat menerjemahkan () pertama-tama menjadi char (0) dan kemudian membungkusnya dengan replace ().

Dari ide: /programming//a/55906638/538763

crokusek
sumber