在MySQLi中select* FROM

我的网站是相当广泛的,我最近刚刚切换到PHP5(称我是一个晚布卢姆)。

我之前的所有MySQL查询都是这样构build的:

"SELECT * FROM tablename WHERE field1 = 'value' && field2 = 'value2'"; 

这使得它非常简单,友好。

我现在正在尝试切换到mysqli出于明显的安全原因,我很难搞清楚当bind_param需要特定参数时如何实现相同的SELECT * FROM查询。

这种说法是过去的事情吗?

如果是这样,我如何处理涉及大量列的查询? 我真的需要每次input它们吗?

 "SELECT * FROM tablename WHERE field1 = 'value' && field2 = 'value2'"; 

 "SELECT * FROM tablename WHERE field1 = ? && field2 = ?"; 

它传递给$mysqli::prepare

 $stmt = $mysqli->prepare( "SELECT * FROM tablename WHERE field1 = ? && field2 = ?"); $stmt->bind_param( "ss", $value, $value2); // "ss' is a format string, each "s" means string $stmt->execute(); $stmt->bind_result($col1, $col2); // then fetch and close the statement 

OP评论:

所以如果我有5个参数,我可能有“sssis”或什么东西(取决于input的types?)

正确的,一个types说明符? 参数在准备好的语句中,它们全都是位置的(第一个说明符适用于第一个?它被第一个实际参数(这是bind_param的第二个参数)replace)。

mysqli会照顾转义和引用(我认为)。

这已经是一个月前了,不过哦。

我可能是错的,但是对于你的问题,我感觉到bind_param在这里并不是真正的问题。 你总是需要定义一些条件,直接在查询string本身,使用bind_param来设置? 占位符。 这不是一个真正的问题。

我使用MySQLi SELECT *查询的问题是bind_result部分。 这就是它变得有趣的地方。 我碰到Jeffrey Way的这篇文章: http : //jeff-way.com/2009/05/27/tricky-prepared-statements/ (这个链接不再有效)。 该脚本基本上循环遍历结果并将其作为数组返回 – 不需要知道有多less列,而且您仍然可以使用预准备语句。

在这种情况下,它看起来像这样:

 $stmt = $mysqli->prepare( 'SELECT * FROM tablename WHERE field1 = ? AND field2 = ?'); $stmt->bind_param('ss', $value, $value2); $stmt->execute(); 

然后使用该网站的片段:

 $meta = $stmt->result_metadata(); while ($field = $meta->fetch_field()) { $parameters[] = &$row[$field->name]; } call_user_func_array(array($stmt, 'bind_result'), $parameters); while ($stmt->fetch()) { foreach($row as $key => $val) { $x[$key] = $val; } $results[] = $x; } 

$results现在包含来自SELECT *所有信息。 到目前为止,我发现这是一个理想的解决scheme。

在切换时,切换到PDO而不是mysqli,它可以帮助您编写数据库agnositc代码,并为预编译语句提供更好的function。

http://www.php.net/pdo

用于PDO的Bindparam: http ://se.php.net/manual/en/pdostatement.bindparam.php

 $sth = $dbh->prepare("SELECT * FROM tablename WHERE field1 = :value1 && field2 = :value2"); $sth->bindParam(':value1', 'foo'); $sth->bindParam(':value2', 'bar'); $sth->execute(); 

要么:

 $sth = $dbh->prepare("SELECT * FROM tablename WHERE field1 = ? && field2 = ?"); $sth->bindParam(1, 'foo'); $sth->bindParam(2, 'bar'); $sth->execute(); 

或者以数组的forms执行:

 $sth = $dbh->prepare("SELECT * FROM tablename WHERE field1 = :value1 && field2 = :value2"); $sth->execute(array(':value1' => 'foo' , ':value2' => 'bar')); 

如果您希望您的应用程序能够在将来运行在不同的数据库上,那将会更容易。

我也认为你应该投入一些时间来使用Zend Framwework的一些类,同时使用PDO。 看看他们的Zend_Db ,更具体的是[Zend_Db_Factory] ​​[2]。 您不必使用所有的框架或将您的应用程序转换为MVC模式,但使用该框架并阅读它是花费时间。

你仍然可以使用它(mysqli只是与服务器通信的另一种方式,SQL语言本身是扩展的,没有改变)。 准备好的陈述是更安全的 – 因为你不需要经历每次正确地逃脱你的价值的麻烦。 如果你愿意的话,你可以把它们留在原来的位置,但是如果你切换的话,sql捎带的风险会降低。

这种说法是过去的事情吗?

是。 不要使用SELECT * ; 这是一个维修噩梦。 有很多其他的线程关于为什么这个构造是坏的,以及如何避免它会帮助你写更好的查询。

也可以看看:

  • 什么是不使用select *的原因?
  • 使用SELECT *时的性能问题?
  • 为什么使用'*'来build立一个视图不好?

我正在寻找一个很好的完整的例子,如何将多个查询参数dynamic地绑定到任何SELECT,INSERT,UPDATE和DELETE查询。 Alec在他的回答中提到了如何绑定结果的方法,对于我来说,SELECT查询的execute()函数后面的get_result()方法工作得很好,并且能够将所有选定的结果检索到一个关联数组数组中。

无论如何,我最终创build了一个函数,可以将任意数量的参数dynamic绑定到参数化查询(使用call_user_func_array函数),并获得查询执行的结果。 下面是它的文档function(请在使用之前阅读它 – 特别是$ paremetersTypes – types说明字符参数是重要的了解)

  /** * Prepares and executes a parametrized QUERY (SELECT, INSERT, UPDATE, DELETE) * * @param[in] $dbConnection mysqli database connection to be used for query execution * @param[in] $dbQuery parametrized query to be bind parameters for and then execute * @param[in] $isDMQ boolean value, should be set to TRUE for (DELETE, INSERT, UPDATE - Data manipulaiton queries), FALSE for SELECT queries * @param[in] $paremetersTypes String representation for input parametrs' types as per http://php.net/manual/en/mysqli-stmt.bind-param.php * @param[in] $errorOut A variable to be passed by reference where a string representation of an error will be present if a FAUILURE occurs * @param[in] $arrayOfParemetersToBind Parameters to be bind to the parametrized query, parameters need to be specified in an array in the correct order * @return array of feched records associative arrays for SELECT query on SUCCESS, TRUE for INSERT, UPDATE, DELETE queries on SUCCESS, on FAIL sets the error and returns NULL */ function ExecuteMySQLParametrizedQuery($dbConnection, $dbQuery, $isDMQ, $paremetersTypes, &$errorOut, $arrayOfParemetersToBind) { $stmt = $dbConnection->prepare($dbQuery); $outValue = NULL; if ($stmt === FALSE) $errorOut = 'Failed to prepare statement for query: ' . $dbQuery; else if ( call_user_func_array(array($stmt, "bind_param"), array_merge(array($paremetersTypes), $arrayOfParemetersToBind)) === FALSE) $errorOut = 'Failed to bind required parameters to query: ' . $dbQuery . ' , parameters :' . json_encode($arrayOfParemetersToBind); else if (!$stmt->execute()) $errorOut = "Failed to execute query [$dbQuery] , erorr:" . $stmt->error; else { if ($isDMQ) $outValue = TRUE; else { $result = $stmt->get_result(); if ($result === FALSE) $errorOut = 'Failed to obtain result from statement for query ' . $dbQuery; else $outValue = $result->fetch_all(MYSQLI_ASSOC); } } $stmt->close(); return $outValue; } 

用法:

  $param1 = "128989"; $param2 = "some passcode"; $insertQuery = "INSERT INTO Cards (Serial, UserPin) VALUES (?, ?)"; $rowsInserted = ExecuteMySQLParametrizedQuery($dbConnection, $insertQuery, TRUE, 'ss', $errorOut, array(&$param1, &$param2) ); // Make sure the parameters in an array are passed by reference if ($rowsInserted === NULL) echo 'error ' . $errorOut; else echo "successfully inserted row"; $selectQuery = "SELECT CardID FROM Cards WHERE Serial like ? AND UserPin like ?"; $arrayOfCardIDs = ExecuteMySQLParametrizedQuery($dbConnection, $selectQuery, FALSE, 'ss', $errorOut, array(&$param1, &$param2) ); // Make sure the parameters in an array are passed by reference if ($arrayOfCardIDs === NULL) echo 'error ' . $errorOut; else { echo 'obtained result array of ' . count($arrayOfCardIDs) . 'selected rows'; if (count($arrayOfCardIDs) > 0) echo 'obtained card id = ' . $arrayOfCardIDs[0]['CardID']; } 

你可以在语句中使用get_result()

http://php.net/manual/en/mysqli-stmt.get-result.php