I'm reading on SQL Server from a column in a table which is of type XML.
The problem is that there is a node called "InstalledBy" which does not always exist.
The definition of the table is like that:
CREATE TABLE [MyDatabase].[dbo].[MyTable](
[Id] [bigint] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL,
[FileGuid] [varchar](36) NOT NULL,
[XmlFileContent] [xml] NOT NULL,
CONSTRAINT [PK_MyTable] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
The part including the problematic node looks like that:
<SDCAsset Type="Software">
<SDCAsset Type="Installed Hotfixes">
<SDCAsset Type="Hotfix" Description="Installed Hotfixes" MaterialNumber="UID" SerialNumber="KB123456">
<Item Name="type" Valuetype="xs:string">Hotfix</Item>
<Item Name="key" Valuetype="xs:string">ad:HotFixID</Item>
<Item Name="HotFixID" Valuetype="xs:string">KB123456</Item>
<Item Name="InstalledBy" Valuetype="xs:string">MASTER\SYSTEM</Item>
<Item Name="InstalledOn" Valuetype="xs:date">3/17/2025</Item>
</SDCAsset>
<SDCAsset Type="Hotfix" Description="Installed Hotfixes" MaterialNumber="UID" SerialNumber="KB7890123">
<Item Name="type" Valuetype="xs:string">Hotfix</Item>
<Item Name="key" Valuetype="xs:string">ad:HotFixID</Item>
<Item Name="HotFixID" Valuetype="xs:string">KB789012</Item>
<Item Name="InstalledOn" Valuetype="xs:date">3/19/2025</Item>
</SDCAsset>
</SDCAsset>
</SDCAsset>
What I want to get is a resulttable like this:
RootType | TypeLevel1 | TypeLevel2 | HotFixID | InstalledBy | InstalledOn |
---|---|---|---|---|---|
Software | Installed Hotfixes | Hotfix | KB123456 | MASTER\SYSTEM | 3/17/2025 |
Software | Installed Hotfixes | Hotfix | KB789012 | null | 3/19/2025 |
I'm reading on SQL Server from a column in a table which is of type XML.
The problem is that there is a node called "InstalledBy" which does not always exist.
The definition of the table is like that:
CREATE TABLE [MyDatabase].[dbo].[MyTable](
[Id] [bigint] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL,
[FileGuid] [varchar](36) NOT NULL,
[XmlFileContent] [xml] NOT NULL,
CONSTRAINT [PK_MyTable] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
The part including the problematic node looks like that:
<SDCAsset Type="Software">
<SDCAsset Type="Installed Hotfixes">
<SDCAsset Type="Hotfix" Description="Installed Hotfixes" MaterialNumber="UID" SerialNumber="KB123456">
<Item Name="type" Valuetype="xs:string">Hotfix</Item>
<Item Name="key" Valuetype="xs:string">ad:HotFixID</Item>
<Item Name="HotFixID" Valuetype="xs:string">KB123456</Item>
<Item Name="InstalledBy" Valuetype="xs:string">MASTER\SYSTEM</Item>
<Item Name="InstalledOn" Valuetype="xs:date">3/17/2025</Item>
</SDCAsset>
<SDCAsset Type="Hotfix" Description="Installed Hotfixes" MaterialNumber="UID" SerialNumber="KB7890123">
<Item Name="type" Valuetype="xs:string">Hotfix</Item>
<Item Name="key" Valuetype="xs:string">ad:HotFixID</Item>
<Item Name="HotFixID" Valuetype="xs:string">KB789012</Item>
<Item Name="InstalledOn" Valuetype="xs:date">3/19/2025</Item>
</SDCAsset>
</SDCAsset>
</SDCAsset>
What I want to get is a resulttable like this:
RootType | TypeLevel1 | TypeLevel2 | HotFixID | InstalledBy | InstalledOn |
---|---|---|---|---|---|
Software | Installed Hotfixes | Hotfix | KB123456 | MASTER\SYSTEM | 3/17/2025 |
Software | Installed Hotfixes | Hotfix | KB789012 | null | 3/19/2025 |
I tried the exist function and can now see if the InstalledBy-node exists or not.
But how can i get the node value and so the resulttable I want?
This is the Select I have so far:
SELECT
[FileGuid]
,[RootType] = roottype.value('@Type', 'nvarchar(max)')
,[TypeLevel1] = typelevel1.value('@Type', 'nvarchar(max)')
,[TypeLevel2] = typelevel2.value('@Type', 'nvarchar(max)')
,ISNULL([hotfixid].value('.','nvarchar(max)'), null) AS [HotFixID]
--,ISNULL([installedby].value('.','nvarchar(max)'), null) AS [InstalledBy]
,typelevel2.exist('./Item[@Name="InstalledBy"]') AS [InstalledByExists] --1 if node with Name="InstalledBy" exists, 0 if it not exists
--,CASE
-- WHEN typelevel2.exist('./Item[@Name="InstalledBy"]') = 1 THEN ISNULL([installedby].value('.','nvarchar(max)'), null)
-- ELSE ''
-- END AS [InstalledBy]
,ISNULL([installedon].value('.','nvarchar(max)'), null) AS [InstalledOn]
FROM [MyDatabase].[dbo].[MyTable] WITH (NOLOCK)
OUTER APPLY [XmlFileContent].nodes('/rootSDCAsset/SDCAsset') AS T2(roottype)
OUTER APPLY [roottype].nodes('SDCAsset') AS T3(typelevel1)
OUTER APPLY [typelevel1].nodes('SDCAsset') AS T4(typelevel2)
OUTER APPLY [typelevel2].nodes('Item') AS T7(hotfixid)
--OUTER APPLY [typelevel2].nodes('Item') AS T8(installedby)
OUTER APPLY [typelevel2].nodes('Item') AS T9(installedon)
WHERE roottype.value('@Type', 'nvarchar(max)') = 'Software'
AND typelevel1.value('@Type', 'nvarchar(max)') = 'Installed Hotfixes'
AND typelevel2.value('@Type', 'nvarchar(max)') = 'Hotfix'
AND hotfixid.value('@Name', 'nvarchar(max)') = 'HotFixID'
--AND installedby.value('@Name', 'nvarchar(max)') = 'InstalledBy'
AND installedon.value('@Name', 'nvarchar(max)') = 'InstalledOn'
AND [FileGuid] = {...}
Share
Improve this question
edited Mar 27 at 13:14
Yitzhak Khabinsky
22.5k2 gold badges19 silver badges23 bronze badges
asked Mar 27 at 9:19
PatrickPatrick
173 bronze badges
1
- FYI, SSMS is just an IDE (like) application that is used with several products such as (but not limited to) SQL Server, Azure SQL Edge and Azure Synapse. SSMS is likely irrelevant to the question here. What product are you actually using for your data engine? Tagging [ssms] for your data engine is like tagging [visual-studio] for your programming language; it doesn't actually really tell us anything. – Thom A Commented Mar 27 at 12:19
1 Answer
Reset to default 1Please try the following solution.
If you need a blank space instead of NULL, you can wrap it as follows:
COLEASCE(t2.c.value(...), '') AS InstalledBy
SQL
-- DDL and sample data population, start
DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY,XmlFileContent XML);
INSERT INTO @tbl (XmlFileContent) VALUES
(N'<SDCAsset Type="Software">
<SDCAsset Type="Installed Hotfixes">
<SDCAsset Type="Hotfix" Description="Installed Hotfixes" MaterialNumber="UID" SerialNumber="KB123456">
<Item Name="type" Valuetype="xs:string">Hotfix</Item>
<Item Name="key" Valuetype="xs:string">ad:HotFixID</Item>
<Item Name="HotFixID" Valuetype="xs:string">KB123456</Item>
<Item Name="InstalledBy" Valuetype="xs:string">MASTER\SYSTEM</Item>
<Item Name="InstalledOn" Valuetype="xs:date">3/17/2025</Item>
</SDCAsset>
<SDCAsset Type="Hotfix" Description="Installed Hotfixes" MaterialNumber="UID" SerialNumber="KB7890123">
<Item Name="type" Valuetype="xs:string">Hotfix</Item>
<Item Name="key" Valuetype="xs:string">ad:HotFixID</Item>
<Item Name="HotFixID" Valuetype="xs:string">KB789012</Item>
<Item Name="InstalledOn" Valuetype="xs:date">3/19/2025</Item>
</SDCAsset>
</SDCAsset>
</SDCAsset>');
-- DDL and sample data population, end
SELECT t.c.value('@Type', 'NVARCHAR(128)') AS RootType
, t1.c.value('@Type', 'NVARCHAR(128)') AS TypeLevel1
, t2.c.value('@Type', 'NVARCHAR(128)') AS TypeLevel2
, t2.c.value('@SerialNumber', 'NVARCHAR(128)') AS HotFixID
, t2.c.value('(Item[@Name="InstalledBy"]/text())[1]', 'NVARCHAR(128)') AS InstalledBy
, t2.c.value('(Item[@Name="InstalledOn"]/text())[1]', 'NVARCHAR(128)') AS InstalledOn
FROM @tbl
OUTER APPLY XmlFileContent.nodes('/SDCAsset') AS t(c)
OUTER APPLY t.c.nodes('SDCAsset') AS t1(c)
OUTER APPLY t1.c.nodes('SDCAsset') AS t2(c);
Output
RootType | TypeLevel1 | TypeLevel2 | HotFixID | InstalledBy | InstalledOn |
---|---|---|---|---|---|
Software | Installed Hotfixes | Hotfix | KB123456 | MASTER\SYSTEM | 3/17/2025 |
Software | Installed Hotfixes | Hotfix | KB7890123 | NULL | 3/19/2025 |
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744100734a4558521.html
评论列表(0条)