web-dev-qa-db-ja.com

sqlsrvと「?」を使用してPHPでストアドプロシージャを実行する方法スタイルパラメータ

(タイトルから)これと同じように見える他のいくつかの質問を見てきました。ただし、私の場合は少し異なります。

次のように動作します(つまり、 "成功"になり、データベースは、指定された変数を使用してプロシージャを実行したときに期待どおりに実行されます)。

$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内で直接動作すること、および上記の方法で呼び出された場合に確認しました。同様に、私はcan任意の生のクエリ(挿入、選択、更新、ストアドプロシージャなど)に対してパラメータ化されたクエリを使用することを確認しました。

だから、私の質問は、パラメータ化されたクエリを使用してストアドプロシージャを呼び出す方法と、クエリ文字列に変数を埋め込む方法ですか?

さらに重要なことに、私は実際に準備/実行を使用したいので、うまくいけば答えがこれも機能することを許可します。

10
LittleTreeX

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

12
chris85

これは、@ 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()を忘れると、使用する前に結果を実行する必要があるというエラーが表示されます。

9
AndyD273

これを設定してください。そうしないと、ストアドプロシージャにメッセージが返された場合に常にエラーが返されます。

sqlsrv_configure('WarningsReturnAsErrors',0);

//Full working code below

$sql = "{call NameOfDatabase.NameOfOwner.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));

}
0
David Northcutt