FOR XML không thể tuần tự hóa dữ liệu vì nó chứa ký tự (0x0000)


18

Tôi có một truy vấn lớn (nếu cần tôi sẽ đăng nó ở đây) và tôi đang gặp lỗi này:

Msg 6841, Cấp 16, Trạng thái 1, Dòng 1
FOR XML không thể tuần tự hóa dữ liệu cho nút 'NoName' vì nó chứa một ký tự (0x0000) không được phép trong XML. Để truy xuất dữ liệu này bằng FOR XML, hãy chuyển đổi nó thành kiểu dữ liệu nhị phân, biến thể hoặc hình ảnh và sử dụng chỉ thị BINary BASE64.

Phần duy nhất tôi sử dụng FOR XMLlà ở đây:

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

Nhưng, là node nonamegì? và làm thế nào tôi có thể tìm kiếm giá trị này:(0x0000)

Đây là một trong những truy vấn con (phần duy nhất tôi có FOR 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...

Câu trả lời:


10

Dòng:

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

Nên là:

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

11

Tôi nhận được cùng một lỗi khi tôi làm điều này:

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

Vì vậy, hãy tìm tất cả các trường hợp DescFuncaohoặc DescTempoExperiencia(xin lỗi, bạn không sử dụng bí danh bảng, vì vậy không thể biết chúng đến từ bảng nào) nơi chứa nội dung CHAR(0)và sửa chúng. Ví dụ:

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

Không đủ để lọc các hàng đó trong truy vấn của bạn, bởi vì bạn không biết tại thời điểm nào các phương thức XML sẽ hoạt động, nhưng bạn cũng có thể thử:

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

Tất nhiên, sửa dữ liệu nguồn một lần sẽ hiệu quả hơn nhiều so với việc chạy các thói quen thay thế này mỗi lần .

Lưu ý, đây có thể không phải là nhân vật cụ thể duy nhất gây ra vấn đề này. 0x0001-> 0x0008cũng sẽ tạo ra lỗi tương tự. Vì vậy, nếu bạn cũng có những ký tự đó, bạn nên điều tra xem chúng đến từ đâu và sửa nguồn.


1
Còn đối với dữ liệu có nhiều biểu tượng cảm xúc thì sao?
devinbost

10

Tôi đã thử nghiệm điều này với các ký tự ASCII 0-255 và phát hiện ra rằng bạn gặp lỗi này đối với các ký tự : 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.

Một cách giải quyết khác là xóa , TYPEkhỏi câu lệnh XML của bạn.

Một cách khác là loại bỏ các ký tự đó trong câu lệnh 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),'')

Bạn cũng có thể tạo một hàm với các câu lệnh thay thế này.


Ý tưởng giải pháp này đã giúp tôi tìm thấy nơi trong một biểu thức bảng chung phức tạp lớn mà khối xml không thành công với lỗi này.
Keith John Hutchison

2
Kịch bản này hữu ích (mặc dù rất chậm), nhưng nó không hoạt động trên các ký tự biểu tượng cảm xúc (chẳng hạn như 0xD83D) và tôi nghi ngờ rằng có thể có rất nhiều trong số chúng .... ít nhất là trong dữ liệu của tôi. : '(Hoặc tôi nên nói: 0x1F62D
devinbost

1

Tối ưu hóa câu trả lời từ @jumxozizi bằng cách sử dụng transl () (SQL Server 2017 ++). Mã dưới đây sẽ thay thế các ký tự bằng dấu chấm.

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

Để loại bỏ chúng thay vào đó, trước tiên người ta có thể dịch () chúng thành char (0) và sau đó bọc nó bằng một thay thế ().

Từ ý tưởng: /programming//a/55906638/538763

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.