PHP多查询问题
我需要查询一个表,并使用该信息查询另一个表。最后,我需要在第一个表上运行一个查询,显示来自表和查询的结果 除了PHP多查询问题,php,mysql,Php,Mysql,我需要查询一个表,并使用该信息查询另一个表。最后,我需要在第一个表上运行一个查询,显示来自表和查询的结果 除了$summary=mysql\u result($y,$j,'WebDesc'),其他一切都正常工作相反,$sql3的响应正确,当我手动运行查询时,它会为WebDesc提取数据。我在手册中看到,mysql\u query不支持“多查询”,但我真的不知道这意味着什么。前两个查询($sql和$sql2)配合得很好,我还使用mysql\u query编写了多个查询的脚本 $sql = "SEL
$summary=mysql\u result($y,$j,'WebDesc'),其他一切都正常工作
相反,$sql3
的响应正确,当我手动运行查询时,它会为WebDesc
提取数据。我在手册中看到,mysql\u query
不支持“多查询”,但我真的不知道这意味着什么。前两个查询($sql
和$sql2
)配合得很好,我还使用mysql\u query
编写了多个查询的脚本
$sql = "SELECT * FROM T_AdditionalInfo WHERE Description LIKE '" . $page_title . "%'" . " AND (ProductType='FG8' OR ProductType='FG1') AND Active='Yes'";
$x = mysql_query($sql);
$table_data = "";
while ($result = mysql_fetch_array($x)) {
$kilnnum = $result['ItemNo'];
} //kilnnum should be set to ItemNo of last matching kiln
$sql2 = "SELECT * FROM T_Accessories WHERE KilnNo='$kilnnum'";
$x = mysql_query($sql2);
$rows = mysql_num_rows($x);
for ($j = 0 ; $j < 4 ; ++$j) //increment through 0-3 first 4 rows of data
{
$item_no = mysql_result($x,$j, 'PartNo'); //get PartNo from T_Accessories
$sql3 = "SELECT ItemNo,WebDesc FROM T_AdditionalInfo WHERE ItemNo='$item_no'"; //Pull data from T_AdditionalInfo for above PartNo/ItemNo
$y = mysql_query($sql3);
$title_w_spaces = mysql_result($x,$j, 'Description'); //Still pulling title from T_Accessories to match image names
$title = str_replace(" ", "-", $title_w_spaces); //Still using title for heading from T_Accessories
$summary = mysql_result($y,$j, 'WebDesc'); //Pulling description from T_AdditionalInfo
if ($title <> "") {
$table_data .= "
<div>
<h6> $title_w_spaces </h6>
<img src='/images/" . $title . ".jpg' alt='" . $title ."' title='" . $title . "' class='alignnone size-full' width='114' />
<p>" . $summary . "</p>
</div>";
} //end if
} //end for
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=“从T_AdditionalInfo中选择*$页面标题。"%'" . “和(ProductType='FG8'或ProductType='FG1')和Active='Yes'”;
$x=mysql\u查询($sql);
$table_data=“”;
而($result=mysql\u fetch\u数组($x)){
$kilnnum=$result['ItemNo'];
}//kilnnum应设置为最后一个匹配窑的ItemNo
$sql2=“从T_附件中选择*,其中KilnNo='$kilnnum';
$x=mysql\u查询($sql2);
$rows=mysql\u num\u rows($x);
对于($j=0;$j<4;++$j)//通过0-3前4行数据递增
{
$item_no=mysql_result($x,$j,'PartNo');//从T_附件获取PartNo
$sql3=“从T_AdditionalInfo中选择ItemNo,WebDesc,其中ItemNo='$item_no'”;//从T_AdditionalInfo中为上述PartNo/ItemNo提取数据
$y=mysql\u查询($sql3);
$title_w_spaces=mysql_result($x,$j,'Description');//仍然从T_附件中提取标题以匹配图像名称
$title=str_replace(“,”-“,$title_w_空格);//仍然使用title作为来自T_附件的标题
$summary=mysql\u result($y,$j,'WebDesc');//从T\u AdditionalInfo中提取描述
如果($title“”){
$table_数据=”
$title\u w\u空格
“$摘要。”
";
}//如果结束,则结束
}//结束
正如其他人所建议的那样,我还建议将您的多个选择组合成一个JOIN
语句。正如其他人所说,我建议使用or。这两种方法都将有效地帮助消除SQL注入,并防止您使用已弃用的代码,这些代码将在下一版本中删除
下面是一个关于如何重写查询和循环逻辑的示例(示例使用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());
}
}
示例
在每个示例中,假设以下内容
$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) 现在我知道了,我说过创建这个类会让一切变得更容易,因为它消除了准备
语句,绑定
参数,执行
语句,然后检索
结果集的所有重复性。下面是如何在一行中完成上述所有操作的快速示例
$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个ItemNo)
嵌套的select语句称为
子查询。
因为您指出您正在使用MySQL,所以下面是一个可能有用的语句。子查询在SQL中对于类似的事情非常有用,并且在子句中使用SELECT*FROM t1 WHERE id in(SELECT t1_id FROM t2)
看起来您需要了解SQL连接,以及如何通过使用参数化查询避免SQL注入。以及如何不使用mysql。新代码都应该使用mysqli或PDO。这是一种非常低效的方法,了解SQL连接,并且一定要使用PDO。关于连接的好建议:谢谢。你们都可以清楚地看出,我是一个相对的新手。我将把脚本转换到mysqli(我想我使用的是一个过时的源代码,尽管这本书是在2012年出版的!),并遵循手册中的示例来防止注入(现在处于开发模式)。有人能提供建设性的信息说明为什么$summary=mysql_result($y,$j,'WebDesc');没有将WebDesc字段值指定给$summary吗?非常感谢您提供的详细教程!实际上,我现在正忙于如何通过查询获得所需的数据。交易是在info
表中有多达4条不同的记录,它们将与我的标题WHERE
子句w/通配符匹配。每个记录将与acc
表中最多8个不同的记录匹配。基本上,info
中有4个型号/变体,每个型号/变体在acc
中都有相同的8个附件,但我只想显示这8个附件一次。我尝试了选择DISTINCT
,但这似乎只在我只选择一列时起作用。根据说明,但不包括info.WebDesc include.@Mark,非常欢迎您。这是我开始使用PDO
时希望得到的信息,所以我想我会分享它。如果我理解正确,您希望只显示附件
项?如果是这样,那么是的,你是正确的。如果您只需要符合给定标准的附件,则需要执行从…
中选择不同的附件说明。如果我有任何误解,请随意分享。访问。和戳。都在info
和Web中
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)