3

laravel のストアド プロシージャから複数の結果セットをフェッチしたい。これを行う方法はありますか?現在、以下のコードを使用して単一行のデータを取得できます。

$result = DB::statement('CALL user_login(' . $userId . ',"'
                                                              . $password . '",'
                                                              . '@success'.','
                                                              . '@first_Name'
                                                              );

$res = DB::select('select @success AS success, @first_Name AS firstName);

Here is my stored procedure:

DELIMITER //

DROP PROCEDURE IF EXISTS user_login//

create procedure user_login (IN userid VARCHAR(50),
                                   IN password VARCHAR(50),
                                   out success int,
                                   OUT first_Name VARCHAR(255),
                                   )

begin

declare count int(1);
set count =0;

select firstName, count(*)
into first_Name, count
from `tmc`.user where user_id = userid and pwd=password;

if count >0 then

set success =0;

else 
set success=1;

end if;

end//
4

2 に答える 2

5

次のコードを使用していますが、問題なく動作します。必要に応じて変更してください。

public static function CallRaw($procName, $parameters = null, $isExecute = false)
{
    $syntax = '';
    for ($i = 0; $i < count($parameters); $i++) {
        $syntax .= (!empty($syntax) ? ',' : '') . '?';
    }
    $syntax = 'CALL ' . $procName . '(' . $syntax . ');';

    $pdo = DB::connection()->getPdo();
    $pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, true);
    $stmt = $pdo->prepare($syntax,[\PDO::ATTR_CURSOR=>\PDO::CURSOR_SCROLL]);
    for ($i = 0; $i < count($parameters); $i++) {
        $stmt->bindValue((1 + $i), $parameters[$i]);
    }
    $exec = $stmt->execute();
    if (!$exec) return $pdo->errorInfo();
    if ($isExecute) return $exec;

    $results = [];
    do {
        try {
            $results[] = $stmt->fetchAll(\PDO::FETCH_OBJ);
        } catch (\Exception $ex) {

        }
    } while ($stmt->nextRowset());


    if (1 === count($results)) return $results[0];
    return $results;
}

呼び出しの例:

$params = ['2014-01-01','2014-12-31',100];
$results = APIDB::CallRaw('spGetData',$params);

結果の呼び出しは次のようになります。

CALL spGetData(?,?,?)

結果セットが 1 つしかない場合は、そのまま返されます。それ以上ある場合は、結果セットの配列を返します。キーは を使用して$pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, true);います。それがないと、恐ろしいSQLSTATE[HY000]: General error: 2053例外がスローされます。

try{} catch() ブロックは、フェッチできない結果セットを排除するために使用されます。特に、2 つの結果セットを返すプロシージャがあります。1 つは更新 (または他の実行ステートメント) の結果であり、最後の 1 つは実際のデータです。fetchAll()実行クエリでスローされる例外はPDOException.

警告: 関数は最適化されていません。パラメータを 1 回通過するだけで書き換えることができます。

于 2015-01-20T10:57:18.167 に答える
1

ストアド プロシージャが複数の出力を返す場合、この場合、2 つの方法でこの状況を処理できます。

  1. に移動vendor\laravel\framework\src\Illuminate\Database\Connectors\Connector.php して設定PDO::ATTR_EMULATE_PREPAREStrueます。

API を開発するときに問題が発生します。なぜなら、すべての API は、応答が JSON で返されるときに文字列として数値を返すためです{"status": "1"}{"status": 1}

  1. 特定の状況に新しい接続を追加します。すべての API ではなく、特定の API についてのみ上記の問題を処理する必要があります。したがって、オプション 2 を選択することをお勧めします。

config/database.php以下のコードを使用して接続を追加しますconnections

'mysql_procedure' => [
'driver' => 'mysql',
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => 'sv_',
'prefix_indexes' => true,
'strict' => false,
'engine' => null,
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),PDO::ATTR_EMULATE_PREPARES => true
]) : [],
],

構成に従って詳細を更新します。

$procRslts = DB::connection('mysql_procedure')
->select("CALL user_login(?,?,?,?)", array( $userId ,$password,$success,$firstName ));

これでは、最後の 2 つのパラメーターを渡す必要はないと思います。データベースから取得するロジック int プロシージャを記述できます。

ストアド プロシージャによって返される複数の出力を取得できます。

于 2020-02-18T10:04:12.573 に答える