Mar*_*lli 5 xml sql-server collation execution-plan encoding
我喜欢在旅途中查找丢失的索引,查看执行计划!
如果我想改进当前正在运行的东西,它可能会给我一个进一步的指示。
为此,我使用以下查询:
SET NOCOUNT ON
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
SELECT
er.session_id,
er.blocking_session_id,
er.start_time,
er.status,
dbName = DB_NAME(er.database_id),
er.wait_type,
er.wait_time,
er.last_wait_type,
er.granted_query_memory,
er.reads,
er.logical_reads,
er.writes,
er.row_count,
er.total_elapsed_time,
er.cpu_time,
er.open_transaction_count,
er.open_transaction_count,
s.text,
qp.query_plan,
logDate = CONVERT(DATETIME,GETDATE()),
logTime = CONVERT(DATETIME,GETDATE())
FROM sys.dm_exec_requests er
CROSS APPLY sys.dm_exec_sql_text(er.sql_handle) s
CROSS APPLY sys.dm_exec_query_plan(er.plan_handle) qp
WHERE
CONVERT(VARCHAR(MAX), qp.query_plan) LIKE '%<missing%'
Run Code Online (Sandbox Code Playgroud)
它通常工作正常;但是,我最近遇到了整理和 XML 的问题:
错误信息说:
SET NOCOUNT ON
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
SELECT
er.session_id,
er.blocking_session_id,
er.start_time,
er.status,
dbName = DB_NAME(er.database_id),
er.wait_type,
er.wait_time,
er.last_wait_type,
er.granted_query_memory,
er.reads,
er.logical_reads,
er.writes,
er.row_count,
er.total_elapsed_time,
er.cpu_time,
er.open_transaction_count,
er.open_transaction_count,
s.text,
qp.query_plan,
logDate = CONVERT(DATETIME,GETDATE()),
logTime = CONVERT(DATETIME,GETDATE())
FROM sys.dm_exec_requests er
CROSS APPLY sys.dm_exec_sql_text(er.sql_handle) s
CROSS APPLY sys.dm_exec_query_plan(er.plan_handle) qp
WHERE
CONVERT(VARCHAR(MAX), qp.query_plan) LIKE '%<missing%'
Run Code Online (Sandbox Code Playgroud)
我已经找到了导致它的原因:
-- get only the applications from Italy:
exec usp_sel_outstandingItems
@startdate='2021-04-07 00:00:00',
@endDate='2021-08-15 00:00:00',
@statusDateStart=NULL,
@statusDateEnd=NULL,
@office=N'UK',
@country=N'IT ',
@userState=N'ParticipantPlaced',
@outstandingBalance=0
Run Code Online (Sandbox Code Playgroud)
我的问题是:
我的查询中的哪些内容对排序规则感到不安?
我该怎么做才能克服这个错误?
Msg 6355, Level 16, State 1, Line 40
Conversion of one or more characters from XML to target collation impossible
Run Code Online (Sandbox Code Playgroud)
问题在于您正在将XML
存储为 Unicode(特别是 UTF-16)的数据转换为 8 位数据。8 位数据需要代码页才能知道要使用哪一组最多 256 个字符(如果使用双字节字符集,则最多大约 24k 个字符,但绝大多数情况下最多 256 个字符)。这里的问题是 XML 数据中存在一个字符(或可能是多个字符):a) 在当前数据库的默认排序规则指定的代码页中不存在,或者 b) 在任何代码页中都不存在。
例如,以下查询显示大多数代码页中不存在的字符(或可能不存在),因此在转换为 时会出现相同的错误VARCHAR
,但转换为NVARCHAR
有效:
SELECT NCHAR(0x1234);
-- ?
DECLARE @Test XML;
SET @Test = CONVERT(XML, N'<a>' + NCHAR(0x1234) + N'</a>')
SELECT @Test;
-- <a>?</a>
SELECT CONVERT(NVARCHAR(MAX), @Test);
-- <a>?</a>
SELECT CONVERT(VARCHAR(MAX), @Test);
/*
Msg 6355, Level 16, State 1, Line XXXXX
Conversion of one or more characters from XML to target collation impossible
*/
Run Code Online (Sandbox Code Playgroud)
请转换为NVARCHAR(MAX)
而不是VARCHAR(MAX)
。你的WHERE
谓词应该是:
CONVERT(NVARCHAR(MAX), qp.query_plan) LIKE N'%<missing%'
Run Code Online (Sandbox Code Playgroud)
(请注意在字符串字面量前添加了“N”——这不是必需的,但要养成一个好习惯)。
转换XML
数据VARCHAR
是唯一真正安全的,如果该查询是在具有UTF-8的排序规则作为默认排序规则数据库中执行,而这仅仅是在SQL Server 2019提供起动。
最后,回答您的“是否会通过COLLATE
帮助强制进行整理?”的问题:不,不是从XML
. 您不能将该COLLATE
子句添加到XML
数据中,因为排序规则不适用于XML
(您会得到“表达式类型 xml 对 COLLATE 子句无效。”)。并且,将COLLATE
外部放置在转换后CONVERT()
无济于事,因为这在此处失败了。您也不能将 紧跟在 the之后,因为它是数据类型而不是数据(您会得到“关键字 'COLLATE' 附近的语法不正确。”)。COLLATE
VARCHAR(MAX)
有关使用排序规则/编码/Unicode 的更多信息,请访问我的网站:排序规则信息
归档时间: |
|
查看次数: |
275 次 |
最近记录: |