สำหรับ XML ไม่สามารถทำให้ข้อมูลเป็นอนุกรมเนื่องจากมีอักขระ (0x0000)


18

ฉันมีคำถามใหญ่ (ถ้าจำเป็นฉันจะโพสต์ไว้ที่นี่) และฉันได้รับข้อผิดพลาดนี้:

ข่าวสารเกี่ยวกับ 6841, ระดับ 16, สถานะ 1, บรรทัดที่ 1
สำหรับ XML ไม่สามารถทำให้เป็นอนุกรมข้อมูลสำหรับโหนด 'NoName' เนื่องจากมีอักขระ (0x0000) ซึ่งไม่ได้รับอนุญาตใน XML ในการดึงข้อมูลนี้โดยใช้ FOR XML ให้แปลงเป็นประเภทข้อมูลไบนารี, varbinary หรือรูปภาพและใช้คำสั่ง BINARY BASE64

ส่วนเดียวที่ฉันใช้FOR XMLอยู่ที่นี่:

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

แต่อะไรนะnode noname? และฉันจะมองหาค่านี้ได้อย่างไร:(0x0000)

นี่เป็นหนึ่งในแบบสอบถามย่อย (ส่วนเดียวที่ฉันมีสำหรับ 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...

คำตอบ:


10

เส้น:

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

ควรจะเป็น:

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

11

ฉันได้รับข้อผิดพลาดเดียวกันเมื่อฉันทำสิ่งนี้:

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

ดังนั้นค้นหาอินสแตนซ์ทั้งหมดของDescFuncaoหรือDescTempoExperiencia(ขออภัยคุณไม่ได้ใช้ชื่อแทนตารางดังนั้นจึงเป็นไปไม่ได้ที่จะบอกว่ามาจากตารางใด) ซึ่งเนื้อหานั้นมีอยู่CHAR(0)และแก้ไขได้ ตัวอย่างเช่น:

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

การกรองแถวเหล่านั้นในแบบสอบถามของคุณยังไม่เพียงพอเพราะคุณไม่ทราบว่าวิธีการที่ XML จะใช้งานได้ในจุดใด แต่คุณอาจลอง:

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

แน่นอนการแก้ไขแหล่งข้อมูลหนึ่งครั้งจะมีประสิทธิภาพมากขึ้นกว่าทำงานเหล่านี้แทนที่การปฏิบัติทุกครั้ง

หมายเหตุนี่อาจไม่ใช่ตัวอักษรเฉพาะที่ทำให้เกิดปัญหานี้ 0x0001-> 0x0008จะสร้างข้อผิดพลาดเดียวกัน ดังนั้นหากคุณมีตัวละครเหล่านั้นอยู่ด้วยคุณควรตรวจสอบว่าพวกเขามาจากไหนและแก้ไขแหล่งที่มา


1
สำหรับข้อมูลที่มีอิโมจิมากมาย
devinbost

10

ผมทดสอบนี้กับอักขระ ASCII 0-255 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และพบว่าคุณได้รับข้อผิดพลาดนี้สำหรับตัวอักษร:

วิธีหนึ่งคือการลบออก, TYPEจากคำสั่ง XML ของคุณ

อีกวิธีหนึ่งคือการลบอักขระเหล่านั้นในคำสั่ง 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),'')

คุณสามารถสร้างฟังก์ชันด้วยคำสั่งแทนที่เหล่านี้


แนวคิดการแก้ปัญหานี้ช่วยให้ฉันค้นหาว่านิพจน์ทั่วไปในตารางขนาดใหญ่ที่ซับซ้อนสำหรับบล็อก xml นั้นล้มเหลวโดยมีข้อผิดพลาดนี้
Keith John Hutchison

2
สคริปต์นี้มีประโยชน์ (แม้ว่าจะช้ามาก) แต่ไม่สามารถใช้กับตัวละครอิโมจิ (เช่น 0xD83D) และฉันสงสัยว่าอาจมีพวกเขาจำนวนมาก .... อย่างน้อยก็ในข้อมูลของฉัน : '(หรือฉันควรจะพูดว่า: 0x1F62D
devinbost

1

เพิ่มประสิทธิภาพคำตอบจาก @jumxozizi โดยใช้ translate () (SQL Server 2017 ++) รหัสด้านล่างจะแทนที่ตัวละครเหล่านั้นด้วยจุด

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

หากต้องการตัดออกพวกเขาสามารถแปล () พวกเขาก่อนเพื่อ char (0) แล้วห่อด้วยแทนที่ ()

จากแนวคิด: /programming//a/55906638/538763

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.