通过 PDO 将 & 号插入 SQL 表
Posted
技术标签:
【中文标题】通过 PDO 将 & 号插入 SQL 表【英文标题】:Inserting ampersand into SQL table through PDO 【发布时间】:2017-12-24 19:26:07 【问题描述】:我目前可以使用下面的 .php 将数据插入 SQL DB,但是如果数据包含一个 & 符号,它会将其视为 PHP 语句,并且 & 符号不会插入到数据库中。
比如我在work_carried_out字段中输入的数据是:
从 6 月 25 日起存档所有 spl 和 inp 来自 c:\versionone\dbcheck_1000\inbound_1000\DESPATCH\ & c:\versionone\dbcheck_1000\inbound_1000\DESPATCH\done 到 c:\Despatch 存档
这是写入表格的内容:
从 6 月 25 日起存档所有 spl 和 inp 来自 c:\versionone\dbcheck_1000\inbound_1000\DESPATCH\
数据库架构
CREATE TABLE [dbo].[server_log_entries](
[id] [int] IDENTITY(1,1) NOT NULL,
[start_date_time] [varchar](100) NOT NULL,
[finish_date_time] [varchar](100) NOT NULL,
[server_name] [varchar](50) NOT NULL,
[carried_out_by] [varchar](50) NOT NULL,
[verified_by] [varchar](50) NOT NULL,
[authorised_by] [varchar](50) NULL,
[work_carried_out] [varchar](max) NULL,
[work_verified] [varchar](max) NULL,
[change_reason] [varchar](max) NULL,
[perceived_impact] [varchar](max) NULL,
[rollback_process] [varchar](max) NULL,
CONSTRAINT [PK_server_log_entries] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
代码
// Get the form fields and remove whitespace
var_dump($_POST);
$datetime = trim($_POST["datetime"]);
$servername = trim($_POST["servername"]);
$carriedoutby = trim($_POST["carriedoutby"]);
$workverifiedby = trim($_POST["workverifiedby"]);
$authorisedby = trim($_POST["authorisedby"]);
$workcarriedout = trim($_POST["workcarriedout"]);
$howverified = trim($_POST["howverified"]);
$reason = trim($_POST["reason"]);
$impact = trim($_POST["impact"]);
$rollback = trim($_POST["rollback"]);
try
$db = new PDO(DB_DSN, DB_USERNAME, DB_PASSWORD);
catch (PDOException $e)
echo 'Connection failed: ' . $e->getMessage();
// Insert data into SQL table
$stmt = $db->prepare("INSERT INTO [dbo].[server_log_entries] (date_time, server_name, carried_out_by, verified_by, authorised_by, work_carried_out, work_verified, change_reason, perceived_impact, rollback_process)
values (:datetime,:servername,:carriedoutby,:workverifiedby,:authorisedby,:workcarriedout,:howverified,:reason,:impact,:rollback)");
$stmt->bindParam(':datetime', $datetime, PDO::PARAM_STR);
$stmt->bindParam(':servername', $servername, PDO::PARAM_STR);
$stmt->bindParam(':carriedoutby', $carriedoutby, PDO::PARAM_STR);
$stmt->bindParam(':workverifiedby', $workverifiedby, PDO::PARAM_STR);
$stmt->bindParam(':authorisedby', $authorisedby, PDO::PARAM_STR);
$stmt->bindParam(':workcarriedout', $workcarriedout, PDO::PARAM_STR);
$stmt->bindParam(':howverified', $howverified, PDO::PARAM_STR);
$stmt->bindParam(':reason', $reason, PDO::PARAM_STR);
$stmt->bindParam(':impact', $impact, PDO::PARAM_STR);
$stmt->bindParam(':rollback', $rollback, PDO::PARAM_STR);
$stmt->execute();
$db = null;
【问题讨论】:
“但是,如果数据包含 & 符号,它会将其视为 PHP 语句” - 那是哪个 POST 数组/列?您需要编辑您的帖子以包含它以供将来的用户使用,因为我们中的一些人可能还没有出现在问题中,等待回复。它的架构也是。 嗨@Fred-ii-这是本例中的工作执行列,我输入的信息是“从 6 月 25 日起归档所有来自 c:\versionone\dbcheck_1000\inbound_1000\DESPATCH\ 的 spl 和 inp & c:\versionone\dbcheck_1000\inbound_1000\DESPATCH\done to c:\Despatch Archive”,这是写入表的内容:“从 6 月 25 日起归档所有来自 c:\versionone\dbcheck_1000\inbound_1000\DESPATCH 的 spl 和 inp \" 你能告诉我们表格的架构吗?数据类型/长度等... 您确定问题出在这一端,而不是在发送数据的代码中吗?您的var_dump($_POST)
是否包含正确的数据?它来自表单、服务、应用程序吗?
嗨@MagnusEriksson - 我已将这个示例添加到您的原始帖子中
【参考方案1】:
注意:我使用 mysql 作为 RDBMS。
尽管看起来很奇怪,但问题是——我希望你的情况也是如此——SQL 语句由双引号 (") 分隔。用单引号 (') 替换它们。另外,请考虑如果您遇到反斜杠问题,请申请 PDO::quote
。
请注意,PDO 异常不仅会在创建连接时发出,还会由其他 PDO 函数(如 PDO::prepare
)发出。一般来说,最好检查每个函数的文档,以便找出返回/抛出的值和/或异常。
我做了一个完整的代码,我把它贴在这里;从异常/返回值处理的角度来看,您可能会发现一些有用的东西。您只需更改 DSN 和凭据以适合您的系统。作为个人选择,我使用了bindValue
而不是bindParam
。
祝你好运!
PDO预处理语句+异常处理:
index.php(主页)
<?php
require_once 'configs.php';
require_once 'functions.php';
require_once 'testFunctions.php';
// Activate error reporting (only on development).
activateErrorReporting();
// Get the form fields and remove whitespace
$datetime = trim($_POST["datetime"]);
$servername = trim($_POST["servername"]);
$carriedoutby = trim($_POST["carriedoutby"]);
$workverifiedby = trim($_POST["workverifiedby"]);
$authorisedby = trim($_POST["authorisedby"]);
$workcarriedout = trim($_POST["workcarriedout"]);
$howverified = trim($_POST["howverified"]);
$reason = trim($_POST["reason"]);
$impact = trim($_POST["impact"]);
$rollback = trim($_POST["rollback"]);
try
// Create db connection.
$connection = createConnection(
MYSQL_HOST
, MYSQL_DATABASE
, MYSQL_USERNAME
, MYSQL_PASSWORD
, MYSQL_PORT
, MYSQL_CHARSET
);
// Insert data.
$lastInsertId = insertData(
$connection
, $datetime
, $servername
, $carriedoutby
, $workverifiedby
, $authorisedby
, $workcarriedout
, $howverified
, $reason
, $impact
, $rollback
);
// Print data (for testing purposes).
printData($lastInsertId, TRUE);
// Fetch all data.
$fetchedLastInsertedData = fetchData($connection, $lastInsertId);
// For testing purposes.
printData($fetchedLastInsertedData, TRUE);
closeConnection($connection);
catch (PDOException $pdoException)
// On development.
printData($pdoException, TRUE);
// On production.
// echo $pdoException->getMessage();
exit();
catch (Exception $exception)
// On development.
printData($exception, TRUE);
// On production.
// echo $exception->getMessage();
exit();
testFunctions.php
<?php
/*
* ---------------------
* Test functions
* ---------------------
*/
/**
* Insert data.
*
* @param PDO $connection Connection instance.
* @param type $datetime
* @param type $servername
* @param type $carriedoutby
* @param type $workverifiedby
* @param type $authorisedby
* @param type $workcarriedout
* @param type $howverified
* @param type $reason
* @param type $impact
* @param type $rollback
* @return integer Last insert id.
* @throws Exception
*/
function insertData(
$connection
, $datetime
, $servername
, $carriedoutby
, $workverifiedby
, $authorisedby
, $workcarriedout
, $howverified
, $reason
, $impact
, $rollback
)
// Sql statement.
$sql = 'INSERT INTO [dbo].[server_log_entries] (
date_time,
server_name,
carried_out_by,
verified_by,
authorised_by,
work_carried_out,
work_verified,
change_reason,
perceived_impact,
rollback_process
) VALUES (
:datetime,
:servername,
:carriedoutby,
:workverifiedby,
:authorisedby,
:workcarriedout,
:howverified,
:reason,
:impact,
:rollback
)';
// Prepare and check sql statement (returns PDO statement).
$statement = $connection->prepare($sql);
if (!$statement)
throw new Exception('The SQL statement can not be prepared!');
// Bind values to sql statement parameters.
$statement->bindValue(':datetime', $datetime, getInputParameterDataType($datetime));
$statement->bindValue(':servername', $servername, getInputParameterDataType($servername));
$statement->bindValue(':carriedoutby', $carriedoutby, getInputParameterDataType($carriedoutby));
$statement->bindValue(':workverifiedby', $workverifiedby, getInputParameterDataType($workverifiedby));
$statement->bindValue(':authorisedby', $authorisedby, getInputParameterDataType($authorisedby));
$statement->bindValue(':workcarriedout', $workcarriedout, getInputParameterDataType($workcarriedout));
$statement->bindValue(':howverified', $howverified, getInputParameterDataType($howverified));
$statement->bindValue(':reason', $reason, getInputParameterDataType($reason));
$statement->bindValue(':impact', $impact, getInputParameterDataType($impact));
$statement->bindValue(':rollback', $rollback, getInputParameterDataType($rollback));
// Execute and check PDO statement.
if (!$statement->execute())
throw new Exception('The PDO statement can not be executed!');
// Get last insert id.
return $connection->lastInsertId();
/**
* Fetch data by id.
*
* @param PDO $connection Connection instance.
* @param integer $id Record id.
* @return array Fetched data.
* @throws Exception
*/
function fetchData($connection, $id)
// Sql statement.
$sql = 'SELECT *
FROM [dbo].[server_log_entries]
WHERE id = :id';
// Prepare and check sql statement (returns PDO statement).
$statement = $connection->prepare($sql);
if (!$statement)
throw new Exception('The SQL statement can not be prepared!');
// Bind values to sql statement parameters.
$statement->bindValue(':id', $id, getInputParameterDataType($id));
// Execute and check PDO statement.
if (!$statement->execute())
throw new Exception('The PDO statement can not be executed!');
// Fetch data.
$fetchedData = $statement->fetchAll(PDO::FETCH_ASSOC);
if ($fetchedData === FALSE)
throw new Exception('Fetching data failed!');
return $fetchedData;
configs.php
<?php
/*
* ----------------
* Database configs
* ----------------
*/
define('MYSQL_HOST', '...');
define('MYSQL_PORT', '3306');
define('MYSQL_DATABASE', '...');
define('MYSQL_CHARSET', 'utf8');
define('MYSQL_USERNAME', '...');
define('MYSQL_PASSWORD', '...');
functions.php
<?php
/*
* ---------------------
* Data access functions
* ---------------------
*/
/**
* Create a new db connection.
*
* @param string $host Host.
* @param string $dbname Database name.
* @param string $username Username.
* @param string $password Password.
* @param string $port [optional] Port.
* @param array $charset [optional] Character set.
* @param array $options [optional] Driver options.
* @return PDO Db connection.
*/
function createConnection($host, $dbname, $username, $password, $port = '3306', $charset = 'utf8', $options = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_PERSISTENT => true,
))
$dsn = getDsn($host, $dbname, $port, $charset);
$connection = new PDO($dsn, $username, $password);
foreach ($options as $key => $value)
$connection->setAttribute($key, $value);
return $connection;
/**
* Create a mysql DSN string.
*
* @param string $host Host.
* @param string $dbname Database name.
* @param string $port [optional] Port.
* @param array $charset [optional] Character set.
* @return string DSN string.
*/
function getDsn($host, $dbname, $port = '3306', $charset = 'utf8')
$dsn = sprintf('mysql:host=%s;port=%s;dbname=%s;charset=%s'
, $host
, $port
, $dbname
, $charset
);
return $dsn;
/**
* Close a db connection.
*
* @param PDO $connection Db connection.
* @return void
*/
function closeConnection($connection)
$connection = NULL;
/**
* Get the data type of a binding value.
*
* @param mixed $value Binding value.
* @return mixed Data type of the binding value.
*/
function getInputParameterDataType($value)
$dataType = PDO::PARAM_STR;
if (is_int($value))
$dataType = PDO::PARAM_INT;
elseif (is_bool($value))
$dataType = PDO::PARAM_BOOL;
return $dataType;
/*
* ---------------
* Print functions
* ---------------
*/
/**
* Print data on screen.
*
* @param mixed $data Data to print.
* @param bool $preformatted Print preformatted if TRUE, print normal otherwise.
* @return void
*/
function printData($data, $preformatted = FALSE)
if ($preformatted)
echo '<pre>' . print_r($data, true) . '</pre>';
else
echo $data;
/*
* -------------------------
* Error reporting functions
* -------------------------
*/
/**
* Toggle error reporting.
*
* @param integer $level Error level.
* @param bool $displayErrors Display errors if TRUE, hide them otherwise.
* @return void
*/
function activateErrorReporting($level = E_ALL, $displayErrors = TRUE)
error_reporting($level);
ini_set('display_errors', ($displayErrors ? 1 : 0));
【讨论】:
对于我的问题downvote(d)的用户:请让我知道你downvote的动机,以便我可以相应地更改我的答案。通过这种方式,我们可以共同为本网站的持续改进做出贡献。谢谢。以上是关于通过 PDO 将 & 号插入 SQL 表的主要内容,如果未能解决你的问题,请参考以下文章