Luk*_*zda 11 xml sql t-sql sql-server sql-server-2012
在玩游戏期间,sys.dm_exec_describe_first_result_set
我到达这一点:
CREATE TABLE #tab(col INT, x XML );
INSERT INTO #tab(col,x) VALUES (1,NULL), (2,NULL), (3,'<a>x</a>');
SELECT 'Simple XML' AS description, name, system_type_name
FROM sys.dm_exec_describe_first_result_set(
N'SELECT col
FROM #tab
FOR XML AUTO', NULL, 0)
UNION ALL
SELECT 'Wrapped with subquery', name, system_type_name
FROM sys.dm_exec_describe_first_result_set(
N'SELECT(SELECT col
FROM #tab
FOR XML AUTO) AS wrapped_subquery', NULL, 0)
UNION ALL
SELECT 'XML column', name, system_type_name
FROM sys.dm_exec_describe_first_result_set(
N'SELECT x FROM #tab ', NULL, 0)
UNION ALL
SELECT 'Casted XML', name, system_type_name
FROM sys.dm_exec_describe_first_result_set(
N'SELECT CAST(''<o>O</o>'' AS XML) AS x', NULL, 0)
UNION ALL
SELECT 'Wrapped Casted XML', name, system_type_name
FROM sys.dm_exec_describe_first_result_set(
N'SELECT (SELECT CAST(''<o>O</o>'' AS XML) AS x) AS wrapped', NULL, 0)
UNION ALL
SELECT 'Text value', name, system_type_name
FROM sys.dm_exec_describe_first_result_set(
N'SELECT CAST(''aaa'' AS NTEXT) AS text_string', NULL, 0)
UNION ALL
SELECT 'Wrapped Text Value', name, system_type_name
FROM sys.dm_exec_describe_first_result_set(
N'SELECT (SELECT CAST(''aaa'' AS NTEXT)) AS text_string_wrapped', NULL, 0)
Run Code Online (Sandbox Code Playgroud)
输出:
??????????????????????????????????????????????????????????????????????????????????????
? Description ? name ? system_type_name ?
??????????????????????????????????????????????????????????????????????????????????????
? Simple XML ? XML_F52E2B61-18A1-11d1-B105-00805F49916 ? ntext ?
? Wrapped with subquery ? wrapped_subquery ? nvarchar(max) ?
? XML column ? x ? xml ?
? Casted XML ? x ? xml ?
? Wrapped Casted XML ? wrapped ? xml ?
? Text value ? text_string ? ntext ?
? Wrapped Text Value ? text_string_wrapped ? ntext ?
??????????????????????????????????????????????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)
和:
SELECT col -- SSMS result grid - XML column
FROM #tab
FOR XML AUTO
SELECT(SELECT col -- text column
FROM #tab
FOR XML AUTO) AS wrapped_subquery
Run Code Online (Sandbox Code Playgroud)
问题:
FOR XML AUTO
不返回XML/NVARCHAR(MAX)
数据类型但是ntext
(不推荐使用数据类型!)?ntext
为nvarchar(max)
?XML/NTEXT
列?我知道我的问题可能是技术和内部操作,但我会很感激MSDN/Connect中的任何见解或文档?
编辑:
有趣的是,当我使用普通表(不是临时表)时,它返回所有ntext
:
?????????????????????????????????????????????????????????????????????????????????????
? description ? name ? system_type_name ?
?????????????????????????????????????????????????????????????????????????????????????
? Simple XML ? XML_F52E2B61-18A1-11d1-B105-00805F499 ? ntext ?
? Wrapped with subquery ? wrapped_subquery ? ntext ?
? XML column ? x ? ntext ?
? Casted XML ? x ? ntext ?
? Wrapped Casted XML ? wrapped ? ntext ?
? Text value ? text_string ? ntext ?
? Wrapped Text Value ? text_string_wrapped ? ntext ?
?????????????????????????????????????????????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)
SQL Server对xml(Transact-SQL)的支持使您可以通过指定TYPE指令,有选择地请求将FOR XML查询的结果作为xml数据类型返回.
SQL Server将XML数据类型实例数据作为不同服务器构造的结果返回给客户端,例如使用TYPE指令的FOR XML查询,或者xml数据类型用于从SQL表列返回XML实例数据值和输出参数.在客户端应用程序代码中,ADO.NET提供程序请求从服务器以二进制编码发送此XML数据类型信息.但是,如果使用不带TYPE指令的FOR XML,则XML数据将以字符串类型的形式返回.
和:
SELECT 'Simple XML' AS description, name, system_type_name
FROM sys.dm_exec_describe_first_result_set(
N'SELECT col AS col
FROM #tab
FOR XML AUTO, TYPE', NULL, 0)
UNION ALL
SELECT 'Wrapped with subquery', name, system_type_name
FROM sys.dm_exec_describe_first_result_set(
N'SELECT(SELECT col
FROM #tab
FOR XML AUTO,TYPE) AS wrapped_subquery', NULL, 0);
Run Code Online (Sandbox Code Playgroud)
ntext
不在nvarchar(max)
引用中the XML data comes back as a string type
,普通/临时表的区别在哪里?FOR XML
是在SQL Server 2000中引入的.
SQL Server 2000没有MAX
数据类型或XML
数据类型.也不可能FOR XML
在子查询中使用.
文章服务器端FOR XML返回什么?说明
在SQL Server 2000中......
FOR XML
在查询处理器和数据传输层之间的代码层中实现...查询处理器以与没有相同的方式生成结果FOR XML
,然后FOR XML
将行集代码格式化为XML.为了获得最大的XML发布性能FOR XML
,可以对生成的行集进行XML格式化,并将其输出直接以小块的形式发送到服务器端TDS代码,而无需在服务器空间中缓冲整个XML.块大小为2033 UCS-2字符.因此,大于2033个UCS-2字符的XML以多行发送到客户端,每行包含一大块XML.SQL Server使用预定义的列名此行集与类型的一列NTEXT
-XML_F52E2B61-18A1-11d1-B105-00805F49916B
" " -以表示UTF-16编码XML分块的行集.
因此,对于FOR XML
更高版本的顶级版本,它仍然以相同的方式实现.
SQL Server 2005引入了FOR XML
在子查询中使用的能力(这意味着这些现在需要由查询处理器处理而不是在其外部的层,同时将结果流式传输到客户端)
同一篇文章解释说,这些将被输入NVARCHAR(MAX)
或XML
取决于type
指令的存在与否.
除了数据类型的差异,这意味着额外的SELECT
包装器可以在性能上产生巨大差异#tab
.
/*Can be streamed straight out to client without using server storage*/
SELECT col
FROM #tab
FOR XML AUTO
/*XML constructed in its entirety in tempdb first*/
SELECT(SELECT col
FROM #tab
FOR XML AUTO) AS wrapped_subquery
Run Code Online (Sandbox Code Playgroud)
可以看到调用堆栈中的不同方法以及执行计划.
直接流式传输
sqllang.dll!CXMLExecContext::AddTagAndAttributes() + 0x5a9 bytes
sqllang.dll!CXMLExecContext::AddXMLRow() + 0x2b7 bytes
sqltses.dll!CEsExec::FastMoveEval() + 0x9c bytes
sqllang.dll!CXStmtQuery::ErsqExecuteQuery() + 0x280 bytes
sqllang.dll!CXStmtXMLSelect::WrapExecute() + 0x2d7 bytes
sqllang.dll!CXStmtXMLSelect::XretDoExecute() + 0x355 bytes
sqllang.dll!CXStmtXMLSelect::XretExecute() + 0x46 bytes
sqllang.dll!CMsqlExecContext::ExecuteStmts<1,1>() + 0x368 bytes
sqllang.dll!CMsqlExecContext::FExecute() + 0x6cb bytes
sqllang.dll!CSQLSource::Execute() + 0x3ee bytes
sqllang.dll!process_request() + 0x757 bytes
Run Code Online (Sandbox Code Playgroud)
带子查询
sqllang.dll!CXMLExecContext::AddTagAndAttributes() + 0x5a9 bytes
sqllang.dll!CXMLExecContext::AddXMLRow() + 0x2b7 bytes
sqllang.dll!CForXmlSerialize::ProcessRow() + 0x19 bytes
sqllang.dll!CUDXR_Base::PushRow() + 0x30 bytes
sqlmin.dll!CQScanUdx::Open() + 0xd5 bytes
sqlmin.dll!CQueryScan::StartupQuery() + 0x170 bytes
sqllang.dll!CXStmtQuery::SetupQueryScanAndExpression() + 0x391 bytes
sqllang.dll!CXStmtQuery::InitForExecute() + 0x34 bytes
sqllang.dll!CXStmtQuery::ErsqExecuteQuery() + 0x217 bytes
sqllang.dll!CXStmtSelect::XretExecute() + 0xed bytes
sqllang.dll!CMsqlExecContext::ExecuteStmts<1,1>() + 0x368 bytes
sqllang.dll!CMsqlExecContext::FExecute() + 0x6cb bytes
sqllang.dll!CSQLSource::Execute() + 0x3ee bytes
sqllang.dll!process_request() + 0x757 bytes
Run Code Online (Sandbox Code Playgroud)
两个最终调用相同的底层XML代码,但"展开"的版本没有在计划本身的任何XML迭代器,其结果是通过替换方法来实现从调用CXStmtSelect
与CXStmtXMLSelect
代替(在俯视为XML选择根节点,而表示而不是一个普通的旧选择).
在SQL Server 2016 CTP3上,我仍然看到ntext
顶级FOR XML
.但顶级FOR JSON
显示为nvarchar(max)
至少在CTP中,JSON特殊列名仍然包含GUID,F52E2B61-18A1-11d1-B105-00805F49916B
尽管它的起源是IXMLDocument接口.
虽然XML Select被JSON Select替换,但计划看起来大致相同
顺便说一句:在构建时,Microsoft SQL Server 2014 - 12.0.4213.0 (X64)
我没有看到临时表和永久表之间的行为有任何区别.这可能取决于@@Version
您的问题使用http://sqlfiddle.com/(12.0.2000.8)和https://data.stackexchange.com/(12.0.4213.0)的环境之间的差异.
也许在sys.dm_exec_describe_first_result_set
2014年的两个版本之间修复了一个错误.
在2012年,我得到了与Shnugo在11.0.5343.0上相同的结果(NULL
在前三行中)但是在安装SP3 11.0.6020.0后,我得到了与问题中显示的初始结果相同的结果.
归档时间: |
|
查看次数: |
994 次 |
最近记录: |