PHP中的SQL Server存储过程输出参数

6

我需要帮助在PHP中运行SQL Server的存储过程。PHP运行在Unix/Linux服务器上。我们无法在PHP中获取输出变量。以下是PHP代码:

$conn = mssql_connect('server', 'user', 'pass');
    mssql_select_db('db', $conn);

    $procedure = mssql_init('usp_StoredProc', $conn);

    $tmpVar1 = 'value';
    $tmpVar2 = 'value2';

    $outVar1 = '';
    $outVar2 = '';

    mssql_bind($procedure, "@var1", $tmpVar1, SQLVARCHAR, false, false);
    mssql_bind($procedure, "@var2", $tmpVar2, SQLVARCHAR, false, false);

    mssql_bind($procedure, "@outVar1", $outVar1, SQLVARCHAR, true);
    mssql_bind($procedure, "@outVar2", $outVar2, SQLVARCHAR, true);

    mssql_execute($procedure,$conn);

    print($outVar1);
    print($outVar2);

存储过程的样式如下所示:
    SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER proc [dbo].[usp_StoredProc]
(
    @var1 as varchar(36), 
    @var2 as varchar(10), 
    @outVar1 varchar(36) OUTPUT, 
    @outVar2 varchar(36) OUTPUT 
)
as
  select distinct 
    @outVar1 = row1, 
    @outVar2 = row2
  from table1
  where column1 = @var1
    and column2 = @var2

有谁能告诉我为什么$outVar1和$outVar2没有被填充吗?非常感谢任何帮助!


mssql_get_last_message() 会返回一些有用的信息吗? - Tomalak
mssql_get_last_message() 返回 '已更改数据库上下文为 "dbName"'。 - ericwindham
你试过用一个包含36个空格的字符串吗? - Tomalak
是的,我们已经尝试在 mssql_bind 调用中指定长度了。仍然没有运气。 - ericwindham
未定义函数mssql_bind,错误显示。 - Bhavesh Nayi
显示剩余5条评论
8个回答

3
根据PHP错误页面的说法,你需要(我的强调):
对于存储过程返回的每个结果集调用mssql_next_result()。这样你就可以处理多个结果。
mssql_next_result()返回false时,你将可以访问输出参数和返回值。

1
你可以通过传递可选的第二个参数到mssql_execute函数中(如果参数值为True),直接访问结果,而无需调用mssql_next_result函数...不过这在这里仍然无济于事,遗憾地说。 - Joe
起初听起来似乎是有道理的。:-\ - Tomalak
如果您不知道存储过程是否会返回结果,即 $result = mssql_execute($procedure) ,则此方法可行,无论是否有结果返回,您都可以调用 mysql_next_result($result) 来获取输出参数。 - icc97

2
execute方法的第二个参数需要为true,而不是conn。这样应该可以正常工作:
$conn = mssql_connect('server', 'user', 'pass');
mssql_select_db('db', $conn);

$procedure = mssql_init('usp_StoredProc', $conn);

$tmpVar1 = 'value';
$tmpVar2 = 'value2';

$outVar1 = '';
$outVar2 = '';

mssql_bind($procedure, "@var1", $tmpVar1, SQLVARCHAR, false, false);
mssql_bind($procedure, "@var2", $tmpVar2, SQLVARCHAR, false, false);

mssql_bind($procedure, "@outVar1", $outVar1, SQLVARCHAR, true);
mssql_bind($procedure, "@outVar2", $outVar2, SQLVARCHAR, true);

mssql_execute($procedure,true);

print($outVar1);
print($outVar2);

1

尝试指定输出字段的具体长度

mssql_bind($procedure, "@outVar1", &$outVar1, SQLVARCHAR, true, false, 36);
mssql_bind($procedure, "@outVar2", &$outVar2, SQLVARCHAR, true, false, 36);

看看是否有所不同。

还要注意显式的&,以通过引用传递输出变量,尽管我不知道它是否仍然需要。


这也是我的下一个想法,+1。提供一个包含36个空格的字符串也可以作为一个有用的测试。 - Tomalak
是的,我们已经尝试了各种方法,包括使用长度和不使用长度。使用传址参数(现在会抛出一个错误,提示该方法已被弃用)以及不使用传址参数。 - ericwindham
关于显式引用传递 - 不认为这是必要的。文档说明该函数仅接受引用。 - Tomalak
我有一个模糊的记忆,以前需要显式地通过引用传递参数,但现在文档显示始终都是通过引用传递。谢谢。 - Joe

0

我怀疑这不是导致你问题的原因,但为什么要使用DISTINCT

这只是一种代码异味 - 每当你看到它时,就意味着可能会返回重复项,并且使用DISTINCT进行“处理”,而为什么会返回重复项可能需要进一步检查。


Distinct可以省略,但我们正在寻找row1和row2的不同组合。如果我们从SQL Server Management工具运行存储过程,它可以正常运行。我们遇到的问题是在php中获取输出参数。 - ericwindham
注意,在像这样的SELECT语句中,如果结果集包含多行,则会出现错误。如果结果集为空,则变量将不会被更改(如果它们从未被赋值,则为NULL)。 - Cade Roux
干得好,Cade。但实际查询只返回一行,所以不是这个问题。这让我很烦恼。我们使用存储过程的所有操作都有效,除了检索输出参数。 - ericwindham
Tomalak是正确的,必须在访问OUTPUT参数之前消耗所有结果集。当我想使用OUTPUT参数返回客户端可以在消耗行之前使用的计数估计时,我遇到了麻烦 - 这是行不通的。 - Cade Roux
我在多个地方看到过这个,但是应该怎么做呢?您需要使用mssql_execute来执行存储过程,它不会返回一个资源。 - ericwindham
$result = mssql_execute($my_procedure); while(mssql_next_recordset($result)) {

做一些事情

}
- Cade Roux

0

嗯。有几点评论:

1)“mssql_execute($procedure,$conn);”是错误的,因为第二个参数不是连接。

2)如果你得到“存储过程执行失败”的消息,那么我必须在freetds.conf中创建一个DB主机并引用它。

到达这一点时,我没有错误,但也没有输出参数。这是在RHEL5上的PHP 5.1。

如果我启用freeTDS日志记录,我会看到返回包中的数据。此时,我也不知道为什么它不起作用(除了SQL服务器对PHP的支持有点不足!)


谢谢,乔。我们已经从mssql_query中删除了$conn参数。是的,我刚从我的Windows电脑通过WampServer运行了这个脚本,它可以正常工作。因此,我认为你说的在Unix/Linux上PHP对SQL Server支持有点不足是正确的。 - ericwindham

0

0

我已经通过Adodb库以非常简单的方式完成了这个...

$addProduct = $obj->ExecuteQuery("Begin;DECLARE @ProductCode as varchar (100) ;EXEC CREATEPRODUCT'$pname', '$price', @ProductCode OUTPUT, '$merchantId';select @ProductCode;End;");

$productCode = $addProduct[0][0];

如需更多解释,请访问此网站.. http://developer99.blogspot.com/2011/07/calling-ms-sql-sp-from-php.html


0

不确定您正在运行哪个版本的PHP,但我认为在一些旧版本中,您需要通过引用传递变量才能再次获取值:

因此,在调用函数时,您需要在变量之前放置&字符:

mssql_bind($procedure, "@outVar1", &$outVar1, SQLVARCHAR, true);
mssql_bind($procedure, "@outVar2", &$outVar2, SQLVARCHAR, true);

根据这个链接,一些版本存在输出参数问题


是的,我们正在运行php 5.*,忘记了确切的版本,但这些问题不应该在这个版本中存在。传递引用的方法会抛出一个错误,说“在mssql_bind中通过引用传递已被弃用”。 - ericwindham

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接