Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/259.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP7.1 PDO+;SQL Server 2014:bindParam问题_Php_Sql Server - Fatal编程技术网

PHP7.1 PDO+;SQL Server 2014:bindParam问题

PHP7.1 PDO+;SQL Server 2014:bindParam问题,php,sql-server,Php,Sql Server,从php PDO执行SQL Server存储过程时遇到问题: 如果$SQL中的参数与存储过程中的参数顺序不同,则值不会传递给相应的参数,而是传递给列表中的下一个参数: 这里有一个例子: <?php $hostname = ''; $database = ''; $user = ''; $password = ''; $DB = new PDO("sqlsrv:Server=".$hostna

从php PDO执行SQL Server存储过程时遇到问题:

如果$SQL中的参数与存储过程中的参数顺序不同,则值不会传递给相应的参数,而是传递给列表中的下一个参数:

这里有一个例子:

<?php
        $hostname   = '';
        $database   = '';
        $user       = '';
        $password = '';
        $DB = new PDO("sqlsrv:Server=".$hostname.";Database=".$database.";TransactionIsolation=".PDO::SQLSRV_TXN_READ_UNCOMMITTED, $user, $password);

        $p1='p1';
        $p2='p2';
        $p3='p3';

      $SQL="EXEC dbo.sp__TEST :p1,:p2,:p3";
      $rsx= $DB->prepare($SQL,[PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL]);
      $rsx->bindParam(':p1',$p1, PDO::PARAM_STR);
      $rsx->bindParam(':p3',$p3, PDO::PARAM_STR);
      $rsx->bindParam(':p2',$p2, PDO::PARAM_STR);
      $rsx->execute();
      $res=$rsx->fetch(PDO::FETCH_ASSOC);
      echo '<br>'.$res['result'];
?>
但如果我们将$SQL声明更改如下:

$SQL="EXEC dbo.sp__TEST :p1,:p3";
我们将获得以下输出:

p1=>p1
p2=>p3
p3=>
而我却希望

p1=>p1
p2=>
p3=>p3
这意味着,如果我需要更改/添加/删除某些参数,我必须始终检查这些参数的顺序是否正确,这是浪费时间

我是忘了什么还是

谢谢

对于那些投反对票的不明智的人: 如果您将声明更改为

$SQL="EXEC dbo.sp__TEST :p1,:p3,:p2";
您将得到以下结果:

p1=>p1
p2=>p3
p3=>p2
这是不对的:

此外,如果您使用其他语言(ASP、ASP.NET)调用存储过程,即使您洗牌参数或省略一些参数,它也会返回正确的结果 是的

ASP示例

<%
    dim cn,cst,cmd,p1,p2,p3,rsx 
    set cn=Server.CreateObject("ADODB.Connection") 
    cst="Provider=sqloledb;server=XXXXX;Database=yyyyy;User ID=sa;Password=zzzzz" 
    cn.CursorLocation = 3 
    cn.open cst 
    set cmd=Server.CreateObject("ADODB.Command") 
    set cmd.ActiveConnection= cn 

    p1="p1" 
    p2="p2" 
    p3="p3" 

    cmd.CommandText="dbo.sp__TEST" 
    cmd.CommandType=4 'adCmdStoredProc 
    cmd.Parameters("@p1")= p1 
    cmd.Parameters("@p2")= p2 
    cmd.Parameters("@p3")= p3 

    set rsx=cmd.execute() 
    if not rsx.eof then 
        response.write rsx("result") 
    end if 
%>

这与PHP无关

您的过程声明声明它接受3个参数:

CREATE PROCEDURE dbo.sp__TEST
(
    @p1     nvarchar(65)='',
    @p2     nvarchar(65)='',
    @p3     nvarchar(65)=''
)
但您的执行仅提供了2个:

$SQL="EXEC dbo.sp__TEST :p1,:p3"; // This is only supplying the first two parameters to your procedure
如果手动执行以下操作,则会得到相同的结果:

$SQL="EXEC dbo.sp__TEST 'hi!','hey!'"; // This is only supplying the first two parameters to your procedure

您需要将
:p2
绑定为空字符串以生成预期结果。

这与PHP函数的工作原理相同,
函数测试($a,$b)
然后
测试($b)
将有
$b
作为函数中的
$a
,并且
$b
将是未定义的。我不同意:即使我按如下方式更改声明,您也可能得到错误的解决方案:
$SQL=“EXEC dbo.sp\u TEST:p1,:p3,:p2”参数的顺序与存储过程中的顺序不同:我的意思是PHP/PDO不是将参数用于其名称,而是用于其位置:如果只检查位置,则命名参数的意义是什么。此外,例如,如果我在vbscript中调用此存储过程,并仅提供参数p1和p3,它会将值放在p1和p3上,而不是放在它的前两个参数上founds@JoePDO绑定的
:p1
声明对存储过程的
@p1
参数绝对没有意义。您可以将其命名为
@jumbo
并使用PHP绑定
:framework
,只要您正确地对参数排序,那么
@jumbo
将收到
:framework
的值。也许我的问题不太清楚,但这是:PHP PDO(用于SQL Server)正确吗不按参数的名称而是按其位置链接参数?考虑到在其他语言中,ASP参数
@p1
链接到StoredProcess
@p1
,无论它们的位置如何,我认为这本身就是一种奇怪的行为。感谢您的帮助answer@Joe你最近的评论是正确的。这就是PHP中参数绑定的工作方式。由于我不熟悉ASP,我不能同意也不能否认你关于ASP的说法,但我确实觉得你的说法很奇怪。如果您用简单的术语来考虑,那么听起来您需要知道参数名称才能使用它们?这听起来像是地狱般的体验,尤其是如果您有一个很大的代码库并在许多位置调用该存储过程。所以,如果你决定给你的参数起一个有意义的名字,那么你将破坏你的整个代码库?@Joe你能给我一个关于这个的文档链接吗?或者甚至是一个堆栈溢出的职位,提出您的索赔?想象一下,如果PHP强迫您知道函数使用的参数名,以便使用该函数。
$SQL="EXEC dbo.sp__TEST :p1,:p3"; // This is only supplying the first two parameters to your procedure
$SQL="EXEC dbo.sp__TEST 'hi!','hey!'"; // This is only supplying the first two parameters to your procedure