我正在使用来自SQL Server和MySQL的两个相同的表,而我的最终目标是能够通过PHP同步它们的内容。我对此做了previous post,发现我的代码无法正常工作的原因是单引号弄乱了我的SQL语法。然后,我将表转换为使用PDO,因为我听说通过它准备语句/绑定参数更有效。但是,我的代码仍无法正确转义单引号。我已经研究过过去的帖子,但是都没有解决我的问题。这是代码:
<?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”,因此由于单引号而给我一个错误。我收到的错误是
错误:SQLSTATE [42000]:语法错误或访问冲突:1064 SQL语法有错误;检查与您的MariaDB服务器版本相对应的手册,以获取在's'AND Address ='IDK'附近使用的正确语法
这几乎告诉我,我没有转义单引号。
任何想法都值得赞赏!
答案 0 :(得分:3)
问题不在于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 = 'email@example.com'
为便于记录,应始终将占位符用于您在代码中未控制的任何值。即使是用于SELECT
语句或您信任的数据源。这样可以防止意外注入并处理任何类型的字符。