【问题标题】:PHP/SQLSRV Stored Procedure with User Defined Table Type具有用户定义表类型的 PHP/SQLSRV 存储过程
【发布时间】:2015-05-26 21:07:27
【问题描述】:

我们目前正在构建一个 Web 门户,以便能够查看我们组织的 SQL 报告。目前,该门户使用 PHP 脚本和 MS SQLSRV 驱动程序来查询我们众多的 SQL 数据库。本质上,门户通过调用我们创建的返回请求数据的存储过程来工作。然后,该网站解析数据并向用户提供他们请求的信息。此流程适用于我们所有现有的报告,除了我目前正在努力制作的报告。

有问题的存储过程/报告使用用户定义的表类型最终在脚本末尾创建 WHERE IN 类型子句,以便根据提供的帐号进行选择。

我很痛苦地意识到 SQLSRV 驱动程序不支持通过用户定义的表类型发送,因此我有一个工作函数,它接受一个 CSV 格式的输入字符串并返回一个包含数据的表。这部分有效,我可以将一串帐号传递给它,它成功地将它们解析成单独的行。如果我远程调用它,我会得到预期的结果。如果我提供 4 个帐号,我的表格会填满 4 行。

输入字符串的一个例子是:

A00000000001,A00000000002,A00000000003,A00000000004

如果我从 MS SQL Server Management Studio 手动运行此脚本/存储过程并为其提供相同的字符串,则该脚本/存储过程可以正常工作;按预期提供的每个帐号给我一行。我还可以从 Mgmt Studio 手动运行脚本,并将字符串硬编码到脚本中,我得到的结果相同,表明脚本可以正常工作。但问题是,当远程执行存储过程时,只返回最后一行,并且它始终是字符串/转换表中的最后一个帐号。更糟糕的是,如果我运行 SQL Trace Profiler,我可以看到正在发出的请求,我可以看到它正在将我的帐号插入到我的表类型中,并且对发送过来的每个帐户都这样做,但是当 Trace Profiler 显示实际存储过程,只返回一行...

我原以为问题出在我的 PHP 脚本中,但看到跟踪分析器也只捕获一行,这让我觉得远程运行时存储过程发生了一些事情......

这是一个精简版的 SQL,没有所有字段以节省空间:

USE [Livendb]
GO
/****** Object:  StoredProcedure [dbo].[cejnsqip]    Script Date: 05/25/2015 12:24:19 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[cejnsqip] @acctList varchar(MAX)
AS

--Split our comma separated list that was sent over so we can convert it to an array 
DECLARE @acctNumList acctNum_list_tbltype
INSERT INTO @acctNumList(AccountNumber) SELECT Data FROM [dbo].[cejSplitCommaList](@acctList, ',')  -- Call to function to split csv into table


SELECT
    ...
    ...
    ...
FROM AbstractData

WHERE AbstractData.AccountNumber IN(SELECT AccountNumber FROM @acctNumList)

【问题讨论】:

    标签: php sql sql-server stored-procedures sqlsrv


    【解决方案1】:

    本身不是一个答案,而是一个调查稍微不同的路径的建议......

    当 TVP 不是一个选项时(通常是由于驱动程序不支持它,如您的情况),我的后备是使用 XML 参数,然后使用 XML 函数来解析它。有时,这需要将 XML 参数公开为字符串,然后将其转换为 XML 数据类型(同样,取决于驱动程序支持)。

    这种方法具有以下好处:
    - 如果您需要比简单的逗号分隔列表更复杂的内容(例如,如果您想发送 {Acct#, Checksum} 对),则更容易扩展
    - 在我的测试中,从 XML(或 XML 片段)中提取有趣的东西而不是使用自制的解析函数会减轻 CPU 的负载
    - 能够使用模式“强类型”XML(或片段)

    如果您的 account# 列表通常超过 ~ 50 长,您也可以考虑将用于传递列表的任何内容(可以是 XML,或者,如果您弄明白的话,简单的字符串列表)分解成一个#temp 表而不是表变量,在键列上有索引。在某些情况下,这将有助于优化器选择更好的计划。

    【讨论】:

      猜你喜欢
      • 2021-11-04
      • 1970-01-01
      • 2017-05-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-08
      • 1970-01-01
      • 2013-09-02
      相关资源
      最近更新 更多