php - 即使在 PDO 准备语句和绑定(bind)参数之后也无法转义数组内的单引号

标签 php mysql sql

我正在使用来自 SQL Server 和 MySQL 的两个相同的表,我的最终目标是能够通过 PHP 同步它们的内容。我做了一个previous post关于这一点,我发现我的代码无法工作的原因是单引号搞乱了我的 SQL 语法。然后我将表转换为使用 PDO,因为我听说通过它准备语句/绑定(bind)参数效率更高。但是,我的代码仍然无法正确转义单引号。我已经查看了过去的帖子,但没有一个能解决我的问题。这是代码:

<?php

$serverName = "<servername>";
$connectionInfo_mssql = array("Database"=>"<dbname>", "CharacterSet"=>"UTF-8");

try
  {
    $conn_mssql = new PDO("sqlsrv:Server=$serverName;Database=<dbname>");
    $conn_mssql->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $conn_mysql = new PDO("mysql:host=localhost;dbname=<dbname>", "", "");
    $conn_mysql->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);


    //SELECT FROM SQL SERVER DB
    $mssql_array = array();
    $mssql_query = $conn_mssql->prepare("SELECT * FROM Customers");
    $mssql_query->execute();

    while($row = $mssql_query->fetch(PDO::FETCH_BOTH))
    {

      $mssql_array[] = array('ID' => $row['ID'], 
                             'Name' => $row["Name"], 
                             'Address' => $row['Address'], 
                             'Email' => $row['Email']);

    }

    foreach($mssql_array as $key => $value)
    {

       //SELECT FROM MySQL DB
       $mysql_query = $conn_mysql->prepare("SELECT COUNT(*) FROM Customers WHERE ID ='".$value['ID']."' 
                                                        AND Name = '".$value["Name"]."' 
                                                        AND Address = '".$value['Address']."' 
                                                        AND Email = '".$value['Email']."' ");
       $mysql_query->execute();
       $num_rows = $mysql_query->fetchColumn();

       if ($num_rows == 0)
                       {
                         //INSERT INTO MySQL DB
                         $sql = $conn_mysql->prepare("INSERT INTO Customers VALUES (:ID, :Name, :Address, :Email)");

                         $params = array(':ID' => $value["ID"], ':Name' => $value["Name"], ':Address' => $value["Address"], ':Email' => $value["Email"]); 
                         $sql->execute($params); //this is where the error occurs
                       }
    }

    echo 'Table Customers from MS SQL DB and table Customers from MySQL DB are now synced!'."<br>";
    echo "<a href='table_updater.php'>Go back to updater</a>";

  }
catch(PDOException $e)
  {
    echo "Error: " . $e->getMessage();
  }

?>

这基本上所做的就是选择 SQL Server 表的所有内容并将其放入 MySQL 中,但由于我的其中一行的值为“Jojo's”,因此由于单引号,它只会给我一个错误。我收到的错误是

Error: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 's' AND Address = 'IDK''

这几乎告诉我,我没有逃避单引号。

非常感谢任何想法!

最佳答案

问题不在于 INSERT 语句,而在于 SELECT 语句。从错误中您可以看到它无法解释选择查询的一部分。所以正确的代码应该是这样的:

//SELECT FROM MySQL DB
$mysql_query = $conn_mysql->prepare("SELECT COUNT(*) FROM Customers WHERE ID = :ID
                                                        AND Name = :Name
                                                        AND Address = :Address
                                                        AND Email = :Email ");

$params = [':ID' => $value['ID'], ':Name' => $value['Name'], ':Address' => $value['Address'], ':Email' => $value['Email']];
$mysql_query->execute($params);

为了进一步解释,如果没有占位符,如果名称中包含引号,您的选择查询可能如下所示:

SELECT COUNT(*) FROM Customers WHERE ID = '123'
                            AND Name = 'As'd, dfg'        # <- Problem here
                            AND Address = 'some address'
                            AND Email = '<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="355058545c5975504d54584559501b565a58" rel="noreferrer noopener nofollow">[email protected]</a>'

郑重声明,您应该始终对代码中无法控制的任何值使用占位符。即使这是针对 SELECT 语句或您信任的数据源。这可以防止意外注入(inject)并处理任何类型的字符。

关于php - 即使在 PDO 准备语句和绑定(bind)参数之后也无法转义数组内的单引号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55809899/

相关文章:

php - FPDF - 在多单元格中写入 HTML?

php - Facebook access_token 无效

php - 当用户向下滚动页面时从数据库延迟加载(类似于 Twitter 和 Facebook)

javascript - 如何将data-id发送到另一个页面

php - 删除数据库中表行的代码将不起作用

mysql - 编写涉及来自三个表的有序数据的 MySQL 查询时遇到问题

mysql - Eloquent sum 参数 db 问题

php - 旧 MySQL 中的错误查询

c# - 如何编写 linq 语句来获取一组记录中的最后一条记录

java - 未映射的 POJO 在 native 查询的结果异常中用作类类型