具有用户定义表类型的PHP/SQLSRV存储过程

具有用户定义表类型的PHP/SQLSRV存储过程,php,sql,sql-server,stored-procedures,sqlsrv,Php,Sql,Sql Server,Stored Procedures,Sqlsrv,我们目前正在构建一个web门户,以便能够查看组织的SQL报告。目前,门户使用一个PHP脚本和MS SQLSRV驱动程序对我们众多的SQL数据库进行查询。本质上,门户通过调用我们创建的存储过程来工作,这些存储过程返回请求的数据。然后,网站解析数据,并向用户提供他们请求的信息。这个过程适用于我们现有的所有报告,除了一个我目前正在努力工作的报告 有问题的存储过程/报表使用用户定义的表类型,最终在脚本末尾生成WHERE IN type子句,以便根据提供的帐号进行选择 我痛苦地意识到,SQLSRV驱动程序

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

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

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

输入字符串的示例如下:

A00000000001、A00000000002、A00000000003、A00000000004

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

我原以为问题出在我的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)

这本身并不是一个答案,而是一个研究稍微不同路径的建议

当TVP不是一个选项时,我的回退通常是因为驱动程序不支持它,比如在您的例子中,使用XML参数,然后使用XML函数来解析它。有时,这需要将XML参数作为字符串公开,然后根据驱动程序支持将其再次转换为XML数据类型

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

如果你的帐号列表超过50长,你也可以考虑把你用来传递列表的任何东西都变成XML,或者,如果你找出它,把简单的字符串列表变成一个临时表,而不是一个表变量,在键列上有一个索引。在某些情况下,这将帮助优化器选择更好的计划