Java 程序员常犯的 10 个 SQL 错误!

本文讨论了Java程序员在混合面向对象和命令式编程时遇到的问题,重点列举了在使用SQL时常见的十个错误,如NULL处理、内存中处理数据、不当使用UNION等,并提供了相应的解决方案。同时,强调了系统学习和利用数据库优化的重要性。作者还分享了关于Java开发的学习资源链接。
摘要由CSDN通过智能技术生成

Java程序员编程时需要混合面向对象思维和一般命令式编程的方法,能否完美的将两者结合起来完全得依靠编程人员的水准:

  • 技能(任何人都能容易学会命令式编程)

  • 模式(有些人用“模式-模式”,举个例子,模式可以应用到任何地方,而且都可以归为某一类模式)

  • 心境(首先,要写个好的面向对象程序是比命令式程序难的多,你得花费一些功夫)

但当Java程序员写SQL语句时,一切都不一样了。SQL是说明性语言而非面向对象或是命令式编程语言。在SQL中要写个查询语句是很简单的。但在Java里类似的语句却不容易,因为程序员不仅要反复考虑编程范式,而且也要考虑算法的问题。

下面是Java程序员在写SQL时常犯的10个错误(没有特定的顺序)。

1、忘掉NULL


Java程序员写SQL时对NULL的误解可能是最大的错误。也许是因为(并非唯一理由)NULL也称作UNKNOWN。如果被称作 UNKNOWN,这还好理解些。另一个原因是,当你从数据库拿东西或是绑定变量时,JDBC将SQL NULL 和Java中的null对应了起来。这样导致了NULL = NULL(SQL)和null=null(Java)的误解。

对于NULL最大的误解是当NULL被用作行值表达式完整性约束条件时。另一个误解出现在对于NULL 在 NOT IN anti-joins的应用中。

解决方法:

  • 好好的训练你自己。当你写SQL时要不停得想到NULL的用法:

  • 这个NULL完整性约束条件是正确的?

  • NULL是否影响到结果?

2、在Java内存中处理数据


很少有Java开发者能将SQL理解的很好。偶尔使用的JOIN,还有古怪的UNION,好吧,但是对于窗口函数呢?还有对集合进行分组呢?许多 的Java开发者将SQL数据加载到内存中,将这些数据转换成某些相近的集合类型,然后再那些集合上面使用边界循环控制结构(至少在Java8的集合升级 以前)执行令人生厌的数学运算。

但是一些SQL数据库支持先进的(而且是SQL标准支持的)OLAP特性,这一特性表现更好而且写起来也更加方便。一个(并不怎么标准的)例子就 是Oracle超棒的MODEL分句。只让数据库来做处理然后只把结果带到Java内存中吧。因为毕竟所有非常聪明的家伙已经对这些昂贵的产品进行了优 化。因此实际上,通过将OLAP移到数据库,你将获得一下两项好处:

  • 便利性。这比在Java中编写正确的SQL可能更加的容易。

  • 性能表现。数据库应该比你的算法处理起来更加快.而且更加重要的是,你不必再去传递数百万条记录了。

解决方法:

每次你使用Java实现一个以数据为中心的算法时,问问自己:有没有一种方法可以让数据库代替为我做这种麻烦事。

3、使用UNION 代替UNION ALL


  • UNION ALL(允许重复)

  • UNION (去除了重复)

移除重复行不仅很少需要(有时甚至是错的),而且对于带很多行的大数据集合会相当慢,因为两个子select需要排序,而且每个元组也需要和它的子序列元组比较。

注意即使SQL标准规定了INTERSECT ALL和EXCEPT ALL,很少数据库会实现这些没用的集合操作符。

解决方法:

每次写UNION语句时,考虑实际上是否需要UNION ALL语句。

4、通过JDBC分页技术给大量的结果进行分页操作


大部分的数据库都会支持一些分页命令实现分页效果,譬如LIMIT…OFFSET,TOP…START AT,OFFSET…FETCH语句等。即使没有支持这些语句的数据库,仍有可能对ROWNUM(Oracle)或者是ROW NUMBER()、OVER()过滤(DB2、SQL Server2008等),这些比在内存中实现分页更快速。在处理大量数据中,效果尤其明显。

解决方法:

仅仅使用这些语句,那么一个工具(例如JOOQ)就可以模拟这些语句的操作。

5、在Java内存中加入数据


从SQL的初期开始,当在SQL中使用JOIN语句时,一些开发者仍旧有不安的感觉。这是源自对加入JOIN后会变慢的固有恐惧。

假如基于成本的 优化选择去实现嵌套循环,在创建一张连接表源前,可能加载所有的表在数据库内存中,这可能是真的。但是这事发生的概率太低了。通过合适的预测,约束和索 引,合并连接和哈希连接的操作都是相当的快。这完全是是关于正确元数据(在这里我不能够引用Tom Kyte的太多)。而且,可能仍然有不少的Java开发人员加载两张表通过分开查询到一个映射中,并且在某种程度上把他们加到了内存当中。

解决方法:

假如你在各个步骤中有从各种表的查询操作,好好想想是否可以表达你的查询操作在单条语句中。

6、在一个临时的笛卡尔积集合中使用 DISTINCT 或 UNION 消除重复项


通过复杂的连接,人们可能会对SQL语句中扮演关键角色的所有关系失去概念。特别的,如果这涉及到多列外键关系的话,很有可能会忘记在JOIN … ON子句中增加相关的判断。这会导致重复的记录,但或许只是在特殊的情况下。有些开发者因此可能选择DISTINCT来消除这些重复记录。从三个方面来说 这是错误的:

  • 它(也许)解决了表面症状但并没有解决问题。它也有可能无法解决极端情况下的症状。

  • 对具有很多列的庞大的结果集合来说它很慢。DISTINCT要执行ORDER BY操作来消除重复。

  • 对庞大的笛卡尔积集合来说它很慢,还是需要加载很多的数据到内存中。

解决方法:

根据经验,如果你获得了不需要的重复记录,还是检查你的JOIN判断吧。可能在某个地方有一个很难觉察的笛卡尔积集合。

7、不使用MERGE语句


这并不是一个过失,但是可能是缺少知识或者对于强悍的MERGE语句信心不足。一些数据库理解其它形式的更新插入(UPSERT)语句, 如 MYSQL的重复主键更新语句,但是MERGE在数据库中确是很强大,很重要,以至于大肆扩展SQL标准,例如SQL SERVER。

解决方法:

如果你使用像联合INSERT和UPDATE或者联合SELECT … FOR UPDATE然后在INSERT或UPDATE等更新插入时,请三思。你完全可以使用一个更简单的MERGE语句来远离冒险竞争条件。

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
95%以上Java开发知识点,不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!**

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

  • 27
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值