1

我正在研究是否可以在 Azure SQL Database中执行任意 SQL 命令(动态 SQL 语句或存储过程)并将结果作为 XML 返回。

我知道它可以使用常规的本地 SQL Server 数据库来完成——在我们的例子中,我们使用 CLR 函数。替代“常规”解决方案包括使用 OPENROWSET 或 OPENQUERY,这两种方法都不适用于 Azure。

自 SQL Server 2012 起提供了一个新的EXECUTE ... AS FOR XML选项,但是当我尝试它时,我得到一个错误 - 我无法找到正确的使用示例。

exec ('select ''A'', 2, ''d''')
with result sets (as for xml)

返回

消息 11537,级别 16,状态 1,第 1 行 EXECUTE 语句失败,因为其 WITH RESULT SETS 子句为结果集编号 1 指定了 1 列,但该语句在运行时发送了 3 列。

要明确明确;我无法控制正在传递的命令——它很可能是一个存储过程,并且很可能返回一个“常规”(即非 xml)结果集。用例是一组 SQL 测试,而不是实际的生产代码。

4

3 回答 3

1

我从客户咨询团队的微软高级项目经理史蒂夫霍华德那里找到了一个权威的答案:

AS FOR XML 不会将来自已执行语句或存储过程的非 XML 表格结果转换为 XML。AS FOR XML 指定EXECUTE 语句调用的语句或存储过程的 XML 结果将被转换为好像它们是由 SELECT ... FOR XML ... 语句生成的格式。原始语句中类型指令的所有格式都将被删除,返回的结果就像没有指定类型指令一样。

但他也为我提供了这个替代方案:

/*
       Demo of how to display results from a stored procedure in XML
       Author: Steve Howard
       Date: June 21, 2012
       Intended as a demo only. Adapt to your purposes

*/

-- for this demo, declare a variable @tsql_batch to hold the batch to be executed
-- note that this could become a parameter in a stored procedure if this is how this is used

declare @tsql_batch  nvarchar(4000)

-- set the variable for the demo only
-- you will need to set this in your testing

set @tsql_batch = N'exec forDemo'

-- declare a table to hold the results of sp_describe_first_result_set
-- note that this can also be used for multiple result sets. See the documentation
-- at: http://technet.microsoft.com/en-us/library/ff878602(v=sql.110).aspx
declare @resultDescription table
(
       is_hidden                                       bit                        null
,      column_ordinal                                  int                        not null primary key
,      name                                            sysname                    not null
,      is_nullable                                     bit                        null
,      system_type_id                                  int                        null
,      system_type_name                         nvarchar(256) null
,      max_length                                      smallint             null
,      precision                                       tinyint                    null
,      scale                                           tinyint                    null
,      collation_name                                  sysname                    null
,      user_type_id                             int                        null
,      user_type_database                       sysname                    null
,      user_type_schema                         sysname                    null
,      user_type_name                                  sysname                    null
,      assembly_qualified_type_name      nvarchar(4000)       null
,      xml_collection_id                        int                        null
,      xml_collection_database                  sysname                    null
,      xml_collection_schema                    sysname                    null
,      xml_collection_name                      sysname                    null
,      is_xml_document                                 bit                        null
,      is_case_sensitive                        bit                        null
,      is_fixed_length_clr_type          bit                        null
,      source_server                            sysname                    null
,      source_database                                 sysname                    null
,      source_schema                            sysname                    null
,      source_table                             sysname                    null
,      source_column                            sysname                    null
,      is_identity_column                       bit                        null
,      is_part_of_unique_key                    bit                        null
,      is_updateable                            bit                        null
,      is_computed_column                       bit                        null
,      is_sparse_column_set              bit                        null
,      ordinal_in_order_by_list          smallint             null
,      order_by_list_length              smallint             null
,      order_by_is_descending                   smallint             null
,      tds_type_id                                     int                        null
,      tds_length                                      int                        null
,      tcs_collation_id                         int                        null
,      tds_collation_sort_id                    tinyint                    null
)

-- populate the table variable
insert into @resultDescription
       exec sp_describe_first_result_set @tsql_batch

-- declare the cursor to create the "create table statement:
declare crs cursor for SELECT '[' + name + '] ' + system_type_name + ' ' + case is_nullable when 0 then 'not null ' else 'null ' end + '
' FROM @resultDescription order by column_ordinal asc

-- variables to hold the statement to be executes as well as the current value from the cursor
declare @exec NVARCHAR(4000)
declare @curVal      nvarchar(1000)
open crs
fetch next from crs into @curval
-- begin building the dynamic SQL statement to be executed
set @exec = 'DECLARE @temp TABLE 
(
' + @curval

fetch next from crs into @curval

while @@FETCH_STATUS = 0
begin
       set @exec = @exec + ', ' + @curVal
       fetch next from crs into @curVal
end
close crs
deallocate crs
set @exec = @exec + '
)


INSERT INTO @temp
       exec sp_executesql N''' + @tsql_batch + '''

SELECT * FROM @temp FOR XML AUTO

' 


-- get the results
exec (@exec)


-- of you want to just see the statement that was executed:

print @exec
于 2012-06-21T19:49:54.687 回答
0

基于使用“FOR XML AUTO TYPE”对 SQL Azure 表进行的快速测试,确实返回了 XML 格式的结果,所以我相信您肯定可以得到 XML 格式的结果,但并非每个查询都可以返回为 XML,这是需要考虑的事情。

获得完全/正确格式的 XML 有点困难,因此您可能想看看这些文章这篇文章。

于 2012-06-15T20:55:04.427 回答
0

要输出简单的(即无类型的 XML),您可以使用如下所示的“for XML”子句。

不支持键入的 XML 和 XML 索引。Windows Azure SQL 数据库支持 XML 数据类型。

在此处输入图像描述

我在 SQL Azure 中用这个例子测试了你的场景,它工作得很好:

--Create the procedure
CREATE PROC SalesLT.ProductList @ProdName nvarchar(50)
AS
-- First result set
SELECT ProductID, Name, ListPrice
    FROM SalesLT.Product
    WHERE Name LIKE @ProdName
    FOR XML AUTO;
-- Second result set 
SELECT Name, COUNT(S.ProductID) AS NumberOfOrders
    FROM SalesLT.Product AS P
    JOIN SalesLT.SalesOrderDetail AS S
        ON P.ProductID  = S.ProductID 
    WHERE Name LIKE @ProdName
    GROUP BY Name
    FOR XML AUTO;
GO

-- Execute the procedure 
EXEC SalesLT.ProductList '%tire%'
于 2012-06-19T01:08:43.683 回答