【问题标题】:PHP PDO with MSSQL does not reuse prepared statement带有 MSSQL 的 PHP PDO 不重用准备好的语句
【发布时间】:2018-05-08 21:29:28
【问题描述】:

我有带有 pdo_sqlsrv 扩展的 PHP 5.3 和一个 MSSQL2008 数据库。以下代码使用准备好的语句从表中检索数据,一切正常。但是,当我多次重复该语句时,在 SQL Server 配置文件中我可以看到准备好的语句没有被重用。在每个 SQL 请求上,都会再次准备语句。

    $this->statement = $connection->prepare("SELECT Lang,MemoryArea,ID,TextType,TextValue FROM CoreLanguage WHERE TextType = :textType;");
    $this->statement->bindValue(":textType", "URL");
    $this->statement->execute();
    $data = $this->statement->fetchAll(PDO::FETCH_ASSOC) or array();
    $this->statement->closeCursor();


    $this->statement->bindValue(":textType", "SYSTEM");
    $this->statement->execute();
    $data = $this->statement->fetchAll(PDO::FETCH_ASSOC) or array();
    $this->statement->closeCursor();

这种行为的原因可能是变量 $textType 的字符串长度不同。正如您在分析器列表中看到的那样,使用不同的输入参数数据类型(nvarchar(6) 和 nvarchar(3))准备了两次相同的语句。

这些数据请求的 SQL Server Profiler 日志条目:

declare @p1 int
set @p1=2
exec sp_prepexec @p1 output,N'@P1 nvarchar(3)',N'SELECT Lang,MemoryArea,ID,TextType,TextValue FROM CoreLanguage WHERE TextType = @P1;',N'URL'
select @p1

declare @p1 int
set @p1=3
exec sp_prepexec @p1 output,N'@P1 nvarchar(6)',N'SELECT Lang,MemoryArea,ID,TextType,TextValue FROM CoreLanguage WHERE TextType = @P1;',N'SYSTEM'
select @p1

如果输入字符串数据的长度始终相同,则 SQL 服务器会重用该语句。但是,这种情况很少发生......

有谁知道为什么 SQL 服务器不重用已经准备好的语句?或者我如何将输入参数 @P1 操作为合适的数据类型,例如 nvarchar(40)(与 TextType 列定义相同)?

也许我错过了一个特定于驱动程序的选项?

【问题讨论】:

  • 您可以尝试将PDO属性PDO::ATTR_EMULATE_PREPARES设置为false。
  • 我现在尝试在准备语句之前设置属性:$connection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); 这并没有改变结果。关键是它可以工作,但前提是参数字符串长度完全相同。否则,由于@P1 的参数长度不同,它会创建一个新的预处理语句。

标签: php sql-server-2008 pdo


【解决方案1】:

您是否尝试过使用 bindParam() 而不是 bindValue()?也许你可以试试。

【讨论】:

  • 是的,我已经尝试过使用 bindParam 及其第三个参数 PDO::PARAM_STR。 sql server上的结果是一样的。
猜你喜欢
  • 2010-11-30
  • 2017-03-13
  • 2010-11-05
  • 1970-01-01
  • 1970-01-01
  • 2012-10-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多