我正在将使用Sqlite3开发的Ruby on Rails应用程序部署到具有MySQL或PostgreSQL的服务器。我很快发现,我正在大量使用“group by”和“strftime”函数来生成按月汇总报告,这些函数在各种数据库之间的工作方式不同或不兼容。
我可以重构我的代码来进行分组,求和和平均 - 但数据库做得很好,减少了服务器所需的处理!高级应用程序超越了简单的选择和加入。 ActiveRecord为我们提供:group,但DATABASES并不一致。
所以我的问题是架构问题 - 有人希望在Ruby on Rails中创建真正的“数据库可移植”应用程序吗?我应该修改我的代码库以仅使用MySQL而忘记其他数据库吗?我应该修改我的代码库来进行高级分组,求和和平均吗?
欢呼 - 唐答案 0 :(得分:4)
几条评论:
使用您要部署的相同RDBMS品牌和版本进行开发和测试。
编写可移植的SQL代码很难,因为供应商拥有所有这些非标准的额外功能和特性。例如,strftime()
不是ANSI SQL标准的一部分。解决此问题的唯一方法是为您使用的每个数据库使用RTM,并了解它们共有的功能。有时它们具有不同名称的功能,您可以以类似的方式使用它们。这方面没有捷径 - 你必须学习手册。
所有数据库都支持GROUP BY,但SQLite和MySQL对某些用法比标准ANSI SQL(以及遵循该标准的所有其他品牌数据库)更宽松。具体来说,在GROUP BY子句中,您必须将选择列表中不属于分组函数的每一列命名。
以下两个例子是正确的:
SELECT A, B, COUNT(C) FROM MyTable GROUP BY A, B;
SELECT A, COUNT(C) FROM MyTable GROUP BY A;
但下一个是错误的,因为B每组有多个值,并且它应该在给定行中返回哪个值是不明确的:
SELECT A, B, COUNT(C) FROM MyTable GROUP BY A;
没有框架可以写出真正的可移植SQL。 Rails的ActiveRecord仅在非常简单的情况下解决了这个问题。实际上,ActiveRecord有助于解决您提供的示例 ,特定品牌的功能以及非标准的GROUP BY子句。
答案 1 :(得分:3)
问题是,特别是GROUP BY MySQL做错了。如果你遗漏了MySQL中的列,只需返回“某些东西”,接受结果可能是不确定的。
如果你的GROUP BY的结果没有明确定义,你可以(应该)使用ONLY_FULL_GROUP_BY参数使MySQL抛出错误。
实际上还有很多设置应该在MySQL中进行更改以使其表现得更加明智
您可能有兴趣阅读此内容:
http://www.slideshare.net/ronaldbradford/mysql-idiosyncrasies-that-bite-201007