如何在Laravel中从MySQL存储过程中获取多个结果集

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//
2个回答

7
我正在使用以下代码,它能够完美地运行。根据您的需求进行更改即可。
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(?,?,?)

如果只有一个结果集,它将按原样返回。如果有更多,则会返回一组结果集。关键是使用$pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, true);。如果没有它,会抛出可怕的SQLSTATE[HY000]: General error: 2053异常。
try{} catch()块用于消除无法获取的结果集。特别是,我有一些程序返回两个结果集,一个是由更新(或其他执行语句)产生的结果集,最后一个是真实数据。在执行查询的fetchAll()上抛出的异常将是PDOException
警告:该函数未经优化。您可以重新编写它,仅通过一次参数传递即可。

1
如果您的存储过程返回多个输出,那么可以通过两种方法来处理这种情况。
1. 转到vendor\laravel\framework\src\Illuminate\Database\Connectors\Connector.php并将PDO::ATTR_EMULATE_PREPARES设置为true
2. 在特定情况下添加新连接。您只需要处理特定API的上述问题,而不是所有API。因此,我建议选择第二个选项。
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 ));

我认为在这种情况下,您不需要传递最后两个参数,可以编写程序逻辑从数据库中获取。

您可以通过存储过程返回多个输出。


1
请在您的答案中添加一些解释 - 哪些部分是解决问题所必需的,以及为什么? - Nico Haase
@NicoHaase 谢谢您的建议。我希望现在没问题了。 - er.irfankhan11
你有没有针对Microsoft SQL Server的具体解决方案? - Waleed Alrashed
1
@WaleedAlrashed,我没有在Laravel中使用MS SQL,如果你找到了任何解决方案,请分享一下,这对其他人会很有帮助 :) - er.irfankhan11

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接