Как выполнить хранимую процедуру в php с помощью sqlsrv и "?" параметры стиля
Я просмотрел несколько других вопросов, которые кажутся (из названий) такими же, как это. Однако мой случай немного отличается.
Следующие работы (т.е. я получаю "успех", и моя база данных выполняет то, что я ожидаю при запуске процедуры с заданными переменными):
$sql = "MyDB.dbo.myProcedure {$var1}, {$var2}, {$var3}";
$result = sqlsrv_query($myConn, $sql);
if (!$result) {
echo 'Your code is fail.';
}
else {
echo 'Success!';
}
Я хочу избежать (или уменьшить вероятность) SQL-инъекции, создав строку SQL, используя параметры. Например:
$sql = "select * from aTable where col1 = ? AND col2 = ?";
$result = sqlsrv_query($myConn, $sql, array($var1, $var2));
//please note. This code WILL work!
Но когда я делаю это с помощью хранимой процедуры, он терпит неудачу. Он терпит неудачу, не сообщая об ошибках через sqlsrv_errors(), никаких действий в базе данных и $result === false
.
Чтобы быть ясным, выполняется следующее:
$sql = "MyDB.dbo.myProcedure ?, ?, ?";
$result = sqlsrv_query($myConn, $sql, array($var1, $var2, $var3));
Аналогично созданный таким же образом оператор prepare/execute также завершится неудачей:
$sql = "MyDB.dbo.myProcedure ?, ?, ?";
$stmt = sqlsrv_prepare($myConn, $sql, array(&$var1, &$var2, &$var3));
foreach($someArray as $key => $var3) {
if(sqlsrv_execute($stmt) === false) {
echo 'mucho fail.';
}
}
//this code also fails.
Для полноты, я подтвердил, что хранимая процедура, о которой идет речь, работает непосредственно в SQL Management Studio И если называется так, как я упоминал выше. Аналогично, я подтвердил, что я может использовать параметризованные запросы для любого необработанного запроса (например, вставка, выбор, обновление и хранимая процедура).
Итак, мой вопрос заключается в том, как я могу вызвать хранимую процедуру с использованием параметризованного запроса и встраивания переменных в строку запроса?
Что еще более важно, я действительно хочу использовать команду prepare/execute, поэтому, надеюсь, ответ позволит этому и работать.
Ответы
Ответ 1
Вклад пользователя на php.net записывается в том, как выполнять хранимую процедуру с помощью sqlsrv-prepare.
В случае удаления из вклада пользователя php.net в будущем вот что было (указано):
$procedure_params = array(
array(&$myparams['Item_ID'], SQLSRV_PARAM_OUT),
array(&$myparams['Item_Name'], SQLSRV_PARAM_OUT)
);
// EXEC the procedure, {call stp_Create_Item (@Item_ID = ?, @Item_Name = ?)} seems to fail with various errors in my experiments
$sql = "EXEC stp_Create_Item @Item_ID = ?, @Item_Name = ?";
$stmt = sqlsrv_prepare($conn, $sql, $procedure_params);
Здесь страница руководства, http://php.net/manual/en/function.sqlsrv-prepare.php
Ответ 2
Это продолжение ответа от @chris85.
Здесь стоит отметить, что как только инструкция подготовлена, вам необходимо выполнить ее:
$sql = "EXEC stp_Create_Item @Item_ID = ?, @Item_Name = ?";
$stmt = sqlsrv_prepare($conn, $sql, $procedure_params);
if (!sqlsrv_execute($stmt)) {
echo "Your code is fail!";
die;
}
while($row = sqlsrv_fetch_array($stmt)){
//Stuff
}
sqlsrv_execute()
возвращает только true/false. Если вы хотите проанализировать данные, возвращаемые хранимой процедурой, вы можете обработать ее так же, как результат sqlsrv_query()
.
Если вы забудете sqlsrv_execute()
вы получите сообщение о том, что результат должен быть выполнен до того, как его можно будет использовать.
Ответ 3
Убедитесь, что вы установили это, иначе вы всегда будете получать ошибки, если хранимая процедура имеет возвращаемые сообщения.
sqlsrv_configure('WarningsReturnAsErrors',0);
$sql = "{call database.owner.StoredProcedureName(?,?)}";
$params = array($param1, $param2);
if ($stmt = sqlsrv_prepare($conn, $sql, $params)) {
echo "Statement prepared.<br><br>\n";
} else {
echo "Statement could not be prepared.\n";
die(print_r(sqlsrv_errors(), true));
}
if( sqlsrv_execute( $stmt ) === false ) {
die( print_r( sqlsrv_errors(), true));
}else{
print_r(sqlsrv_fetch_array($stmt));
}