正如其他人所建议的那样,我还建议将您的多个选择组合成一个JOIN
语句。正如其他人所说,我建议使用mysqli或PDO。这两种方法都将有效地帮助消除 SQL 注入,并防止您使用已经存在deprecated
以及将在下一个版本中删除的代码。
这是一个关于如何重写查询和循环逻辑的示例(示例使用 PDO,因为我使用 mysqli 已经有一段时间了)。我想我可能错过了连接的一部分,因为我不是 100% 确定你的表之间的关联是什么。
$sql = "
SELECT
Description,
WebDesc
FROM T_AdditionalInfo info JOIN T_Accessories acc ON info.ItemNo = acc.PartNo
WHERE info.Description LIKE :title
";
$db = false;
$table_date = '';
try {
$db = new PDO(...);
}
catch(PDOException $e) {
$db = false
//Failed to connect to DB for some reason
}
if($db !== false) { //Did we connect?
if(($stmt = $db->prepare($sql)) !== false) { //Prepare the statement
$stmt->bindParam(':title', '%abc%'); //Bind the parameter
if($stmt->execute() !== false) { //Execute the statement
while($row = $stmt->fetch(PDO::FETCH_ASSOC)) { //Loop through the result set
$table_w_spaces = $row['Description']; //Get title
$title = str_replace(' ', '-', $title_w_spaces); //alter title
$table_date .= "
<div>
<h6>{$table_w_spaces}</h6>
<img src="/images/{$title}.jpg" alt="{$title}" title="{$title}" class="alignnone size-full" width="114" />
<p>{$row['WebDesc']}</p>
</div>
";
}
}
else {
//Execution of statement failed
print_r($stmt->errorInfo());
}
}
else {
//An error occurred when preparing SQL statement, probably a SQL error
print_r($stmt->errorInfo());
}
}
这可能是我有点超前了,但我猜你可能会经常做这样的事情。一旦您熟悉了 PDO 或 mysqli,创建一个类以消除大量重复性任务可能会有所帮助。此外,如果您应该更改到另一台数据库服务器(从 MySql、PostGre 或 MSSQL),甚至更改您的服务器名称,那么它就在一个地方并且很容易更改。如果下面的示例类起初看起来有点混乱,请不要担心。请参阅下面的示例,它应该变得清晰。它基本上是一种去掉所有重复性任务并将它们集成到两个特定功能executeQuery
和executeNonQuery
.
class Database {
private $db = false;
private $connected = false;
public function __construct($db = 'DefaultDBName', $username = 'MyUser', $password = 'MyPassword') {
$this->connect($db, $username, $password); //Auto connect when you create a new database
}
/**
* Connect to a database
*
* @param $db The database to connect to; default is DefaultDBName
* @param $username The username to connect as; default is MyUser
* @param $password The password to use when connecting; default is MyPassword
* @return True/False if the connection was successfull
*/
public function connect($db = 'DefaultDBName', $username = 'MyUser', $password = 'MyPassword') {
try {
$this->db = new PDO('drivername:Server=MYDBSERVER;Database=' . $db, $username, $password); //Create new connection
$this->connected = true; //We are connected
}
catch(PDOException $e) { //Oh no. An error
$this->db = false; //Set DB back to false, just in case
$this->connected = false; //We couldn't connect
//You can do something with the error message if you wish
}
return $this->connected
}
/**
* Prepares a SQL statement for execution
*
* @param $sql The SQL string to be prepared
* @params $params An optional array of parameters to bind to the statement
* @return The prepared statement; false if failed
*/
public function prepare($sql, $params = array()) {
$stmt = false;
if($this->connected) { //Are we connected
if(($stmt = $this->db->prepare($sql)) !== false) { //Prepare the statement
foreach($params as $param => $value) { //Bind the parameters
$stmt->bindValue($param, $value);
}
}
else {
//You can do something with $stmt->errorInfo();
}
}
return $stmt;
}
/**
* Execute a prepared statement
*
* @param $stmt A PDO statement
* @param $params An optional array of parameter values
* @return True/False
*/
public function execute($stmt, $params = array()) {
if($this->connected) { //Are we connected
if(!empty($params)) { //Can't bind an empty array of parameters
$result = $stmt->execute($params); //Execute with parameters
}
else {
$result = $stmt->execute(); //Execute without parameters
}
}
return $result;
}
/**
* Gets the results from an executed statement
*
* @param $stmt A reference to a PDO statement
* @return An array of results from the statement
*/
public function getResults($stmt) {
$results = array();
if($stmt !== false) { //Make sure we have a valid statement
while($row = $stmt->fetch(PDO::FETCH_ASSOC))) { //Get all of the data for the row
$results[] = $row; //Add the row to the results array
}
}
return $results; //Return the results
}
/**
* Executes a query and returns the results
*
* @param $sql The SQL query
* @param $parameters An array of parameters
* @return An array of results or false if execution failed
*/
public function executeQuery($sql, $params = array()) {
$results = false;
if($this->connected) { //Are we connected
if(($stmt = $this->prepare($sql, $params)) !== false) { //Prepare the statement
if($this->execute($stmt) !== false) { //Execute the statement
$results = $this->getResults($stmt); //Get the result set
}
}
}
return $results;
}
/**
* Executes a query, but returns no results
*
* @param $sql The SQL query
* @param $parameters An optional array of paraters
* @return True/False
*/
public function executeNonQuery($sql, $params = array()) {
$success = false;
if($this->connected) { //Are we connected
if(($stmt = $this->prepare($sql, $params)) !== false) { //Prepare the statement
if($this->execute($stmt) !== false) { //Execute the statement
$success = true; //Successfully executed
}
}
}
return $success;
}
}
例子
在每个示例中,假设以下
$sql = "
SELECT
Description,
WebDesc
FROM T_AdditionalInfo info JOIN T_Accessories acc ON info.ItemNo = acc.PartNo
WHERE info.Description LIKE :title
";
$parameters = array(':title' => '%abc%');
1)使用新的数据库类将它们放在一起
$db = new Database();
if(($stmt = $db->prepare($sql, $parameters)) !== false) {
if($db->execute($stmt)) {
$results = $db->getResults($stmt);
foreach($results as $result) {
//Do something with this result
}
}
}
2) 现在我知道我说过创建这个类将通过消除preparing
语句、binding
参数、executing
语句以及retrieving
结果集的所有重复性来使一切变得更容易。下面是一个快速示例,说明如何在一行中完成上述所有操作。
$db = new Database();
if(($results = $db->executeQuery($sql, $parameters)) !== false) {
foreach($results as $result) {
//Do something with this result
}
}
3) 但是我想使用的不返回结果集的查询呢?我仍然可以快速执行语句而不会造成混乱吗?是的。您可以使用该executeNonQuery
功能。下面是一个例子。
$db = new Database();
$sql = 'update table1 set field = :value where id = :id';
$parameters = array(':value' => 'val1', ':id' => '5');
if($db->executeNonQuery($sql, $parameters)) {
//Yay! The update was successfull
}
更新
根据我与 OP 的对话(见评论),这是他的查询的更新版本,应该会得到预期的结果。LIMIT 1
查询部分确保只使用一个,ItemNo
它应该只给出正在寻找的 8 个附件,而不是全部 32 个(8 个附件 X 4 个项目编号)。
SELECT
info.Description,
acc.WebDesc
FROM T_AdditionalInfo info JOIN T_Accessories acc ON info.ItemNo = acc.PartNo
WHERE info.ItemNo = (SELECT ItemNo FROM T_AdditionalInfo WHERE Description LIKE %abc% LIMIT 1)
嵌套的 select 语句称为 asubquery.
由于您表明您使用的是 MySQL,因此这里有一个您可能会发现有用的参考页面。子查询在 SQL 中对于这样的事情以及使用IN
子句非常有用SELECT * FROM t1 WHERE id IN (SELECT t1_id FROM t2)
。