从 mysql 迁移到 postgresql 时,Laravel 雄辩的 ORM 不起作用
Posted
技术标签:
【中文标题】从 mysql 迁移到 postgresql 时,Laravel 雄辩的 ORM 不起作用【英文标题】:Laravel elequent ORM not working when migrate from mysql to postgresql 【发布时间】:2017-12-18 13:50:34 【问题描述】:ORM 的基本特性通常说是因为数据库迁移很容易从一个数据库迁移到另一个数据库。在这里,我最初在我的项目中使用了 mysql 数据库,并计划将其迁移到 PostgreSQL。迁移时,它适用于几乎所有使用 select * from table、insert update 等的简单查询。
但是当我通过 MySQL 中的一些 datediff
函数时,ORM 无法在 PostgreSQL 中创建相应的查询。
这是我的查询
$result = DB::table('sales_target')
->select(db::raw('DATEDIFF(end_date,start_date) as DaysInQuarter'))
->whereraw("sales_target.target_quarter=$currentQuarter AND sales_target.target_year=$currentYear and status=1")
->first();
我想知道我是否用完全 ORM 结构编写了查询。请帮我解决这个问题。
编辑 1
简而言之,我想请任何人告诉我如何编写此查询
DB::table('sales_target')
->select(db::raw("DATEDIFF(end_date,start_date) AS DaysInQuarter"))
->first();
这应该可以在使用 ORM 的 mysql 和 postgresl 中工作。
在 Mysql 中它可以正常工作,但在 postgresql 中却不是。
我收到这样的错误
No function matches the given name and argument types. You might need to add explicit type casts. (SQL: select DATEDIFF(end_date,start_date) AS DaysInQuarter from "sales_target" limit 1)
【问题讨论】:
【参考方案1】:首先,这里没有使用 ORM。您使用的是查询生成器,而不是 Eloquent。
第二件事是 Laravel 不会为你完成这项工作 - 如果你使用原始表达式,你应该根据你使用的数据库引擎来使用它们。
此外,您应该关心 SQL 注入,现在可以将一些代码注入到您的查询中,您应该使用:
$result = DB::table('sales_target')
->select(db::raw('DATEDIFF(end_date,start_date) as DaysInQuarter'))
->whereRaw("sales_target.target_quarter=? AND sales_target.target_year= ? and status=1", [$currentQuarter, $currentYear])
->first();
当然,在上述情况下,$currentQuarter
和 $currentYear
可能是您完全控制的变量,但最好使用准备好的状态,以防您以后决定使用用户输入数据。
【讨论】:
查询生成器不也是基于 eloquent 的吗?它们的功能不是可以互换的(我可以在雄辩的查询中使用每个数据库功能)吗?我同意 Db::raw 绝不是 ORM 请考虑到当我问这个问题时我只是处于学习模式:) 不,Eloquent 正在使用查询构建器,但查询构建器不使用 Eloquent。在上面,您使用查询构建器,因为您从DB::table('sales_target')
开始 - 如果您从模型 SalesTarget
开始,那么您将使用 Eloquent
我基本上打算从mysql迁移到postgresql,但是postgresql不支持datediff函数。所以我认为我无法访问 db::raw('datediff()') 函数。在 elequent ORM 的情况下,我如何管理可以在 mysql 和 postgres 上运行的 ORM 查询。
@anoop 如果你想在任何数据库引擎中使用你的代码,首先不要使用特定的 SQL 函数。在上述情况下,只需从数据库中获取 end_date 和 start_date 而不使用 datediff
,如果你想计算差异,请在 php 中进行
这就是我所困惑的,我如何将其转换为 ORM DB::table('sales_target') ->select(db::raw('DATEDIFF(end_date,start_date) as DaysInQuarter ')) ->whereraw("sales_target.target_quarter=$currentQuarter AND sales_target.target_year=$currentYear and status=1") ->first();.我被困在这里了。【参考方案2】:
如果您使用db::raw()
,那么 ORM 无法帮助您从数据库引擎中抽象出来。你应该看看 Laravel 中的 Carbon 集成和 methods of the Query Builder like whereBetween()
来重写你的查询。
【讨论】:
【参考方案3】:当你使用“db::raw(”时,这不再是 ORM。
您只需将该字符串原样直接发送到数据库服务器。
检查 Postgresql 是否具有与 DateDIFF 函数相同的语法
【讨论】:
【参考方案4】:我可以这样写来管理查询
DB::table('sales_target')
->select(db::raw(" DATE_PART('day', end_date - start_date) AS DaysInQuarter"))
->whereRaw("sales_target.target_quarter=? AND sales_target.target_year= ? and status=1", [$currentQuarter, $currentYear])
->first();
我认为在 eloquent 中我们必须手动将函数 DATEDIFF 更改为 DATE_PART。但是在像休眠这样的 ORM 中,我认为它们本身在不同的 SQL 查询中管理这个函数的变化。
【讨论】:
以上是关于从 mysql 迁移到 postgresql 时,Laravel 雄辩的 ORM 不起作用的主要内容,如果未能解决你的问题,请参考以下文章
从 MySQL 迁移到 PostgreSQL 后类似查询的 SQL 性能问题
从 MSSQL 迁移到 postgresql 或 mysql [关闭]
AskTUG 论坛迁移实战:Discourse 从 PostgreSQL 到 MySQL 到 TiDB | 极客分享第 36 期