在 Laravel 中高效执行复杂原生 SQL 查询

霞舞
发布: 2025-11-21 12:59:42
原创
104人浏览过

在 Laravel 中高效执行复杂原生 SQL 查询

laravel 的 eloquent orm 或查询构建器无法满足高度定制化的复杂 sql 查询需求时,db::select() 方法提供了一种直接且高效的解决方案。本文将指导您如何在 laravel 应用程序中无缝集成并执行原生 sql 语句,处理复杂的联接、聚合与条件筛选,确保数据检索的灵活性与性能。

理解 Laravel 中的数据库操作

Laravel 提供了强大的数据库抽象层,包括 Eloquent ORM 和查询构建器(Query Builder),它们极大地简化了数据库交互。对于大多数 CRUD 操作和中等复杂度的查询,这些工具都能提供优雅且高效的解决方案。然而,在面对某些极端复杂或高度优化的 SQL 语句时,例如涉及多表复杂联接、自定义函数、高级聚合或复杂的 HAVING 子句时,尝试将这些逻辑完全转换为查询构建器语法可能会变得异常困难,甚至导致代码冗长、难以维护或性能不佳。

在这种情况下,Laravel 允许开发者直接执行原生 SQL 查询,从而在不脱离框架环境的前提下,获得最大的灵活性和控制力。

何时选择原生 SQL 查询

选择使用原生 SQL 而非查询构建器或 Eloquent,通常基于以下考量:

  1. 查询复杂度极高: 当查询涉及多个非标准联接、复杂的子查询、自定义数据库函数、递归查询或难以通过构建器表达的 HAVING 条件时。
  2. 性能优化: 对于某些特定的、需要极致性能的报表或数据分析查询,直接编写优化的原生 SQL 可能是最佳选择。
  3. 特定数据库特性: 需要利用数据库特有的函数或语法,而这些特性不被 Laravel 查询构建器普遍支持时。
  4. 现有复杂 SQL 迁移: 当需要将大量已有的、复杂的原生 SQL 语句集成到 Laravel 项目中,且重写成本过高时。

使用 DB::select() 执行原生 SQL

Laravel 的 DB Facade 提供了一个 select() 方法,专门用于执行读取操作的原生 SQL 查询。这个方法非常直观,它接受一个 SQL 字符串作为第一个参数,以及一个可选的绑定数组作为第二个参数(用于安全地处理用户输入)。

基本语法:

use Illuminate\Support\Facades\DB;

$results = DB::select('SELECT * FROM users WHERE active = ?', [1]);
登录后复制

DB::select() 方法返回一个包含 stdClass 对象的数组,每个对象代表查询结果集中的一行。

豆绘AI
豆绘AI

豆绘AI是国内领先的AI绘图与设计平台,支持照片、设计、绘画的一键生成。

豆绘AI 485
查看详情 豆绘AI

示例:执行复杂的用户会话统计查询

假设我们有一个非常复杂的 SQL 查询,用于统计用户会话的上传、下载总量,并根据特定条件进行过滤和分组。以下是这样一个查询的示例:

SELECT
    ru.external_ref_no AS SID,
    usd.user_name AS Username,
    rs.servicecode AS Package,
    rc.clientdesc AS Entity,
    rc.clientip AS NAS_IP,
    ROUND((ROUND((SUM(usd.FREE_UPLOAD_OCTETS)/1048576)))/1024,2) AS Upload,
    ROUND((ROUND((SUM(usd.FREE_DOWNLOAD_OCTETS)/1048576)))/1024,2) AS Download,
    ROUND((ROUND((SUM(usd.FREE_UPLOAD_OCTETS)/1048576)))/1024,2) + ROUND((ROUND((SUM(usd.FREE_DOWNLOAD_OCTETS)/1048576)))/1024,2) AS Total_Usage
FROM
    user_session_detail usd,
    radservice rs,
    radclient rc,
    radgroup rg,
    raduser ru
WHERE
    ru.username = usd.user_name AND
    rs.serviceid = usd.service_id AND
    rg.groupid = usd.group_id AND
    usd.client_id = rc.clientid AND
    usd.SESSION_START_TIME > '2021-09-30 00.00.01' AND
    usd.SESSION_START_TIME < '2021-09-30 23.59.59'
GROUP BY
    usd.user_name
HAVING
    (ROUND((SUM(usd.FREE_UPLOAD_OCTETS)/1048576)))/1024 + (ROUND((SUM(usd.FREE_DOWNLOAD_OCTETS)/1048576)))/1024 > 15 AND
    (ROUND((SUM(usd.FREE_UPLOAD_OCTETS)/1048576)))/1024 + (ROUND((SUM(usd.FREE_DOWNLOAD_OCTETS)/1048576)))/1024 < 20;
登录后复制

将上述复杂查询集成到 Laravel 中,只需将其作为字符串传递给 DB::select():

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class ReportController extends Controller
{
    public function showUserUsageReport()
    {
        // 定义复杂的SQL查询字符串
        // 在实际应用中,对于如此长的SQL,建议将其放在单独的文件或常量中以保持代码整洁
        $sqlQuery = "
            SELECT
                ru.external_ref_no AS SID,
                usd.user_name AS Username,
                rs.servicecode AS Package,
                rc.clientdesc AS Entity,
                rc.clientip AS NAS_IP,
                ROUND((ROUND((SUM(usd.FREE_UPLOAD_OCTETS)/1048576)))/1024,2) AS Upload,
                ROUND((ROUND((SUM(usd.FREE_DOWNLOAD_OCTETS)/1048576)))/1024,2) AS Download,
                ROUND((ROUND((SUM(usd.FREE_UPLOAD_OCTETS)/1048576)))/1024,2) + ROUND((ROUND((SUM(usd.FREE_DOWNLOAD_OCTETS)/1048576)))/1024,2) AS Total_Usage
            FROM
                user_session_detail usd,
                radservice rs,
                radclient rc,
                radgroup rg,
                raduser ru
            WHERE
                ru.username = usd.user_name AND
                rs.serviceid = usd.service_id AND
                rg.groupid = usd.group_id AND
                usd.client_id = rc.clientid AND
                usd.SESSION_START_TIME > '2021-09-30 00.00.01' AND
                usd.SESSION_START_TIME < '2021-09-30 23.59.59'
            GROUP BY
                usd.user_name
            HAVING
                (ROUND((SUM(usd.FREE_UPLOAD_OCTETS)/1048576)))/1024 + (ROUND((SUM(usd.FREE_DOWNLOAD_OCTETS)/1048576)))/1024 > 15 AND
                (ROUND((SUM(usd.FREE_UPLOAD_OCTETS)/1048576)))/1024 + (ROUND((SUM(usd.FREE_DOWNLOAD_OCTETS)/1048576)))/1024 < 20;
        ";

        // 执行查询
        $results = DB::select($sqlQuery);

        // $results 将是一个包含stdClass对象的数组,每个对象代表一行数据
        // 例如:$results[0]->SID, $results[0]->Username 等
        return view('reports.secretuserlist', compact('results'));
    }
}
登录后复制

将查询结果传递到视图

获取到 $results 数组后,您可以像处理任何其他数据一样,将其传递给 Laravel 的 Blade 视图进行渲染。上述控制器示例

以上就是在 Laravel 中高效执行复杂原生 SQL 查询的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号