我目前有一个响应 HTTP 请求的 C# 应用程序。 HTTP 请求 (XML) 的主体被传递到 SQL Server,此时数据库引擎执行正确的指令。其中一条指令用于使用客户的 id (InvoiceLoad) 加载有关发票的信息:
<InvoiceLoad ControlNumber="12345678901">
<Invoice>
<CustomerID>johndoe@gmail.com</CustomerID>
</Invoice>
</InvoiceLoad>
我需要对发票表(包含关联的电子邮件地址)执行 SELECT 操作。
我试过使用:
SELECT 'Date', 'Status', 'Location'
FROM Invoices
WHERE Email_Address = Invoice.A.value(.)
using an xml.nodes('InvoiceLoad/Invoice/CustomerId') Invoice(A)
命令。
但是,由于此查询每分钟可能运行数千次,因此我希望它尽可能快。我听说执行此操作的一种方法可能是使用 CROSS APPLY(我从未使用过)。那是解决方案吗?如果没有,我将如何尽可能快地进行此查询?非常感谢任何和所有建议!
最佳答案
我完全不明白您为什么需要调用 .nodes()
- 据我了解,每个 XML 片段只有一个条目 - 对吗?
给定这个 XML:
<InvoiceLoad ControlNumber="12345678901">
<Invoice>
<CustomerID>johndoe@gmail.com</CustomerID>
</Invoice>
</InvoiceLoad>
您可以使用此 SQL 获取 <CustomerID>
节点的值:
DECLARE @xmlvar XML
SET @xmlvar = '<InvoiceLoad ControlNumber="12345678901">
<Invoice>
<CustomerID>johndoe@gmail.com</CustomerID>
</Invoice>
</InvoiceLoad>'
SELECT
@xmlvar.value('(/InvoiceLoad/Invoice/CustomerID)[1]', 'varchar(100)')
您可以根据您的客户表或任何您需要做的事情加入它。
如果您将 XML 存储在一个表中,并且您总是需要从 <CustomerID>
中提取该值,您还可以考虑在该表上创建一个计算的持久化列,以提取该值- 将邮件地址放入单独的列中,然后您可以使用它来轻松加入。这需要一些工作 - 一个将 XML
作为输入的存储函数 - 但它确实是一种从 XML 中“显示”某些重要数据片段的好方法。
第 1 步:创建您的函数
CREATE FUNCTION dbo.ExtractCustomer (@input XML)
RETURNS VARCHAR(255)
WITH SCHEMABINDING
AS BEGIN
DECLARE @Result VARCHAR(255)
SELECT
@Result = @Input.value('(/InvoiceLoad/Invoice/CustomerID)[1]', 'varchar(255)')
RETURN @result
END
因此,根据您的 XML,您可以获得一个 <CustomerID>
节点并提取其“内部文本”并将其作为 VARCHAR(255)
返回。
第 2 步:向表中添加计算的持久化列
ALTER TABLE dbo.YourTableWithTheXML
ADD CustomerID AS dbo.ExtractCustomer(YourXmlColumnHere) PERSISTED
现在,具有 XML 列的表有一个新列 - CustomerID
- 它将自动包含 <CustomerID>
的内容作为 VARCHAR(255)
。该值是持久化的,即只要 XML 没有改变,就不必重新计算。您可以像使用表中的任何其他列一样使用该列,甚至可以对其编制索引以加速其上的任何连接!
关于sql-server - 使用 XML 输入的 SQL SELECT,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11126193/