Java程序员在写SQL程序时候常犯的10个错误

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

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

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

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

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

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

  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相比UNION ALL还需要额外的关键字。如果SQL标准已经规定了支持,那么可能会更好点。

  UNION(允许重复)

  UNION DISTINCT (去除了重复)

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

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

  处理方法:

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

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

  大部分的数据库都会支持一些分页命令实现分页效果,譬如LIMIT..OFFSET,TOP..START AT,OFFSET..FETCH语句等。即使没有支持这些语句的数据库,仍有可能对ROWNUM(甲骨文)或者是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语句来远离冒险竞争条件。

  8. 使用聚合函数代替窗口函数(window functions)

  在介绍窗口函数之前,在SQL中聚合数据意味着使用GROUP BY语句与聚合函数相映射。在很多情形下都工作得很好,如聚合数据需要浓缩常规数据,那么就在join子查询中使用group查询。

  但是在SQL:2003中定义了窗口函数,这个在很多主流数据库都实现了它。窗口函数能够在结果集上聚合数据,但是却没有分组。事实上,每个窗口函数都有自己的、独立的PARTITION BY语句,这个工具对于显示报告太TM好了。

  使用窗口函数:

  使SQL更易读(但在子查询中没有GROUP BY语句专业)

  提升性能,像关系数据库管理系统能够更容易优化窗口函数

  解决方法:

  当你在子查询中使用GROUP BY语句时,请再三考虑是否可以使用窗口函数完成。

  9. 使用内存间接排序

  SQL的ORDER BY语句支持很多类型的表达式,包括CASE语句,对于间接排序十分有用。你可能重来不会在Java内存中排序数据,因为你会想:

  SQL排序很慢

  SQL排序办不到

  处理方法:

  如果你在内存中排序任何SQL数据,请再三考虑,是否不能在数据库中排序。这对于数据库分页数据十分有用。

  10. 一条一条的插入大量纪录

  JDBC ”懂“批处理(batch),你应该不会忘了它。不要使用INSERT语句来一条一条的出入成千上万的记录,(因为)每次都会创建一个新的PreparedStatement对象。如果你的所有记录都插入到同一个表时,那么就创建一个带有一条SQL语句以及附带很多值集合的插入批处理语句。你可能需要在达到一定量的插入记录后才提交来保证UNDO日志瘦小,这依赖于你的数据库和数据库设置。

  处理方法:

  总是使用批处理插入大量数据。

时间: 2025-01-05 18:10:15

Java程序员在写SQL程序时候常犯的10个错误的相关文章

Python程序员开发中常犯的10个错误_python

Python是一门简单易学的编程语言,语法简洁而清晰,并且拥有丰富和强大的类库.与其它大多数程序设计语言使用大括号不一样 ,它使用缩进来定义语句块. 在平时的工作中,Python开发者很容易犯一些小错误,这些错误都很容易避免,本文总结了Python开发者最常犯的10个错误,一起来看下,不知你中枪了没有. 1.滥用表达式作为函数参数默认值 Python允许开发者指定一个默认值给函数参数,虽然这是该语言的一个特征,但当参数可变时,很容易导致混乱,例如,下面这段函数定义: 复制代码 代码如下: >>

调查:Java程序员最伤心,C++程序员最年老

说起我们对编程世界现有的刻板印象,你一定听说过类似于没有人喜欢用Java编码或者使用C ++都是老人家,等等这样的话.为了分析这些刻板印象背后的真相,Trestle Technology的数据工程师写了一个工具. 不知道你有没有听说过微软的Project Oxford,它的Face API可以检测图像中的人脸,并检测这个人是否在笑,他/她的性别和年龄,以及面部毛发数量. 数据工程师结合Face API和获取自GitHub趋势网页的数据.这个页面显示了特定语言在流行时的代码仓库.你还可以看到这些项

调查:Java 程序员最伤心,C++ 程序员最年老

说起我们对编程世界现有的刻板印象,你一定听说过类似于没有人喜欢用 Java 编码或者使用 C ++ 都是老人家,等等这样的话.为了分析这些刻板印象背后的真相,Trestle Technology 的数据工程师写了一个工具. 不知道你有没有听说过微软的 Project Oxford,它的 Face API 可以检测图像中的人脸,并检测这个人是否在笑,他/她的性别和年龄,以及面部毛发数量. 数据工程师结合 Face API 和获取自 GitHub 趋势网页的数据.这个页面显示了特定语言在流行时的代码

java-android中这种方法是程序员自己写的,并不是系统自带的,这种理解对吗

问题描述 android中这种方法是程序员自己写的,并不是系统自带的,这种理解对吗 android中这种方法是程序员自己写的,并不是系统自带的,这种理解对吗 如图所示 解决方案 你把鼠标移到方法上,绿色小圆点就是系统的,红色小方块就是自己写的 解决方案二: 看你这段代码应该是自定义的类方法的. 解决方案三: 快捷键 F3 看看来源于哪里 .

探讨:东方程序员眼中的西方程序员是怎样?

引言:本文译自StackExchange上的一个讨论贴:东方程序员眼中的西方程序员是怎样的?,有网友发帖问: 在我看来,东方的程序员如何看待西方同行是一个有趣并且重要的问题. 通常认为东方国家(印度/中国/菲律宾)是为西方国家提供外包服务(美国和欧洲)的. 你有过参与离岸开发的经历吗?如果有,你对此有何看法? 对于西方程序员你有哪些总印象吗(比如是否具有协作精神,是否按时交付产品,或者他们的工作质量如何)? 以下是来自东方各国程序员的答案: 一.印度程序员 Danish 身为印度人,我想谈谈印度

C#程序员会比C++程序员“矮一截”吗??

问题描述 C#程序员会比C++程序员"矮一截"吗??就像本科生在研究生面前"矮一截"C++的软件开发人员貌似比较盛气凌人啊好像很藐视C#程序员似的真TMD不爽 解决方案 解决方案二:反正俺1米74解决方案三:本帖最后由 caozhy 于 2011-09-21 22:55:17 编辑解决方案四:我可没多少时间来理会你所说的那些人了.我只想温+饱解决方案五:众生平等.解决方案六:死亡面前,人人平等,只是有的人需要特殊照顾而已.这可是俺们亡灵界的格言.解决方案七:C---

【转】10年的程序员生涯,给程序员小弟弟小妹妹们的一些总结性忠告

从电驴上看到的一篇文章,写的挺对味的.摘下来,共勉.说的挺对的. 展望未来,总结过去10年的程序员生涯,给程序员小弟弟小妹妹们的一些总结性忠告 走过的路,回忆起来是那么曲折,把自己的一些心得体会分享给程序员兄弟姐妹们,虽然时代在变化,但是很可能你也会走我已经做过的10年的路程,有些心得体会你可以借鉴一下,觉得说得有道理的你就接纳,觉得说得没道理的,你就抛弃,以下是我发自内心的,给大家的忠告,特别是针对那些小弟弟妹妹们. 01. 自己的户口档案.养老保险.医疗保险.住房公积金一定要保管好.由于程序

“菜鸟”程序员和“大神”程序员差距在哪里

"菜鸟"和"大神" 刚刚走出就业的程序员,技术是刚刚起步的基点.那下面我们就聊一聊有关技术 的东西.首先请您先想想这几个问题.现在社会上有很多程序员,CSDN就是我们程序员的家,那您是否可想过程序员为什么会有不同的水平?你又是哪一类的程 序员?"菜鸟"程序员和"大神"程序员差在哪里?真是差在技术上了吗?那不是差在技术上那差在了哪里? 上面很多一连串的问题,没有把你搞晕吧!那就听我一一给您分析这个问题背后的答案.确切的说程序员分

程序员你真的只是程序员吗?

进来了吧~你是不是感觉标题有点矛盾啊,是啊,程序员当然就只是程序员而已嘛,还会有其他什么吗? No,No,No,如果你以前是如此认为的,那看完这篇文章后,请从此打消这个念头,因为你要改变成一个不一样的程序员(怎么还是程序员?) 虽然我工作经验也就6年左右,但经历了很多,也自己创业过,也是从一个初级程序员走起,因为看的比较多了,某些东西也普遍存在着很多程序员身上,希望自己的经验能帮助你们. 当刚踏入程序员这条路的时候,有幸为一家公司开发一个大型的电子商务网站,因为这篇领域当时还算刚刚起步,自己的编