Pol*_*ris 1 php sql sql-server stored-procedures sqlsrv
我在SQL Server 2012中有一个存储过程,它首先检查数据是否存在,如果存在,则将Output参数设置@Return
为1并运行select查询,如果不存在,则设置@Return
为0并返回不同的select查询.
在测试此存储过程以确保数据准确时,它是完美的并返回我期望的数据.问题在于PHP端在尝试读取它显示的输出参数??t_rrr
时应该显示1或0.我相信问题可能在sqlsrv_query中的预定义常量中,但我似乎无法使其工作.这是我的代码:
PHP:
if(isset($_GET['accno'])) {
$search = $_GET['accno'];
$return = "";
$tsql_callSP = "EXEC Intranet.CustomerSearch @Search=?, @Return=?";
$params = array(
array($search, SQLSRV_PARAM_IN),
array($return, SQLSRV_PARAM_OUT, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR),SQLSRV_SQLTYPE_INT),
);
/* Execute the query. */
$stmt = sqlsrv_query( $conn, $tsql_callSP, $params);
if( $stmt === false )
{
echo "EXEC Intranet.CustomerSearch Failed\n";
die( print_r( sqlsrv_errors(), true));
}
while($res = sqlsrv_next_result($stmt))
{
// make sure all result sets are stepped through,
// since the output params may not be set until this happens
}
echo $return;
if($return == 0) { ?>
//1st Result Set
while($row = sqlsrv_fetch_array($stmt)) {
}
<?php } elseif($return == 1) { // End if Return 0 ?>
//2nd Result Set
while($row = sqlsrv_fetch_array($stmt)) {
}
<?php } // End if Return 1 ?>
Run Code Online (Sandbox Code Playgroud)
SQL存储过程:
USE [Intranet]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [Intranet].[CustomerSearch]
@Search nvarchar(10)
,@Return int output
AS
BEGIN
SET NOCOUNT ON;
IF EXISTS
(
SELECT KeyCode
FROM Autopart.dbo.Customer
WHERE KeyCode = @Search
)
BEGIN
SELECT
Customer.KeyCode
,Customer.X13
,Customer.Name
,Customer.Addra
,Customer.Addrb
,Customer.Addrc
,Customer.Addrd
,Customer.Addre
,Customer.PCode
,Customer.CTitle
,Customer.Climit
,Customer.Ptype
,Customer.Stel
,Customer.SCont
,Customer.ACont
,Customer.XString5
,Customer.Locked
,Customer.Email
,Customer.StopStatus
,CusNotes.Comment
FROM
Autopart.dbo.Customer
LEFT OUTER JOIN Autopart.dbo.CusNotes ON Autopart.dbo.Customer.KeyCode = Autopart.dbo.CusNotes.Account
WHERE
(Customer.KeyCode = @Search)
AND (CusNotes.Seqno = 1 OR CusNotes.Seqno IS NULL)
SET @Return = 1
END ELSE BEGIN
SELECT TOP 100
KeyCode
,Name
,PCode
,Addra
,Addrb
,Addrc
FROM
AUTOPART.dbo.Customer
WHERE
(KeyCode LIKE '%'+@Search+'%'
OR Name LIKE '%'+@Search+'%'
OR PCode LIKE '%'+@Search+'%')
SET @Return = 0
END
END
Run Code Online (Sandbox Code Playgroud)
我试过更改PHP和SQL类型但无法获得所需的结果.奇怪的是,如果我创建一个正确返回的存储过程INSERT
或UPDATE
语句OUTPUT
.
编辑:
SQL Server存储过程排序规则是Latin1_General_CI_AS
我碰巧在我的VirtualBox上安装了SQL Server和PHP,所以我玩了.
一些事情:
&
传递参数时使用.sqlsrv_next_result
.这个建议来自sqlsrv_prepare
底部的例子.这是代码:
$search = "qweryt";
$return = 123;
$tsql_callSP = "EXEC Intranet.CustomerSearch @Search=?, @Return=?";
$params = array(
array(&$search, SQLSRV_PARAM_IN),
array(&$return, SQLSRV_PARAM_OUT),
);
$stmt = sqlsrv_query($conn, $tsql_callSP, $params);
if ($stmt === false)
{
echo "EXEC Intranet.CustomerSearch Failed\n";
die( print_r( sqlsrv_errors(), true));
}
else
{
while($res = sqlsrv_next_result($stmt))
{
// make sure all result sets are stepped through,
// since the output params may not be set until this happens
}
}
echo $return;
Run Code Online (Sandbox Code Playgroud)
已通过PHP 5.4.28,SQL Server Express 2014,PHP SQLSRV 3.2的Microsoft驱动程序验证
如果您的存储过程只执行INSERT
或者UPDATE
,即不返回结果SELECT
,则sqlsrv_next_result
恰好不需要获取output
参数的值.如果SELECT
与输出参数一起使用,则实际上意味着该过程返回多个结果集,您需要读取所有这些结果集.
实际上,这是一个非常相似的问题.
如果我理解正确,您首先要检索OUTPUT
参数的值.然后,您想要检索SELECT
语句的结果.
据我了解,这是不可能的.SQL Server SELECT
在第一个结果集中返回语句结果,您可以使用该结果集进行读取sqlsrv_fetch_array
.然后使用移动到第二个结果集sqlsrv_next_result
.此时,OUTPUT
参数的值将传输到PHP变量,因为SQL Server会OUTPUT
在最后一个结果集中发送参数值.在您调用之后sqlsrv_next_result
,第一个结果集不再可用sqlsrv_fetch_array
.
顺便说一下,当你说
奇怪的是,如果我创建一个INSERT或UPDATE语句的存储过程,OUTPUT会正确返回.
,这很有道理.如果存储过程没有SELECT
语句且没有语句SET NOCOUNT ON;
,则返回的唯一结果集是OUTPUT
参数,因此为PHP变量分配了正确的值而没有显式调用sqlsrv_next_result
.
所以,你至少有两个选择.
1)使用将完整结果读SELECT
入临时数组sqlsrv_fetch_array
.然后使用sqlsrv_next_result
获取OUTPUT
参数的值.然后SELECT
根据OUTPUT
参数的接收值处理第一个保存在数组中的结果.
2)根本不要使用OUTPUT
参数.使用此类参数,SQL Server会隐式返回多个结果集.由于您有任何方式的多个结果集,请显式返回两个结果集.在你的存储过程中,首先SELECT
只返回一行一个数字,然后你的主要SELECT
:
ALTER PROCEDURE [Intranet].[CustomerSearch]
@Search nvarchar(10)
AS
BEGIN
SET NOCOUNT ON;
IF EXISTS
(
SELECT KeyCode
FROM Autopart.dbo.Customer
WHERE KeyCode = @Search
)
BEGIN
SELECT CAST(1 AS int) AS ReturnCode;
SELECT
Customer.KeyCode
,Customer.X13
,Customer.Name
,Customer.Addra
,Customer.Addrb
,Customer.Addrc
,Customer.Addrd
,Customer.Addre
,Customer.PCode
,Customer.CTitle
,Customer.Climit
,Customer.Ptype
,Customer.Stel
,Customer.SCont
,Customer.ACont
,Customer.XString5
,Customer.Locked
,Customer.Email
,Customer.StopStatus
,CusNotes.Comment
FROM
Autopart.dbo.Customer
LEFT OUTER JOIN Autopart.dbo.CusNotes ON Autopart.dbo.Customer.KeyCode = Autopart.dbo.CusNotes.Account
WHERE
(Customer.KeyCode = @Search)
AND (CusNotes.Seqno = 1 OR CusNotes.Seqno IS NULL)
;
END ELSE BEGIN
SELECT CAST(0 AS int) AS ReturnCode;
SELECT TOP 100
KeyCode
,Name
,PCode
,Addra
,Addrb
,Addrc
FROM
AUTOPART.dbo.Customer
WHERE
KeyCode LIKE '%'+@Search+'%'
OR Name LIKE '%'+@Search+'%'
OR PCode LIKE '%'+@Search+'%'
;
END
END
Run Code Online (Sandbox Code Playgroud)
在PHP代码中sqlsrv_fetch_array
第一次调用ReturnCode
.然后调用sqlsrv_next_result
切换到第二个结果集.然后调用sqlsrv_fetch_array
读取主要的结果SELECT
.
$search = "qweryt";
$tsql_callSP = "EXEC Intranet.CustomerSearch @ParamSearch=?";
$params = array
(
array(&$search, SQLSRV_PARAM_IN)
);
$stmt = sqlsrv_query($conn, $tsql_callSP, $params);
if( $stmt === false )
{
echo "EXEC Failed\n";
die( print_r( sqlsrv_errors(), true));
}
echo "First result set:\n";
while ($row = sqlsrv_fetch_array($stmt))
{
var_dump($row);
}
echo "Next result:\n";
$next_res = sqlsrv_next_result($stmt);
var_dump($next_res);
echo "Second result set:\n";
while ($row = sqlsrv_fetch_array($stmt))
{
var_dump($row);
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
4491 次 |
最近记录: |