问题
I have a helper library in app/Lib
that needs to store a log so I'm trying DboSource::rawQuery()
. Docs are pretty vague:
/**
* Executes given SQL statement.
*
* @param string $sql SQL statement
* @param array $params Additional options for the query.
* @return bool
*/
public function rawQuery($sql, $params = array()) {
$this->took = $this->numRows = false;
return $this->execute($sql, $params);
}
... and any example I find online pretends that SQL injection does not exist. No matter what syntax I try:
public function log (DataSource $db) {
$sql = 'INSERT INTO log (foo, bar)
VALUES (:foo, :bar)';
$params = array(
'foo' => 'One',
'bar' => 'Two',
);
$db->rawQuery($sql, $params);
}
... I always get database errors like this:
SQLSTATE[42000]: [Microsoft][ODBC Driver 11 for SQL Server][SQL Server]Incorrect syntax near ':'.
I've also tried positional place-holders (?
) and even PDO-like params (with PDO::PARAM_STR
and all the stuff).
What's the syntax to run a parametrised raw query in CakePHP/2.5.5 against SQL Server?
回答1:
Answer is (apparently): none.
In the source code for Sqlserver::_execute() we can read:
/**
* Executes given SQL statement.
*
* @param string $sql SQL statement
* @param array $params list of params to be bound to query (supported only in select)
* @param array $prepareOptions Options to be used in the prepare statement
* @return mixed PDOStatement if query executes with no problem, true as the result of a successful, false on error
* query returning no rows, such as a CREATE statement, false otherwise
* @throws PDOException
*/
So you can only use prepared statements on reading, not on writing :-!
You need to get back to the early 2000s and escape:
public function log (DataSource $db) {
$sql = sprintf('INSERT INTO log (foo, bar)
VALUES (%s, %s)',
$db->value('foo'),
$db->value('bar')
);
$db->rawQuery($sql);
}
来源:https://stackoverflow.com/questions/45859985/raw-insert-query-with-prepared-statements