当前位置: 首页 > 科技观察

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

时间:2023-03-13 03:11:30 科技观察

Java程序员在编程时需要将面向对象的思想和一般的命令式编程相结合。两者能否完美结合,完全取决于程序员的水平:技能(任何人都可以轻松学会命令式编程)模式(有些人用“模式-模式”,比如模式无处不在,可以归类为某种模式)的心态(首先,编写一个好的面向对象程序比编写一个命令式程序更难,你必须花费一些精力)但是当Java程序员编写SQL语句时,一切都不同了。SQL是一种声明性语言,而不是面向对象或命令式编程语言。用SQL写查询语句非常简单。但是Java中类似的语句并不容易,因为程序员不仅要反复思考编程范式,还要思考算法。以下是Java程序员在编写SQL时常犯的10个错误(排名不分先后)。1、忘记NULLJava程序员在写SQL时对NULL的误解可能是最大的错误。也许是因为(不是唯一的原因)NULL也被称为UNKNOWN。如果它被称为UNKNOWN,它会更容易理解。另一个原因是,当您从数据库中获取某些内容或绑定变量时,JDBC会将SQLNULL映射到Javanull。这就导致了NULL=NULL(SQL)和null=null(Java)的误解。关于NULL的最大误解是当NULL被用作行值表达式完整性约束时。NOTIN反连接中NULL的应用产生了另一个误解。解决办法:好好训练自己。当你写SQL的时候,你必须不断地思考NULL的使用:这个NULL完整性约束是否正确?NULL会影响结果吗?2.在Java内存中处理数据很少有Java开发人员能很好地理解SQL。偶尔的JOIN和奇怪的UNION,好吧,但是窗口函数呢?那么分组集合呢?许多Java开发人员将SQL数据加载到内存中,将该数据转换为某种集合类型,然后使用有界循环控制结构(至少在Java8集合升级之前)操作对这些集合执行讨厌的数学运算。但一些SQL数据库支持高级(和SQL标准支持的)OLAP功能,这些功能性能更好且更易于编写。一个(不是很标准的)例子是Oracle很棒的MODEL子句。只需让数据库进行处理,并将结果放入Java内存即可。因为毕竟真正聪明的人已经优化了这些昂贵的产品。所以实际上,通过将OLAP移至数据库,您可以获得两个好处:方便。这可能比用Java编写正确的SQL更容易。表现。数据库应该比你的算法更快。更重要的是,您不必传递数百万条记录。解决方案:每次用Java实现以数据为中心的算法时,问问自己:有没有办法让数据库代替我处理这些麻烦事。SpringBoot学习笔记,这篇分享给大家学习。3.使用UNION而不是UNIONALLUNIONALL(duplicatesallowed)UNION(removesduplicates)去除重复行不仅很少需要(有时甚至是错误的),而且对于有很多行的大数据集来说相当慢,因为这两个子查询需要排序,并且每个元组需要与其子序列元组进行比较。请注意,即使SQL标准指定了INTERSECTALL和EXCEPTALL,但很少有数据库实现这些无用的集合运算符。MySQL系列面试题整理完毕。微信搜索Java技术栈,后台发送:面试,可以在线刷题。解决方案:每次编写UNION语句时,请考虑是否确实需要UNIONALL语句。4、使用JDBC分页技术,对大量结果进行分页操作。大多数数据库都支持一些分页命令??来实现分页效果,比如LIMIT..OFFSET、TOP..STARTAT、OFFSET..FETCH语句等,即使没有支持这些语句的数据库,仍然可以过滤ROWNUM(Oracle)或ROWNUMBER()、OVER()(DB2、SQLServer2008等),这比在内存中实现分页更快。在处理大量数据时,效果尤其明显。解决方案:只要使用这些语句,然后有一个工具(如JOOQ)可以模拟这些语句的运行。5.Java内存中的数据连接自从SQL出现初期,一些开发人员在SQL中使用JOIN语句时仍然感到不自在。这源于对加入JOIN后速度变慢的内在恐惧。如果基于成本的优化选择实现嵌套循环,那么在创建连接表源之前,所有表可能都加载到数据库内存中可能是真的。但是这种情况发生的概率太低了。通过适当的预测、约束和索引,合并连接和散列连接操作都非常快。这一切都是为了获得正确的元数据(我不能在这里过多地引用TomKyte)。此外,可能仍然有相当多的Java开发人员通过分别查询将两个表加载到一个映射中,并以某种方式将它们添加到内存中。解决方案:如果你在每一步都有对不同表的查询操作,那么考虑一下你的查询操作是否可以用一条语句表达出来。6.使用DISTINCT或UNION消除临时笛卡尔积集中的重复项。通过复杂的连接,人们可能会失去所有在SQL语句中起关键作用的关系的概念。特别是这里如果涉及多列外键关系,很可能忘记在JOIN..ON子句中添加相关判断。这可能会导致重复记录,但可能只在特殊情况下才会出现。因此,一些开发人员可能会选择DISTINCT来消除这些重复记录。这在三个方面是错误的:它(也许)解决了症状而不是问题。在极端情况下,它也有可能无法解决症状。对于包含许多列的巨大结果集来说速度很慢。DISTINCT执行ORDERBY操作以消除重复。对于大型笛卡尔积集合来说速度很慢,并且仍然需要将大量数据加载到内存中。解决方法:根据经验,如果得到不必要的重复记录,检查一下你的JOIN判断。某处可能存在一组难以察觉的笛卡尔积。7.没有使用MERGE语句这不是错误,但可能是缺乏知识或对强大的MERGE语句缺乏信心。有些数据库理解其他形式的更新插入(UPSERT)语句,比如MYSQL的重复主键更新语句,但是MERGE在数据库中确实非常强大和重要,让SQL标准得到了极大的扩展,比如SQLSERVER。解决方法:如果您使用unionINSERTandUPDATE或unionSELECT..FORUPDATE然后在INSERT或UPDATE等上更新插入,请三思。您可以使用更简单的MERGE语句来避免有风险的竞争条件。最新2021年Java面试题出炉!8、使用聚合函数代替窗口函数(windowfunctions)在引入窗口函数之前,在SQL中聚合数据就是使用GROUPBY语句映射到聚合函数。在很多情况下效果很好,比如聚合数据需要压缩常规数据,然后在连接子查询中使用组查询。但是窗口函数是在SQL2003中定义的,在很多主流数据库中都有实现。窗口函数可以在结果集上聚合数据,但没有分组。事实上,每个窗口函数都有自己独立的PARTITIONBY语句,这个工具非常适合显示报告。使用窗口函数:使SQL更具可读性(但子查询中不能使用GROUPBY语句)提高性能,如关系数据库管理系统可以更方便地优化窗口函数解决方法:当你在子查询中使用GROUPBY语句时,请三思是否可以使用窗口函数完成。9、使用内存的间接排序SQL的ORDERBY语句支持多种类型的表达式,包括CASE语句,这对间接排序非常有用。你可能不会在Java内存中对数据进行排序,因为你认为:SQL排序很慢SQL排序行不通解决方法:如果你在内存中对任何SQL数据进行排序,再想一想,如果它在数据库中无法排序。这对于数据库分页数据很有用。10、一条一条插入大量记录JDBC“懂”批处理(batch),你不要忘了。不要使用INSERT语句一条一条地进入和退出数千条记录,(因为)每次都会创建一个新的PreparedStatement对象。如果您的所有记录都被插入到同一个表中,请使用一个SQL语句和多个值集创建一个INSERT批处理语句。根据您的数据库和数据库设置,您可能需要仅在插入一定数量的记录后才提交,以保持较小的UNDO日志。解决方法:始终使用批处理来插入大量数据。另外,关注公众号Java技术栈,后台回复:面试,可以拿到我整理的Java/MySQL系列面试题及答案,很全。