SQL Server 2019 存储过程中的 XML 节点需要一个 where 子句
Need a where clause for an XML Node in a SQL Server 2019 stored procedure
我有 150 万个 XML 文档存储在 SQL Server 2019 数据库中,我需要在存储过程中有一个包含多个节点的 where 子句。
<PROJECTS xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<row>
<APPLICATION_ID>1015</APPLICATION_ID>
<ORG_STATE>SC</ORG_STATE>
<ORG_CITY>Charleston</ORG_CITY>
<ORG_ZIPCODE>29407</ORG_ZIPCODE>
<PIS>
<PI>
<PI_NAME>BO, LEO (contact)</PI_NAME>
<PI_ID>9983950 (contact)</PI_ID>
</PI>
<PI>
<PI_NAME>KUZ, BEN I</PI_NAME>
<PI_ID>1862593</PI_ID>
</PI>
</PIS>
<PROJECT_START>08/15/2019</PROJECT_START>
<PROJECT_END>05/31/2024</PROJECT_END>
<INDIRECT_COST_AMT>103034</INDIRECT_COST_AMT>
<TOTAL_COST>638854</TOTAL_COST>
<TOTAL_COST_SUB_PROJECT />
</row>
</PROJECTS>
我需要提取 PI_ID
等于 9983950
的所有 XML 个文件。 PIS 节点中 PI 的数量可以是 1 个或 5 个。
我正在使用此代码:
SELECT TOP 100
[APPLICATION_ID], [FileName], [XMLData],
nref.value('ORG_CITY[1]', 'VARCHAR(30)') as ORG_CITY
FROM
[NIH_EXPORTER].[dbo].[ADMIN_Exporter_Files_XML]
CROSS APPLY
XMLData.nodes('//row[1]') AS R(nref)
WHERE
nref.value('ORG_CITY[1]', 'VARCHAR(30)') = 'Charleston'
当我需要城市但我不确定在有多个节点时如何找到值
您可以检查是否存在任何需要的 PIS/PI
节点,并在链下使用 CROSS APPLY。
SELECT TOP 100
[APPLICATION_ID], [FileName], [XMLData],
nref.value('ORG_CITY[1]', 'VARCHAR(30)') as ORG_CITY
FROM
[NIH_EXPORTER].[dbo].[ADMIN_Exporter_Files_XML]
CROSS APPLY
XMLData.nodes('//row[1]') AS R(nref)
--
cross apply (select top(1) null x
from R.nref.nodes('./PIS/PI') t(n)
where t.n.value('./PI_ID[1]', 'VARCHAR(30)') like '9983950%' ) t
--
WHERE
nref.value('ORG_CITY[1]', 'VARCHAR(30)') = 'Charleston'
请尝试以下解决方案。
SQL
-- DDL and sample data population, start
DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, xmldata XML);
INSERT INTO @tbl (xmldata) VALUES
(N'<PROJECTS xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<row>
<APPLICATION_ID>1015</APPLICATION_ID>
<ORG_STATE>SC</ORG_STATE>
<ORG_CITY>Charleston</ORG_CITY>
<ORG_ZIPCODE>29407</ORG_ZIPCODE>
<PIS>
<PI>
<PI_NAME>BO, LEO (contact)</PI_NAME>
<PI_ID>9983950 (contact)</PI_ID>
</PI>
<PI>
<PI_NAME>KUZ, BEN I</PI_NAME>
<PI_ID>1862593</PI_ID>
</PI>
</PIS>
<PROJECT_START>08/15/2019</PROJECT_START>
<PROJECT_END>05/31/2024</PROJECT_END>
<INDIRECT_COST_AMT>103034</INDIRECT_COST_AMT>
<TOTAL_COST>638854</TOTAL_COST>
<TOTAL_COST_SUB_PROJECT/>
</row>
</PROJECTS>');
-- DDL and sample data population, end
DECLARE @PI_ID VARCHAR(20) = '9983950';
SELECT ID
, xmldata.value('(/PROJECTS/row/ORG_CITY/text())[1]', 'VARCHAR(30)') as ORG_CITY
FROM @tbl
WHERE xmldata.exist('/PROJECTS/row/PIS/PI/PI_ID[contains(./text()[1], sql:variable("@PI_ID"))]') = 1;
我有 150 万个 XML 文档存储在 SQL Server 2019 数据库中,我需要在存储过程中有一个包含多个节点的 where 子句。
<PROJECTS xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<row>
<APPLICATION_ID>1015</APPLICATION_ID>
<ORG_STATE>SC</ORG_STATE>
<ORG_CITY>Charleston</ORG_CITY>
<ORG_ZIPCODE>29407</ORG_ZIPCODE>
<PIS>
<PI>
<PI_NAME>BO, LEO (contact)</PI_NAME>
<PI_ID>9983950 (contact)</PI_ID>
</PI>
<PI>
<PI_NAME>KUZ, BEN I</PI_NAME>
<PI_ID>1862593</PI_ID>
</PI>
</PIS>
<PROJECT_START>08/15/2019</PROJECT_START>
<PROJECT_END>05/31/2024</PROJECT_END>
<INDIRECT_COST_AMT>103034</INDIRECT_COST_AMT>
<TOTAL_COST>638854</TOTAL_COST>
<TOTAL_COST_SUB_PROJECT />
</row>
</PROJECTS>
我需要提取 PI_ID
等于 9983950
的所有 XML 个文件。 PIS 节点中 PI 的数量可以是 1 个或 5 个。
我正在使用此代码:
SELECT TOP 100
[APPLICATION_ID], [FileName], [XMLData],
nref.value('ORG_CITY[1]', 'VARCHAR(30)') as ORG_CITY
FROM
[NIH_EXPORTER].[dbo].[ADMIN_Exporter_Files_XML]
CROSS APPLY
XMLData.nodes('//row[1]') AS R(nref)
WHERE
nref.value('ORG_CITY[1]', 'VARCHAR(30)') = 'Charleston'
当我需要城市但我不确定在有多个节点时如何找到值
您可以检查是否存在任何需要的 PIS/PI
节点,并在链下使用 CROSS APPLY。
SELECT TOP 100
[APPLICATION_ID], [FileName], [XMLData],
nref.value('ORG_CITY[1]', 'VARCHAR(30)') as ORG_CITY
FROM
[NIH_EXPORTER].[dbo].[ADMIN_Exporter_Files_XML]
CROSS APPLY
XMLData.nodes('//row[1]') AS R(nref)
--
cross apply (select top(1) null x
from R.nref.nodes('./PIS/PI') t(n)
where t.n.value('./PI_ID[1]', 'VARCHAR(30)') like '9983950%' ) t
--
WHERE
nref.value('ORG_CITY[1]', 'VARCHAR(30)') = 'Charleston'
请尝试以下解决方案。
SQL
-- DDL and sample data population, start
DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, xmldata XML);
INSERT INTO @tbl (xmldata) VALUES
(N'<PROJECTS xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<row>
<APPLICATION_ID>1015</APPLICATION_ID>
<ORG_STATE>SC</ORG_STATE>
<ORG_CITY>Charleston</ORG_CITY>
<ORG_ZIPCODE>29407</ORG_ZIPCODE>
<PIS>
<PI>
<PI_NAME>BO, LEO (contact)</PI_NAME>
<PI_ID>9983950 (contact)</PI_ID>
</PI>
<PI>
<PI_NAME>KUZ, BEN I</PI_NAME>
<PI_ID>1862593</PI_ID>
</PI>
</PIS>
<PROJECT_START>08/15/2019</PROJECT_START>
<PROJECT_END>05/31/2024</PROJECT_END>
<INDIRECT_COST_AMT>103034</INDIRECT_COST_AMT>
<TOTAL_COST>638854</TOTAL_COST>
<TOTAL_COST_SUB_PROJECT/>
</row>
</PROJECTS>');
-- DDL and sample data population, end
DECLARE @PI_ID VARCHAR(20) = '9983950';
SELECT ID
, xmldata.value('(/PROJECTS/row/ORG_CITY/text())[1]', 'VARCHAR(30)') as ORG_CITY
FROM @tbl
WHERE xmldata.exist('/PROJECTS/row/PIS/PI/PI_ID[contains(./text()[1], sql:variable("@PI_ID"))]') = 1;