我有一个情况
样本元素
<ColumnReference Database="[Adventureworks]" Schema="[dbo]" Table="[Product]" Column="ProductID" />
挑战:ColumnReference
有多个层次结构,需要提取所有这些
预期产出如下表所示:
Database | Schema | Table | Column
示例数据集:(运行下面的代码,您将在temptable中获取名为#t的数据集)
CREATE TABLE Employee
(
EmpID INT NOT NULL ,
EmpName VARCHAR(50) NOT NULL,
Designation VARCHAR(50) NULL,
Department VARCHAR(50) NULL,
JoiningDate DATETIME NULL,
CONSTRAINT [PK_Employee] PRIMARY KEY CLUSTERED (EmpID)
)
INSERT INTO Employee
(EmpID, EmpName, Designation, Department, JoiningDate) VALUES
(1, 'CHIN YEN', 'LAB ASSISTANT', 'LAB', GETDATE()),
(2, 'MIKE PEARL', 'SENIOR ACCOUNTANT', 'ACCOUNTS', GETDATE()),
(3, 'GREEN FIELD', 'ACCOUNTANT', 'ACCOUNTS', GETDATE()),
(4, 'DEWANE PAUL', 'PROGRAMMER', 'IT', GETDATE()),
(5, 'MATTS', 'SR. PROGRAMMER', 'IT', GETDATE()),
(6, 'PLANK OTO', 'ACCOUNTANT', 'ACCOUNTS', GETDATE())
create proc itemployee
as
select EmpName, Designation from Employee where department = 'it'
go
exec itemployee
SELECT
'itemployee ' as SP_Name,
query_plan into #t FROM sys.dm_exec_cached_plans cp CROSS APPLY sys.dm_exec_query_plan(cp.plan_handle)
WHERE
object_id('itemployee') = objectid;
用于提取输出的查询:
SELECT
AnyColRef.value('@Table', 'nvarchar(250)') AS [Table],
AnyColRef.value('@Column', 'nvarchar(250)') AS [Column]
FROM
#t t
CROSS APPLY t.query_plan.nodes('//ColumnReference') A(AnyColRef);
你提供的是不够的......对于你的下一个问题,请尝试创建一个mcve (a stand-alone sample to reproduce your issue)。
挑战:ColumnReference可用于多个层次结构,需要提取所有这些层次结构
作为快速拍摄,您可以尝试以下方法:
SELECT AnyColRef.value('@Database','nvarchar(250)') AS [Database]
,AnyColRef.value('@Schema','nvarchar(250)') AS [Schema]
,AnyColRef.value('@Table','nvarchar(250)') AS [Table]
,AnyColRef.value('@Column','nvarchar(250)') AS [Column]
FROM YourTable t
CROSS APPLY t.YourXMLColumn.nodes('//ColumnReference') A(AnyColRef);
简而言之:
深度搜索(由//ColumnReference
的双斜线触发)将在XML中的任何位置搜索具有此名称的任何元素。所有这些元素都作为派生集返回,其中每个元素都返回自己的行(这由.nodes()
完成)。原生XML方法.value()
将最终检索属性的iternal值(由@
指示)。
最好是提供您想要阅读的XML样本,但是对于上面的代码来说,重现您的问题,它也有所帮助。
您的问题是:XML声明了一个默认命名空间。有三种方法可以解决这个问题:
WITHXMLNAMESPACES
WITHXMLNAMESPACES
和DEFUALT
default element namespace
的内部声明这个
WITH XMLNAMESPACES('http://schemas.microsoft.com/sqlserver/2004/07/showplan' AS ns)
SELECT
AnyColRef.value('@Table', 'nvarchar(250)') AS [Table],
AnyColRef.value('@Column', 'nvarchar(250)') AS [Column]
FROM
#t t
CROSS APPLY t.query_plan.nodes('//ns:ColumnReference') A(AnyColRef);
- 或这个
WITH XMLNAMESPACES(DEFAULT 'http://schemas.microsoft.com/sqlserver/2004/07/showplan')
SELECT
AnyColRef.value('@Table', 'nvarchar(250)') AS [Table],
AnyColRef.value('@Column', 'nvarchar(250)') AS [Column]
FROM
#t t
CROSS APPLY t.query_plan.nodes('//ColumnReference') A(AnyColRef);
- 或这个
SELECT
AnyColRef.value('@Table', 'nvarchar(250)') AS [Table],
AnyColRef.value('@Column', 'nvarchar(250)') AS [Column]
FROM
#t t
CROSS APPLY t.query_plan.nodes('declare namespace ns="http://schemas.microsoft.com/sqlserver/2004/07/showplan";//ns:ColumnReference') A(AnyColRef);
- 或这个
SELECT
AnyColRef.value('@Table', 'nvarchar(250)') AS [Table],
AnyColRef.value('@Column', 'nvarchar(250)') AS [Column]
FROM
#t t
CROSS APPLY t.query_plan.nodes('declare default element namespace "http://schemas.microsoft.com/sqlserver/2004/07/showplan" ;//ColumnReference') A(AnyColRef);
- 或这个
SELECT
AnyColRef.value('@Table', 'nvarchar(250)') AS [Table],
AnyColRef.value('@Column', 'nvarchar(250)') AS [Column]
FROM
#t t
CROSS APPLY t.query_plan.nodes('//*:ColumnReference') A(AnyColRef);
一般建议是:尽可能具体。命名空间不仅仅是一个花哨的附加组件,而且非常重要,可以处理具有相同名称的不同元素(通常在组合各种XML时)。只有在您可以确定不需要命名空间的情况下,才使用easy-cheesy通配符。我个人更喜欢WITH XMLNAMESPACES
与DEFAULT
的方法,因为它最接近给定的XML。