大きなクエリがあり(必要に応じてここに投稿します)、次のエラーが発生します。
メッセージ6841、レベル16、状態1、行1
FOR XMLには、XMLで許可されていない文字(0x0000)が含まれているため、ノード 'NoName'のデータをシリアル化できませんでした。 FOR XMLを使用してこのデータを取得するには、binary、varbinary、またはimageデータ型に変換し、BINARY BASE64ディレクティブを使用します。
私が使用する唯一の部分はFOR XML
です:
WHERE
(CodFuncionario = Results.CodFuncionario)
FOR XML PATH(''), TYPE).value('(./text())[1]',
'VARCHAR(MAX)'), 1, 2, '') AS [Experiencia]
しかし、node noname
とは何ですか?そして、どのようにこの値を探すことができます:(0x0000)
これはサブクエリの1つです(私が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...
この線:
...
SELECT
[CodFuncionario],
STUFF
(
(
SELECT
' / ' +
CAST
(
[DescFuncao] + '-' +
[DescTempoExperiencia]
AS VARCHAR(MAX)
)...
する必要があります:
...
SELECT
[CodFuncionario],
STUFF
(
(
SELECT
' / ' +
CAST
(
replace -- *** NEW! ***
(
[DescFuncao] + '-' +
[DescTempoExperiencia],
char(0),
''
)
AS VARCHAR(MAX)
)...
これを行うと同じエラーが発生します。
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))
もちろん、ソースデータの修正onceは、これらの置換ルーチン毎回を実行するよりもはるかに効率的です。
この問題の原因となる特定の文字はこれだけではない場合があることに注意してください。 0x0001
-> 0x0008
も同じエラーを生成します。したがって、そこにもそれらの文字がある場合は、それらがどこから来ているのかを調査し、ソースを修正する必要があります。
これを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
でこのエラーが発生することがわかりました。
回避策の1つは、XMLステートメントから, TYPE
を削除することです。
別の方法は、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),'')
これらのreplaceステートメントを使用して関数を作成することもできます。
Translate()を使用して@jumxoziziからの回答を最適化する(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)に変換()してから、それをreplace()でラップします。