2011年12月23日 星期五

DBA生存之四大守则



http://www.builder.com.cn/2007/0930/531123.shtml
在我的DBA系列课程讲义中,我曾经总结了"DBA的四大守则",做为一点告诫,每次我都会在课程开始时强调这几个内容.

此前在几篇文章中,陆续的介绍过2大守则:

    DBA生存守则之三
    年终难终 进入数据库事故多发期

曾经有很多朋友问我另外2个守则是什么,今天一并写在这里,做为回答.

我列出的四大守则是:

 1.备份重于一切
我们必需知道,系统总是要崩溃的,没有有效的备份只是等哪一天死!我经常开玩笑的说,唯一会使DBA在梦中惊醒的就是,没有有效的备份.

2.三思而后行
think thrice before you act

任何时候都要清楚你所做的一切,否则宁可不做!有时候一个回车,一条命令就会造成不可恢复的灾难,所以,你必需清楚确认你所做的一切,并且在必要时保护现场.

3.rm是危险的
  要知道在UNIX/Linux下,这个操作意味着你可能将永远失去后面的东西,所以,确认你的操作!!!
 太多的人在 "rm -rf" 上悲痛欲绝,当年写下这条守则时,是一个凌晨被一个朋友吵醒,他说误操作rm -rf删除掉了200G的数据库,并且没有备份.

我当时能告诉他的只有一句话:要保持冷静.

4.你来制定规范
 良好的规范是减少故障的基础。所以,做为一个DBA,你需要来制订规范,规范开发甚至系统人员,这样甚至可以规避有意或是无意的误操作.减少数据库的风险.

我们知道,在管理良好的数据库服务器上,rm -rf甚至可能是不允许使用的.



也许我们需要遵守的可能更多,所以我一直强调DBA一定要严谨专注,当然我也非常喜欢另外一句话:坚韧卓绝之人,必能成就万事.

以上四大守则,愿于诸位DBA朋友共勉.

怎样成长为一个真正的Oracle DBA


http://www.builder.com.cn/2007/0820/460894.shtml
Oracle分两大块,一块是开发,一块是管理。

开发主要是写写存储过程、触发器什么的,还有就是用Oracle的Develop工具做form。有点类似于程序员,需要有较强的逻辑思维和创造能力,个人觉得会比较辛苦,是青春饭;管理则需要对Oracle数据库的原理有深刻的认识,有全局操纵的能力和紧密的思维,责任较大,因为一个小的失误就会down掉整个数据库,相对前者来说,后者更看重经验。因为数据库管理的责任重大,很少公司愿意请一个刚刚接触Oracle的人去管理数据库。

对于刚刚毕业的年轻人来说,可以先选择做开发,有一定经验后转型,去做数据库的管理。当然,这个还是要看人个的实际情况来定。

二、学习方法

我的方法很简单,就是:看书、思考、写笔记、做实验、再思考、再写笔记。看完理论的东西,自己静下心来想想,多问自己几个为什么,然后把所学和所想的知识点做个笔记;在想不通或有疑问的时候,就做做实验,想想怎么会这样,同样的,把实验的结果记下来。思考和做实验是为了深入的了解这个知识点。而做笔记的过程,也是理清自己思路的过程。学习的过程是使一个问题由模糊到清晰,再由清晰到模糊的过程。而每次的改变都代表着你又学到了一个新的知识点。

学习的过程也是从点到线,从线到网,从网到面的过程。当点变成线的时候,你会有总豁然开朗的感觉。当网到面的时候,你就是高手了。很多网友,特别是初学的人,一碰到问题就拿到论坛上来问,在问前,你有没有查过书,自己有没有研究过,有没有搜索一下论坛?这就叫思维惰性。

由别人来回答你的问题,会让你在短时间内不费劲地弄懂这个知识点,然而通过自己的努力去研究它,不但会更深入的了解这个知识点,更重要的是在研究的过程会提高你解决问题和分析问题的能力。总的来说,没有钻研的学习态度,不管学什么东西,都不会成功的。 当然,初学的人很多时候是因为遇到问题时,无从下手,也不知道去哪里找资料,才会到论坛上提问题的。但我认为,在提问的时候,是不是可以问别人是如何分析这个问题?从哪里可以找到相关的资料?而不是这个问题的答案是什么?授人以鱼不如授人以渔。

下面我讲下,我处理问题的过程。首先要知道Oracle的官方网站:www.oracle.com。这里有Oracle的各种版本的数据库、应用工具和权威的官方文档。

其次,还要知道http://metalink.Oracle.com/。这里是买了Oracle服务或是Oracle的合作伙伴才可以进去的,里面有很多权威的解决方案和补丁。

然后就是一些著名网站:asktom.Oracle.com www.orafaq.net, www.dbazine.com。这里有很多遇到问题了的经验之谈。

如果是概念上的问题,第一时间可以找tahiti.Oracle.com,这里会给你最详细的解释。如果在运行的过程中出了什么错误。可以去metalink看看。如果是想知道事务的处理的经验之谈。可以去asktom。当然。这里只是相对而言。

三、Oracle的体系

Oracle的体系很庞大,要学习它,首先要了解Oracle的框架。在这里,简要的讲一下Oracle的架构,让初学者对Oracle有一个整体的认识。

1、物理结构(由控制文件、数据文件、重做日志文件、参数文件、归档文件、密码文件组成)

控制文件:包含维护和验证数据库完整性的必要信息、例如,控制文件用于识别数据文件和重做日志文件,一个数据库至少需要一个控制文件。

数据文件:存储数据的文件。

重做日志文件:含对数据库所做的更改记录,这样万一出现故障可以启用数据恢复。一个数据库至少需要两个重做日志文件。 参数文件:定义Oracle例程的特性,例如它包含调整SGA中一些内存结构大小的参数。

归档文件:是重做日志文件的脱机副本,这些副本可能对于从介质失败中进行恢复很必要。

密码文件:认证哪些用户有权限启动和关闭Oracle例程。

2、逻辑结构(表空间、段、区、块)

表空间:是数据库中的基本逻辑结构,一系列数据文件的集合。

段:是对象在数据库中占用的空间。

区:是为数据一次性预留的一个较大的存储空间。

块:Oracle最基本的存储单位,在建立数据库的时候指定。

3、内存分配(SGA和PGA)

SGA:是用于存储数据库信息的内存区,该信息为数据库进程所共享。它包含Oracle服务器的数据和控制信息,它是在Oracle 服务器所驻留的计算机的实际内存中得以分配,如果实际内存不够再往虚拟内存中写。

PGA:包含单个服务器进程或单个后台进程的数据和控制信息,与几个进程共享的SGA正相反PGA是只被一个进程使用的区域,PGA 在创建进程时分配在终止进程时回收。

4、后台进程(数据写进程、日志写进程、系统监控、进程监控、检查点进程、归档进程、服务进程、用户进程)

数据写进程:负责将更改的数据从数据库缓冲区高速缓存写入数据文件。

日志写进程:将重做日志缓冲区中的更改写入在线重做日志文件。

系统监控:检查数据库的一致性如有必要还会在数据库打开时启动数据库的恢复。

进程监控:负责在一个Oracle进程失败时清理资源。

检查点进程:负责在每当缓冲区高速缓存中的更改永久地记录在数据库中时,更新控制文件和数据文件中的数据库状态信息。 归档进程:在每次日志切换时把已满的日志组进行备份或归档。

服务进程:用户进程服务。

用户进程:在客户端,负责将用户的SQL语句传递给服务进程,并从服务器段拿回查询数据。

5、Oracle例程

Oracle 例程由SGA内存结构和用于管理数据库的后台进程组成。例程一次只能打开和使用一个数据库。

6、SCN(System Change Number)

系统改变号,一个由系统内部维护的序列号。当系统需要更新的时候自动增加,他是系统中维持数据的一致性和顺序恢复的重要标志。

四、深入学习

管理:可以考OCP证书,对Oracle先有一个系统的学习,然后看Oracle Concepts、Oracle online document,对Oracle的原理会有更深入的了解,同时可以开始进行一些专题的研究如:RMAN、RAS、STATSPACT、DATAGUARD、TUNING、BACKUP&RECOVER等等。

开发:对于想做Oracle开发的,在了解完Oracle基本的体系结构之后,可以重点关注PL/SQL及Oracle的开发工具这一部分。PL/SQL主要是包括怎么写SQL语句,怎么使用Oracle本身的函数,怎么写存储过程、存储函数、触发器等。Oracle的开发工具主要就是Oracle自己的Developer Suite(Oracle Forms Developer and Reports Developer这些),学会如何熟练使用这些工具。

介绍几个网站

http://tahiti.Oracle.com Oracle的官方文档

http://metalink.Oracle.com/Oracle的技术支持网站。需要购买Oracle服务才能有一个帐号,才能登陆,有大量的Knowledge Base,大量问题解决经验。

http://www.Oracle.com Oracle的官方网站,可以在这里down Oracle的软件、官方文档和获得最新的消息

http://www.dbazine.com/Oracle的杂志

0.1. DBA的性格


http://blog.oraclefans.cn/baishan1/entry/dba%E6%97%A5%E8%AE%B0_%E5%89%8D%E8%A8%80%E4%B9%8Bdba%E7%9A%84%E6%80%A7%E6%A0%BC
0.1. DBA的性格

不一定任何人都需要从事DBA这个工作,DBA是一种压力相对比较大的职业,并且要求从业人员在工作期间不断的学习新的技术。Oracle数据库每5年左右会进行大版本升级,这就需要DBA不断的学习新的知识。记得几年前在做一个项目的时候,和一个干了七八年的老DBA一起聊天,他说本来想好了,9i的技术就不去学习了,就吃8i的老本了,不过没办法,想要生存,必须去学习。最后他说他的最大愿望是不要再去学10g 的东西了。不过愿望只是愿望,2年后,我看到他出差的时候带着一本10g 的书,就说起了那次对话。他也只能笑着说,干DBA的都是苦命人,不学习是不可能的。DBA这个职业可以做的很长,国外一些高手和大师都是从事DBA工作超过20年的。不过对于绝大多数朋友来手,DBA只是职业生涯中的一个台阶而已,因此在做职业规划的时候,首先你需要考虑DBA是作为一种过渡性的工作呢,还是作为一种生活和爱好。

这就需要根据自身的性格来考虑了,有几种性格是不适合做DBA的。DBA需要谨慎的态度,如果你的性格比较急躁,那么DBA不是适合你的工作。DBA承担了企业中最为重要的数据库的维护,其工作性质决定了DBA是一种压力十分大的职业,在处理日常工作以及突发性问题的时候,急躁是最为可怕的性格,越是碰到紧急的问题,越需要DBA以冷静的心态来面对,否则很容易出现不必要的问题。2004年美国的一项调查表明,超过30%的系统故障是由于维护人员人为失误造成的,因此沉稳的性格是DBA减少出现操作失误的一个重要保证。

除了急躁外,好奇心太强的人也不适合做DBA。DBA在做维护工作的时候,经常会碰到一些莫名其妙的事情,和自己工作无关的事情尽量不要做,这是铁的纪律。Oracle公司的工程师到客户现场工作的时候,一般会拒绝客户提出的和本次任务无关的工作,这也是oracle原厂服务经常被客户诟病的一点。不过我认为这是一种很职业的态度,我只做和我工作相关的事情。从另外一个角度来说,就是做自己技术能力范围内的事情。有些DBA无法判断某个操作的风险,在这种情况下,客户让你做某件事情,你到底是做还是不做呢?最好的方式是通过向专家咨询,确认没有问题后再去做。一个好奇心很强的DBA,可能发现了一个新的脚本,就很急迫的想在自己维护的生产库上尝试一下,可能他根本没有去考虑这个脚本是否存在风险。实际上,在我这十多年的DBA工作中,也多次出现了由于好奇心强导致去做一些自己认为没有风险的事情,结果或多或少的造成了一些问题,甚至有一次我在一个客户的生产库上尝试一个以前没有做过的DUMP命令,最终碰到了一个Oracle 的BUG,导致RAC的一个节点宕机。从那以后,哪怕再好奇,我也会先充分评估操作的风险,并且尽可能不去做一些和自己工作无关的分析。实际上,作为一个DBA是很难经得起诱惑的,因为有很多情况可能你一辈子也碰不上几回,作为一个爱好ORACLE的人,碰到了某种现场,都可能会被吸引,甚至诱惑。作为DBA,经得起诱惑,是十分好的性格。从另一个方面来说,DBA需要足够的职业素养,由于DBA工作的风险十分高,任何一个违背职业素养的工作习惯都可能演变为工作中的失误,因此做一个真正的职业人是十分关键的。

DBA需要有决断的性格。虽然强调DBA不能胆子太大,但是在某些情况下,DBA必须决断。有一次客户的数据库出现了严重的问题,导致宕机,启动后没多久再次宕机,客户也十分着急,由于时间十分紧迫,现场工程师和我们在二线做支持的人都没有足够的时间去进行分析,我当时感觉和我以前碰到的一个BUG十分类似,不过从CALL STACK来看,还是有些差别。当时现场工程师就不敢做这个决定,我说这种时候了,如果这个补丁不起作用,我们的服务也就做到头了,这种情况下目前没有别的思路,但是我们目前什么都不做,肯定是不行的,所以立即打补丁。幸运的是,补丁打上之后,数据库恢复正常了。决断不仅仅是一种性格,这种情况下,决断是基于一定的条件的,因为我知道,哪怕这个补丁不能解决问题,也是没有副作用的。对风险的理解,是决断的基础。

DBA的责任心是十分关键的。我面试一个DBA,首先看到的不是他的技术能力有多强,而是他的工作态度和责任心。一个有责任心的人,哪怕技术水平稍微差一点,也不容易出大问题。而一个缺乏责任心的DBA,不亚于一颗定时炸弹。能把工作当成自己的事情的人,是肯定能够成为一个好的DBA的。在很多情况下,DBA的工作都是从纷繁的表象中去发现危险的存在,一个把工作当成苦差事的人,是很难做到这一点的。我平时很少会和同事发脾气,唯一的一次,是因为一件小事。当时客户的一个系统需要我们帮助做一个健康性检查,一共有10多套大型数据库,要在2、3天内完成巡检工作。当时有三个人一起参与巡检,采用的方式是集中采集数据,集中编写报告的方式,这种方式一般来说我们很少采用,因为这种方式可能导致巡检的质量下降,不过由于时间紧迫,也只能采用这种权宜之计了。在做巡检之前,我就和哥几个说虽然时间紧,但是一定要认真。虽然哥几个答应的挺好,不过报告出来后,我感觉还是过于粗糙。我只好打回去让他们整改,整改了2、3次还是难以让人满意。事后我和哥几个说,如果你把这件事当成一个工作,确实让一个人在这么短时间里做这么多库的巡检,难免会有些枯燥,质量下降也是难免。不过如果你是以前的手工艺者,做巡检就是我们的手艺,你拿出的活能不能对得起自己这点手艺呢?大家听后都感触颇深,既然我们吃这碗饭,那么我们就应该拿出对得起这碗饭的手艺。现代社会比较浮躁,大家都是为了生活而工作,工作已经不是目的而只是手段,这一点我也能够认同,不过人除了物质的东西,总还是需要一些形而上的信仰来支撑自己,否则会失去很多乐趣的。这种信仰就是手艺人赖以生存的基础,失去了这些信仰,把DBA工作当成纯粹的谋生手段,那么你还会为了解决一个问题而兴奋不已吗?还会为了自己的失误而感到懊悔吗?

每一个准备做DBA这个工作的人,无论自己的职场规划是如何的,作为DBA就应该明白自己承担什么样的责任。摆在我们面前会有很多的诱惑,你面对的是企业最为宝贵的财富--数据库。可能你干一辈子的收入还不如把其中一小部分数据复制出去卖给别人赚的多,但是你必须守住自己的信念,你必须对得起自己,对得起自己的衣食父母。记得刚刚工作的时候,我在DEC软件中心,帮助香港氧气公司移植他们的核心业务系统,我负责的工作就是将香港氧气公司的TME数据库里的数据移植到OPENVMS的RMS系统中去。我第一次接触数据之前,老板让我签署了一个保密协议,他当时对我说,这些数据,随便拿出一些,你就可以卖出几十万的价钱,但是我相信你不会这么做,作为职场中的人,这是最起码的道德底线,今后你可能会遇到很多类似的事情,只要你一次触动了底线,那你就万劫不复了。作为DBA,那根底线是绝对不能突破的,这不仅仅是道德的问题,实际上这个底线是对我们最好的保护。

一个人的性格是天生的,不过也是可以改变的,如果一个人想去做一件事情,并且不断的在努力,成功的机会是很大的。连郭靖这种蠢笨如牛的人都可以成为一代宗师,你想成为一个DBA又有何难呢。虽然说不是所有的人都适合做DBA,不过这一切对于一个努力的人来说,都不成问题。性格是可以改变的,习惯是可以改变的,为了自己的目标,可以改变一切的人,那么还有什么不能实现吗?我们公司有一个小伙子,性格极为内向,和同事在一起上班,可以一天只说1、2句话,甚至一句话不说。有一次去客户现场工作了2个多月,我们给他一个额外的任务就是请客户的DBA吃一顿饭,就是这么一个很小的任务,他最后都没有完成。按理说,这种性格的人,是很难成为一个合格的DBA的,因为DBA需要和别人沟通,作为DBA,三分靠技术,七分考沟通。就是这样一个内向的人,在大家的努力下,通过一年的时间,居然有了很大的改变,首先是和自己同事之间的沟通多了起来,和客户之间的交流也逐渐好了起来,虽然和其他工程师比较,他还是属于沉默寡言的那一类人,不过可以看得出,他一直很努力的克服自己的瓶颈,而且我们也看到了他的努力所得到的成果,我想再有1、2年的时间,他会成功的。在这一节的最后,我举这个例子,就是想说DBA的最后一个,也就是最重要的性格--坚持。大家应该都看过士兵突击,许三多不是一个当兵的料,不够他在战友的帮助下,一直坚持着,最后成就了兵王。在这个故事里,有两个重要的要素,一个是许三多的坚持,一个是战友的坚持。钢七连的"不抛弃,不放弃"的信念是成功的关键。对于一个刚刚走入职场,想成为一个成功的DBA的人,这个信念尤为重要。

每日一技 我成长之路


http://blog.oraclefans.cn/baishan1/entry/dba%E6%97%A5%E8%AE%B0_%E5%89%8D%E8%A8%80%E4%B9%8B%E6%88%91%E7%9A%84%E6%88%90%E9%95%BF%E4%B9%8B%E8%B7%AF

0.1.1. 每日一技 我成长之路

每日一技将是DBA日记第一部中的重头戏,在日记之后会将和日记相关的技术问题进行一个较为深入的讨论,以便于读者更好的掌握工作方法与相关技术。

作为一个DBA在其成长过程中,所需要学习的不仅仅是技术,现在介绍ORACLE技术的书籍已经相当多了,通过对这些书籍的阅读,DBA应该能够学到足够的专业知识了。不过大家可能都有这样的感觉,刚开始学oracle的时候觉得OCP是一道十分高的门槛,总觉得不知道自己需要花上多少时间才能达到那个境界。而事实上,真正想要去考OCP认证,花上半年到一年的时间也就足够了。而通过OCP认证考试后,自己还是感觉到心里空空的,碰到问题还是找不到解决的方法。

实际上如果真正的认真学习了ocp的课程,了解了oracle的一些基本原理,通过OCP考试后,理论上已经具有了相当的基础了,只是oracle DBA工作不是考试,OCP的理论也只是一个初级的理论,如何将这些理论知识融会贯通,实际应用到日常的工作中去,是十分关键的,这一点也就是我们常说的工作方法。作为一个DBA,除了学习理论知识外,学习工作方法也是十分关键的。因为DBA是一个职业,而不是一门课程,理论知识只是基础,只有理论基础是远远不够的。我碰到过很多正在学习ORACLE的朋友,他们很容易走入两个极端,一种是仅仅注重理论,看了很多书,但是总是感觉看书的时候好像什么都懂了,一放下书就觉得好像什么都没学到,真正碰到问题的时候还是两眼一抹黑;另外一种是另外一个极端,觉得读书太枯燥,总是喜欢自己摸索,他们哪怕碰到一点点小问题,都会去寻求其他人的帮助,而不愿意自己去书本里学习。实际上,一个DBA成长的过程中,需要读书和实践有机的结合,读书固然很重要,不过没有实践操作,书中学到的知识无法巩固下来。

不过并不是每个人都有条件能够参加各种实践活动的,特别是刚刚入门的DBA,他们往往缺少大型项目和大型数据库维护的经验,这对于他们在技术上的提高是很不利的,这个时候,其他人的经验就是很好的教材。DBA日记的目的是把我这些年在DBA工作中碰到的一些典型的案例,用一种很轻松的方式说出来,让大家在看这些案例的时候学习到分析问题的方法,如果看DBA日记的时候,仅仅去关注那些技术性的东西,那就本末倒置了,DBA日记的真正精华是那些象流水账似的东西。所以大家不要把DBA日记当做一本技术宝典来使用,DBA日记里涉及的技术都是大家在其他地方能够学习到的,所以DBA日记也不会大篇幅的去介绍这些技术。大家更应该看到的是老白在碰到各种问题的时候,是如何处理的,是如何把一些很基本的技术运用到这些项目中去的。

DBA日记已经在我的博客上连载了大半年了,在这期间,有些朋友在其中看到了一些共鸣性的东西,有些朋友说看不太懂,有些朋友说深有启发。那些感到共鸣的人大概从事DBA工作已经有一段时间了,确实DBA日记是比较真实的,虽然也有一些艺术的夸大,但是其基础是真实可信的。

那些感到看不懂的朋友,还是没有理解我的意思,实际上DBA日记里面就像流水账一样记录了一些DBA日常的工作。所以你觉得看不懂的时候,可能是你还没有碰到过那种情况,你不需要理解其中的每个技术细节,看不懂的地方完全可以跳过,这并不妨碍你看其他的章节(当然在DBA日记中有些问题的处理过程写的过于简化,不利于读者看懂,因此在修订DBA日记的时候,老白已经将这些案例的处理过程细化)。另外对于刚刚入门的DBA来说,这本书的第一部从一个优化的案例入手,可能确实会感觉有点不容易摸到头脑,不过不要紧,你完全可以把这本书当做一本写的比较烂的小说来看,跳过那些生涩的技术描述,提前体会一下一个DBA做优化项目的时候会遇到些什么问题,并且如何面对这些问题。只要你理解了DBA分析问题的思路与方法,这本书对于你来说就是值得的了。

那些感觉深有启发的人,应该是刚刚进入DBA行业几年的年轻人。这本书中的很多技术都是这些DBA目前正在接触和使用的。而他们又往往缺乏接触大型优化项目的机会,这本书可以作为一本不错的教材。前几天有个网友问我,他正准备接手一个优化项目,能不能给他介绍一下优化项目该怎么做。我推荐他到我的博客上去看看DBA日记。DBA日记只是一本书而已,也许和你以前看到的Oracle的书有点不同,不过书仅仅就是书,如果你认为看过一本书就能成为高手,那就错了。

每个DBA的成长之路是完全不同的,我可以把我如何学习oracle的告诉大家,给大家一个参考。我开始接触Oracle的时候,在国内接触Oracle的人还是少数。当时唯一能够找到的Oracle的资料除了Oracle的随机文档外,就只有太极出的那套VAX技术书籍里寥寥可数的几个薄薄的小册子了。刚开始的时候仅仅是安装Oracle,最早是OPENVMS平台,后来逐渐转移到UNIX平台,SCO UNIX,DIGITAL UNIX,IRIX,SUN OS,...。Oracle 5、6在性能优化上没有什么可做的,主要是针对SQL进行优化,维护管理也较为简单,主要是表空间管理。那时候的系统也比较小,一般都在几百M到几个G之间,所以也很少能够碰到ORACLE 的BUG。不过在这段时间里,有较多的机会接触小型机、网络、操作系统和应用开发,这些经历都让我在今后的DBA生涯受益匪浅。随着DBA工作做的越来越专一,接触数据库以外的工作就越来越少,到目前为止,可能除了数据库以外,其他的技术都基本上都是停留在理论上了。在做DBA初期,多接触一下其他的技术,是十分好的,随着时间的推移,年龄的增长,学习能力和学习新东西的速度都会有不小的下降。

特别值得一提的是,应用软件开发方面的经验对我的DBA工作帮助良多。DBA是在和系统和应用打交道,而不是仅仅和数据库打交道,因此应用软件开发、应用软件体系架构方面的经验和知识是必不可少的。在成为一个完全的DBA之前,我曾经是一个系统架构师,设计过大量的应用软件,因此在分析一个系统的时候,我往往能够从开发者的角度去考虑问题,在处理问题的时候就比较能够抓住关键,提出的建议也能够切合实际。我经常看到一些DBA给系统提出的建议,从oracle数据库的理论上来看这些建议没有问题,不过作为一个系统来说,这些建议的针对性不强,可操作性就很低了,这种建议哪怕提出的再多,再深刻,包含的技术含量再高,也是没有多大价值的。

在刚刚进入DBA这个行业,特别是刚刚工作的时候,应该多接触一些应用开发、系统体系架构、IT架构方面和硬件的知识。这些知识的学习不能停留在表面上,而应该较为深入的去了解。做过系统工程师或软件工程师的DBA往往更容易成功。最理想的状态是在做DBA之前做过1、2年开发,还从事过个把年的硬件工程师。实际上在DBA的工作中,不断的要面对应用软件和系统硬件方面的问题,在实际工作中,也会不断的学习这些方面的知识。如果你并没有象我说的那样在DBA这个职业之前从事过软件开发或者硬件维护的工作,那也没有什么关系,在DBA工作中,尽可能多的去学习这方面的知识就行了。

在92年到98年这几年里,我逐渐从安装Oracle转向在oracle上做各种应用软件,在使用过程中也经常对数据库进行简单的性能分析和优化。在那段时间里,Oracle相关的书籍也逐渐多了起来,通过阅读,对Oracle的一些基础知识有了一个整体的认识。在性能分析方面,学会了使用bstat/estat工具,这个工具就是现在著名的STATSPACK工具的前身,在Oracle 7上,可以使用这个工具来进行OWI的分析。不过那段时间里,对于oracle的知识的学习还不是很系统的,主要是在工作中遇到什么问题,就去学习什么知识。99年的时候一个偶然的机会读了一下oracle concepts,感觉这本书对我的帮助很大,很多以前工作中碰到的疑点都在这本书里找到了答案,所以我会给每个Oracle入门者推荐这本书,认真读几遍oracle concepts,比学习一些独门秘籍要有用的多。

99年的时候由于要给几个客户做一些维护工作,对Oracle的知识做了一些梳理,梳理的过程中也阅读了一些oracle的书籍,这个期间最大的发现是METALINK,由于给客户做相关的服务,从客户那里拿到了 METALINK账号,从那时开始,我发现以前想从书籍上获取的知识绝大多数都能够在METALINK上获取。通过对ORACLE概念的阅读,我已经基本上掌握了Oracle的基本概念和体系,知道了SGA,PGA,UGA等基本的概念,但是这些概念在我的脑子里还是凌乱的,不成体系的,粗浅的。这些概念对于我做一些复杂的分析,帮助不大,我需要更加深入的理解这些概念。在99年到2000年这段时间里,由于客户的水平和维护需求也相对较低,所以虽然我在协助客户进行数据库维护,实际上,大多数工作是较为初级的工作。这段时间里我花了大量的精力在METALINK上阅读技术文档,这个时侯的主要学习任务是扩大知识面,Oracle是十分庞大的体系,其广度十分大,如果要掌握Oracle的一些基本技术,必须花费足够的时间。在这之前,我的Oracle知识主要集中在和应用软件相关的方面,通过这段时间知识面的扩展,一些oracle的主流技术、工具基本上都有了一个初步的认识。这段时间的学习,对于主业是系统架构设计的我来说,也是帮助十分大的,因为这段时间里我面对的主要系统还是使用Oracle。由于对Oracle数据库了解的深入,在我进行系统设计的时候,就不自觉的从Oracle的角度去考虑应用软件,使应用软件能够更加适合Oracle,更多的利用Oracle的新技术。

2000年开始,我突然想写一本书,书名叫《Oracle深度历险》,这本书包括第一章 Oracle基础知识,第二章 SQL与Oracle数据库编程,第三章 深入了解Oracle数据库 ,第四章 OEM与其他Oracle第三方工具,第五章 备份恢复与容灾,第六章 Oracle数据库性能优化。为了编写这本书,从2000年到2003年,我阅读了大量的Oracle数据库方面的技术资料和书籍。其中第三章的内容是介绍Oracle基本原理的,因此我查找了数百篇关于Oracle内部原理的技术资料,其中大多数来自于METALINK,在收集资料的过程中,我也得到了美国和澳洲Oracle公司朋友的大力协助,获得了大量的INTERNAL ONLY的文档,这些文档对于我理解Oracle的内部原理帮助十分大,这些文档我已经陆续发布在Oracle粉丝网(http://www.oraclefans.cn)上了。《Oracle深度历险》的编写工作历时3年,不过2004年我第二次修改这本书的时候,我决定放弃这本书,因为那时候Oracle的技术书籍已经相当丰富了,《oracle深度历险》中的绝大部分内容都已经有了,再出版这样一本书没有任何意义。虽然《Oracle深度历险》夭折了,不过写书的目标让我在2、3年时间里,对Oracle重新梳理了一遍,对Oracle的认识更加深入了。在写书的过程中,对于每个知识点,如果能够进行实际操作的,我必须亲自操作一遍,确定没问题,才会写入深度历险。这段时间的写作虽然没有写出一本好书,不过写书的经历对我来说是一笔十分宝贵的财富。所以我也经常建议公司的员工,不要光看书,看书的时候一定要自己亲自做一遍,然后再把做的过程写成文档,书上的东西才能真正变成自己的。其实这个过程包含了几个步骤,第一个步骤是通过读书学到了新的知识,然后通过自己的亲自实践,将书中学到的新知识得到一个感性的体验,最后将这个体验用自己的语言描述出来,那么这个知识点就记住了。如果不这么做一下,读书的效果就要打很大的折扣了。

对于DBA来说,写博客是一个不错的主意。将自己学习的成果通过博客整理出来,既可以起到整理思路,完善知识点的掌握的作用,又可以通过博客和其他DBA进行交流,为其他正在学习中的人提供技术资料,最终达到群体学习的目的。我经常建议公司的年轻人群体学习,群体学习说起来很简单,就是如果存在一些知识点,有几个人都想去学习,如果每个人都是独立的去学习可能需要花费1、2个月的时间,如果换一种学习方法,就是几个人分分工,每个人学习一个知识点,然后通过互相交流的方式,大家互相传递知识,这种学习方法,可能可以缩短一倍的学习时间,而且学习到的知识的深度也会高于一个人自己学习。群体学习的前提条件是,一起学习的人的技术层面基本接近,而且大家都很开放,都愿意把自己的知识拿出来和大家分享。

到达一定的阶段后,很多DBA会感觉遇到了一个瓶颈。这个瓶颈我也曾遇到过。2003年到2004年这段时间里,我经常感觉到碰到了天花板的感觉,这段时间里我在经营一家软件公司,最初的时候还自己写一些代码,随着公司越来越大,最后连系统架构都交给了技术总监,从那时候开始我离开发就越来越远了,不过也有更多的时间研究Oracle相关的技术。这段时间给客户做优化的项目比较多,在做项目的时候,总是感觉很难很快的抓住问题的核心。在这段时间里,阅读了大量Oracle INTERNAL和优化相关书籍,包括《Cost Based Oracle Fundamentals》、《oracle 8i internal services for waits latches locks and memory》、《Inner look on Oracle latches》、《Oracle performance tuning & tips》、《Oracle 9i tuning guide》(oracle官方文档)、《DSI 401E》、《DSI 402E》等。实际上来说这些书籍,每一本都对我理解Oracle有很大的帮助,不过每一本都没办法解决我的所有的问题,在很多地方涉及到内部原理和算法的时候也往往都是点到即止。DSI是Oracle内部培训教材,也是广大DBA追逐的目标。认真学习一下DSI对理解Oracle内部原理是有很大帮助的,不过想理解ORACLE内部原理并不只有DSI一条路,说实在的,DSI的文档,我手头有一些,不过真正认真去看过的,也只有DSI 401E和DSI 402E这两个。现在DSI的文档在互联网上很容易下载到,系统的学习一下DSI课程对于DBA来说是个不错的选择。

除了读书外,还有很多问题是书本无法回答的,所以我也在互联网上查找更多的关于Oracle内部原理的文档,通过GOOGLE和百度去搜索更多的Oracle技术网站。http://ixora.com.au是一个相当不错的网站,上面有很多关于ORACLE INTERNAL的资料,虽然资料基本上都是基于8i的,不过资料十分权威。ASKTOM网站也是这段时间经常访问的网站,最初知道ASKTOM是通过GOOGLE搜索的时候,基本上都有链接指向ASKTOM,从ASKTOM,我学习到了TOM分析问题的思路和方法,这一点对于我今后自己处理问题是十分有帮助的。

至于国内的网站,那时候ITPUB和ORACLE.COM.CN比较热门,开始的时候也经常在这两个网站上讨论一些技术问题。随着这两个网站上一批DBA的水平越来越高,这两个网站上技术交流的质量却越来越低,在国内的网站上很难找到我所需要的资料,所以我把目标面向了英文网站。国外的ORACLE技术网站很多,不过大多数都是会员制的收费网站,少量免费网站(比如ITTOOLBOX)上面的技术水平又普遍比较低,所以找了一圈网站,最后还是觉得学习ORACLE,最好的网站还是METALINK。这段时间由于ben的帮助,获得了不少Oracle内部的技术资料,通过对这些资料的学习,很深入的了解了Oracle内部的一些算法,这些学习过程,对我突破这个瓶颈起到了很至关重要的作用。

在这个突破瓶颈的阶段,我的学习方法是对于某一个知识点,深入的研究下去,并尽可能的把相关知识点也融会贯通,特别是两个知识点的结合部。为了了解数据块的结构,我花了相当长的时间去DUMP数据块,甚至编写了一些小程序去读取数据块中的数据,这个时候,以前搞开发时候深厚的c语言功底起到了很好的作用。对于绝大多数DBA来说,完成好日常工作并不需要学习那么多内部原理性的东西,不过如果你有兴趣,并且有足够的时间,那么深入研究Oracle的内部结构和原理是十分有趣的事情。至少对于我来说是这样的,从BUG报告生涩的文字和少量的内部代码里分析Oracle内部实现的原理和看一部好的小说一样有趣。上大学的时候也刚毕业的时候喜欢看一些散文和诗歌,而现在我阅读的对象除了轻松的商业小说外,就只剩下METALINK文档了,这是一个爱好问题,已经可以说与ORACLE技术无关了。

对于绝大多数DBA来说,可能他们缺少实践的机会,这对于DBA这个职业来说是十分致命的,可能会影响到DBA的成长。我第一次做优化项目的时候,虽然说那时候我已经具备了很深的理论知识,从事Oracle维护工作也有几年时间了,不过在项目开始之初,还还是碰到了很多意想不到的困难,甚至有时候出现了方向上的偏差。这实际上和实际工作经验是息息相关的,哪怕你的理论水平再高,没有真正做过几个优化项目,是很难真正理解什么叫优化的。对于缺乏实际工作经验的DBA,在ITPUB、METALINK、OTN等论坛或者QQ群里帮助别人解决问题,是一个十分好的办法,你可能会碰到各种各样的案例,都是你目前工作环境中无法碰到的,通过接触这些实际的案例,可以弥补你在实际工作经验上的不足。从04年起,我建立了自己的ORACLE讨论群"白鳝的洞穴",在这个群里,帮助网友解决问题是一件十分有趣的事情,很多案例可能在日常的维护工作中你无法遇到,不过通过QQ群你可以接触到更多的实际案例。

当你通过了OCP甚至OCM认证考试后,你的理论知识积累已经达到了一定的程度,这个时候,如果你不能从事相应的工作,在这些工作中把你的理论知识消化,并融入你的思维当中,这些理论知识很快会在你的头脑中消失。过上1到2年,这些理论知识就会被忘的干干净净。所以说,通过认证考试不是目的,只是一个过程。当然拥有OCM证书,会给你的职场生涯带来很多好处。

理论知识的学习是十分枯燥的,很少有人原意一遍一遍的阅读ORACLE CONCEPTS,虽然这么做对你的Oracle理论知识的提升帮助很大。Oracle的知识面很广,一个人也很难有机会把所有的ORACLE知识都认真的梳理学习一遍。给别人讲课是学习理论的一个很好的途径,我有一些知识就是通过给别人培训学习的。比如说DATA GUARD,对于DATA GUARD的原理,我大体了解,这是从REDO LOG的结构方面可以推断出来的,不过具体的一些技术细节以及实现方法,就知之甚少了。有一次需要给一个客户讲DATA GUARD的课程,我花了差不多两天的时间来整理培训讲义,并且准备了一个学生实际操作用的WORKSHOP,设计了几个常见的演练场景。通过这个备课过程,对DATAGUARD的原理、配置管理和维护的基本操作就了解的十分清楚了。几年过去了,虽然DATA GUARD的技术在不断演进,我在这几年里也没有做过DATA GUARD的项目,但是通过那次讲课,DATA GUARD已经深深的融入了我的血液里,再也不会忘记了。随着数据库新版本的推出,GATA GUARD技术在不断的演进,不过其主体技术是不会发生大的变化的,因此这些知识,在有了一定基础后,只需要你在使用前再去RENEW一遍就足够了,不需要花更多的精力去更新。

有些知识点,平时可能不会注意,不过如果你要给别人讲课,就需要你真正认认真真的把这些知识点一个一个搞清楚,因为没有一个老师原意在课堂上被学生们问的哑口无言。记得刚刚工作的时候,公司派我给一个客户讲RDB数据库,在这之前我连RDB数据库是什么样都不知道,那时候在DEC公司,老板是香港人,给我留下一本讲义一本RDB的REFERENCE,给了我3天的时间准备。那是一个十分艰苦的任务,我给客户讲了近10天的RDB课程,每天晚上我通过阅读讲义和参考手册备课,对于讲义上的每个WORK SHOP都要首先做一遍,第二天再教给学员们。10天的课程终于讲完了,没有一个学员看出我也是第一次学习RDB。通过那次讲课,我对RDB数据库的了解比公司里其他员工都要深。10多年后的一天在一个客户那里,听说他们有一个RDB数据库里有一批很重要的数据想搞出来,不过没有人懂,所以只能通过应用程序显示在终端上,然后由一个人一点一点的抄下来。我听说后凭着那次讲课留下的对RDB的印象,居然帮用户把数据导成文本格式,然后通过SQL LOADER装载到了ORACLE数据库里。

最后要说的是,DBA是一个工作,一个还算不错的工作,但是并不是每个人都需要把DBA当做一种生活。因此对于技术的追求并不是每个人的生活目标,如果你喜欢ORACLE,那你不妨把阅读枯燥的理论知识和越多干涩的TRACE文件当成一种乐趣,否则,就把它当成一种工作,一种生活中的点缀吧。

2011年12月19日 星期一

2-0-1 SQL JOIN 語法說明



SQL 語法中的 Left Join,是一個非常重要的語法;用以下的實例來說明,應該比較容易瞭解。Table 範例如下:

table : Users
userId named companyNo deptNo
1 Scott c01 d01
2 Tiger c01 d02
3 Jacky c01 d02
4 Polin c01 d03
SQL:
?
1
2
3
4
5
6
create table users ( userId char(4), name varchar2(16),
                     companyNo char(3), DeptNo char(3) );
insert into users values( '0001' , 'Scott', 'c01' , 'd01' );
insert into users values( '0002' , 'Tiger', 'c01' , 'd02' );
insert into users values( '0003' , 'Jacky' , 'c01' , 'd02' );
insert into users values( '0004' , 'Polin', 'c01' , 'd03' );
table : Companys
companyNo name
c01 ABC Corp.
c02 XYZ Corp.
SQL:
?
1
2
3
create table Company ( companyNo char(3), name varchar2(16) );
insert into Company values( 'c01' , 'ABC Corp.' );
insert into Company values( 'c02' , 'XYZ Corp.' );
table : Depts
companyNo DeptNo name
c01 d01 Account
c01 d02 Sales
c01 d03 MIS
c01 d04 HR
SQL:
?
1
2
3
4
5
create table Depts ( companyNo char(3), deptNo char(3), name varchar2(16) );
insert into Depts values( 'c01' ,'d01' , 'Account' );
insert into Depts values( 'c01' ,'d02' , 'Sales' );
insert into Depts values( 'c01' ,'d03' , 'MIS' );
insert into Depts values( 'c01' ,'d04' , 'HR' );
需求一: User 屬於那一個公司,那一個部門的 SQL:
?
1
2
3
4
5
SELECT u.*, d.name as deptName, c.name as companyName
FROM users u , depts d, company c
WHERE 1=1
AND u.deptNo = d.deptNo
AND u.companyNo = c.companyNo
結果:
USERID  NAME COMPANYNO DEPTNO DEPTNAME COMPANYNAME
1 Scott c01 d01 Account ABC Corp.
3 Jacky c01 d02 Sales ABC Corp.
2 Tiger c01  d02  Sales  ABC Corp.
4 Polin c01  d03  MIS  ABC Corp.
需求二:列出所有部門的人員,部門若沒有人員也要列出:
?
1
2
3
4
SELECT d.*, u.name as userName , c.name as companyName
FROM depts d
LEFT JOIN users u ON d.deptNo = u.deptNo
INNER JOIN company c ON d.companyNO = c.companyNo
結果:
COMPANYNO  DEPTNO NAME USERNAME COMPANYNAME
c01 d01 Account Scott ABC Corp.
c01 d02 Sales Jacky ABC Corp.
c01 d02 Sales  Tiger ABC Corp.
c01 d03 MIS  Polin ABC Corp.
c01 d04 HR (null) ABC Corp.
PS: 若仍用需求一的方法,則無法顯示 d04 HR 部門:
SQL:
?
1
2
3
4
5
SELECT d.*, u.name as userName , c.name as companyName
FROM depts d, users u, company c
WHERE 1=1
AND d.deptno = u.deptno
AND d.companyno = c.companyno

結果:
COMPANYNO  DEPTNO NAME USERNAME COMPANYNAME
c01 d01 Account Scott ABC Corp.
c01 d02 Sales Jacky ABC Corp.
c01 d02 Sales  Tiger ABC Corp.
c01 d03 MIS  Polin ABC Corp.
 整理一下這三個 JOIN 的特色如下:
  • INNER JOIN - 兩邊的資料表擁有相同的優先權,要兩邊都有的資料才會被包含在新的資料表。
  • RIGHT JOIN - 右邊的資料表擁有優先權,右邊所有的資料都會被包含,而左邊只有符合的資料才會被包含。
  • LEFT JOIN - 左邊的資料表擁有優先權,左邊所有的資料都會被包含,而右邊只有符合的資料才會被包含。

Oracle To_Date Function 由文字格式轉成日期格式



 to_date function :由文字格式轉換成日期格式
在使用此函式時,可以下列 SQL 來查詢目前的日期格式為何:
?
1
2
3
4
5
6
SELECT parameter, value FROM v$nls_parameters
where parameter='NLS_TIMESTAMP_TZ_FORMAT';
 
select to_char(sysdate,'DD-MON-RR') from dual;
 
select to_date('06-9月-10') from dual;
to_date function 語法如下:
to_date( string1, [ format_mask ], [ nls_language ] )
  • string1文字格式的日期
  • format_mask選用,將  string1 轉換成此格式的日期
  • nls_language is optional: This is the nls language used to convert string1 to a date.
 The following is a list of options for the format_mask parameter. These parameters can be used in many combinations.
Parameter Explanation
YEAR Year, spelled out
YYYY 4-digit year
YYY
YY
Y
Last 3, 2, or 1 digit(s) of year.
IYY
IY
I
Last 3, 2, or 1 digit(s) of ISO year.
IYYY 4-digit year based on the ISO standard
RRRR Accepts a 2-digit year and returns a 4-digit year.
A value between 0-49 will return a 20xx year.
A value between 50-99 will return a 19xx year.
Q Quarter of year (1, 2, 3, 4; JAN-MAR = 1).
MM Month (01-12; JAN = 01).
MON Abbreviated name of month. 簡短月份
MONTH Name of month, padded with blanks to length of 9 characters.
RM Roman numeral month (I-XII; JAN = I).
WW Week of year (1-53) where week 1 starts on the first day of the year and continues to the seventh day of the year.
W Week of month (1-5) where week 1 starts on the first day of the month and ends on the seventh.
IW Week of year (1-52 or 1-53) based on the ISO standard.
D Day of week (1-7).
DAY Name of day.
DD Day of month (1-31).
DDD Day of year (1-366).
DY Abbreviated name of day.
J Julian day; the number of days since January 1, 4712 BC.
HH Hour of day (1-12).
HH12 Hour of day (1-12).
HH24 Hour of day (0-23).
MI Minute (0-59).
SS Second (0-59).
SSSSS Seconds past midnight (0-86399).
FF Fractional seconds. Use a value from 1 to 9 after FF to indicate the number of digits in the fractional seconds. For example, 'FF4'.
AM, A.M., PM, or P.M. Meridian indicator
AD or A.D AD indicator
BC or B.C. BC indicator
TZD Daylight savings information. For example, 'PST'
TZH Time zone hour.
TZM Time zone minute.
TZR Time zone region.
參考文章:http://www.techonthenet.com/oracle/functions/to_date.php

oracle 日期常用函數 (SYSDATE、日期格式)


http://forum.twbts.com/thread-5218-1-1.html

--◎ 可得到目前系統的時間  
select sysdate from dual;

--◎ 常用之日期格式

日期格式                 說明
------------------------------------------------------------------------
YYYY/MM/DD                                           -- 年/月/日
YYYY                                                              -- 年(4位)
YYY                                                                 -- 年(3位)
YY                                                                    -- 年(2位)
MM                                                                 -- 月份
DD                                                                   -- 日期
D                                                                      -- 星期      (星期日 = 1  星期一 = 2 星期二 = 3  星期三 = 4  星期四 = 5 星期五 = 6 星期六 = 7 )                      
DDD                                                               -- 一年之第幾天
WW                                                                -- 一年之第幾週
W                                                                    -- 一月之第幾週
YYYY/MM/DD HH24:MI:SS                  -- 年/月/日 時(24小時制):分:秒
YYYY/MM/DD HH:MI:SS                        -- 年/月/日 時(非24小時制):分:秒

select to_char(sysdate,'YYYY/MM/DD') FROM DUAL;       --2011/11/29
select to_char(sysdate,'YYYY') FROM DUAL;                          --2011
select to_char(sysdate,'YYY') FROM DUAL;                             --011
select to_char(sysdate,'YY') FROM DUAL;                                --11
select to_char(sysdate,'MM') FROM DUAL;                             --11
select to_char(sysdate,'DD') FROM DUAL;                               --29
select to_char(sysdate,'D') FROM DUAL;                                   --3
select to_char(sysdate,'DDD') FROM DUAL;                            --333
select to_char(sysdate,'WW') FROM DUAL;                             --48
select to_char(sysdate,'W') FROM DUAL;                                 --5
select to_char(sysdate,'YYYY/MM/DD HH24:MI:SS') FROM DUAL;       --2011/11/29 09:47:18
select to_char(sysdate,'YYYY/MM/DD HH:MI:SS') FROM DUAL;            --2011/11/29 09:47:32

ORACLE SQL 總整理 : 引用文章

http://pramaire.pixnet.net/blog/post/9170784


最近有使用到SQL語法,找到不錯的總整理,紀錄一下。
 引用文章:http://oracled2k.pixnet.net/blog/trackback/6922f661f0/24564662
Statement 陳述
Description 敘述
SELECT
Retrieves data from the database.

大寫字母
指令  keyword
小寫字母
由使用者決定(指定)
[ ]     
Optional(選項)  可有可無
;      
SQL Statement 結束符號並執行
{ }   
一定要,不可省略
|     
,    
逗號
…    
可重複輸入
Null Value
任何數和null做運算,其結果都為null
AS   
設別名時的Keyword
“  “   
使用別名時,有要區分大小寫時用此符號,無使用則都為大寫
||    
用在字串連結
‘  ’
用於所要顯示的字串或日期
DISTINCT
Keyword 用來排除重複資料
WHERE
條件子句,可指定特定的欄位,字串要分大小寫
DD-MM-RR
日期的格式,需依照建構資料的基本格式
Equal to
Greater than
>=
Greater than or equal to
Less than
<=
Less than or equal to
<>
Not equal to  (不等於)

DESC employees  為檢視employees 這個table的欄位格式
BETWEEN…AND…
區間設定值,介於2值之間
WHERE  salary  BETWEEN  2500  AND  3500;
IN(SET)
為值的列表;SET為集合
WHERE  manager_id  IN (100, 101, 201);
LIKE
用於模糊比對
此符號為0~多字元的模糊比對
此符號為單一值的模糊比對
WHERE  fist_name  LIKE ‘S%’;(為S開頭的字母以下模  糊比對) 
WHERE  fist_name  LIKE ‘_o%’;(為第一個字模糊比對第2的字元為o的字母以下模糊比對)
若想要select的字串裡有%和_時,用ESCAPE來定義跳脫字元
WHERE  job_id  LIKE ‘%SA\_%’ESCAPE ‘\’;(此就可以顯示出_的符號,可參考P2-13)
IS NULL
WHERE  manager_id  IS NULL ;(顯示出manager_id為NULL的欄位)
AND
2者為真,則傳回為真
WHERE  salary  >=1000
   AND  job_id  LIKE ‘%MAN%’;(2者皆符合的資料才顯示)
OR
2者其一為真,則傳回為真
WHERE  salary  >=1000
    OR  job_id  LIKE ‘%MAN%’;(2者中其一的資料符合者就顯示)
NOT
用於不想顯示的
WHERE  job_id  NOT  IN (‘IT_PROG’,’ST_CLERK’); (job_id為此2者時,不顯示其他的資料就顯示)P2-18
規則順序
  1.  算數的運算
  2.  關聯的運算
  3.  比較條件
  4. IS [NOT] NULL,LIKE,[NOT] IN
  5. [NOT] BETWEEN
  6. NOT  logical condition
  7. AND  logical condition
  8. OR    logical condition
WHERE  job_id  LIKE ‘SA_REP’j
    OR  job_id  LIKE ‘AD_PRES’ k
   AND  salary  > 1500 ; l  (先判斷2.3後再和1一起判斷)
WHERE  job_id  LIKE ‘SA_REP’
    OR  job_id  LIKE ‘AD_PRES’
   AND  salary  > 1500 ; (若加上()時,先判斷1.2後再和3一起判斷)
ORDER BY
用於指定的欄的排序,預設為ASC(遞增);DESC(遞減)
ORDER  BY  hire_date; (預設為ASC)
ORDER  BY  hire_date  DESC; (為遞減)
ORDER  BY子句的寫法:支援多個column的排序
  1. BY  column  欄位
  2. BY  column  alias  欄位別名
  3. BY  expression  欄位運算方式
  4. BY  position  欄位編號
ORDER  BY  department_id, salary  DESC;(先照department_id的遞減排序在照salary的遞減排序)

Case  Manipulation  Functions
LOWER
將字串轉為小寫,可用於欄位
LOWER ('TEST');結果為test
LOWER(job_id);結果會顯示job_id都為小寫的
UPPER
將字串轉為大寫,可用於欄位
UPPER('TEST');結果為TEST
UPPER(last_name);結果會顯示last_name都為大寫
INITCAP
將字串的第一個字母轉為大寫其餘的小寫,可用於欄位
INITCAP('TEST');結果為Test

Character-Manipulation  Functions
CONCAT
值的結合
CONCAT('Hello','World');結果為HelloWorld
SUBSTR
獲得一個在決定長度內的字串
SUBSTR('HelloWorld',4,5);結果為loWor
LENGTH
查出此字串的長度
LENGTH('HelloWorld');結果為10
INSTR
查出指定字元在字串中第幾個位置
INSTR('HelloWorld','l');結果為3
LPAD
墊個字串值從右邊放起
LPAD(salary,10,'*');結果為*****24000,設定總共為10個數字其餘補上*
RPAD
墊個字串值從左邊放起
RPAD(salary,10,'*');結果為24000*****,設定總共為10個數字其餘補上*
TRIM
從設定的第一個字元以後才顯示
TRIM('H' FROM 'HelloWorld');結果為elloWorld
DUAL
FROM  DUAL與table無關的算式都可以用

Number  Functions
ROUND
四捨五入
ROUND(45.926,2);四捨五入到小數點第2位其結果為45.93
ROUND(45.926,-1);結果為50   ROUND(45.926);結果為46
TRUNC
無條件捨去
TRUNC(45.926,2);無條件捨去到小數點第2位其結果為45.92
TRUNC(45.926,-1);結果為40   TRUNC(45.926,-2);結果為0
MOD
餘數
MOD(1600,300);將1600除以300結果的餘數為100

Working  with  Dates
SELECT  SYSDATE
FROM  DUAL;   顯示現在的系統時間

Date  Functions
MONTHS_
BETWEEN
算在2個日期之間有多少個月,會有小數
MONTHS_ BETWEEN(‘01-SEP-95’,’11-JAN-94’) →19.677
ADD_MONTHS
依照設定的數字再加上現有的月份
ADD_MONTHS(‘11-JAN-94’,6) → ‘11-JUL-94’
NEXT_DAY
找出設定日期的下一個指定星期
NEXT_DAY(‘01-SEP-95’,’FRIDAY’) →’08-SEP-95’
LAST_DAY
找出設定日期的月份的最後一天
LAST_DAY(‘01-FEB-95’) →’28-FEB-95’
ROUND
Assume  SYSDATE = ‘25-JUL-95’
ROUND(SYSDATE, ‘MONTH’) →01-AUG-95
ROUND(SYSDATE, ‘YEAR’) →01-JAN-96
TRUNC
Assume  SYSDATE = ‘25-JUL-95’
TRUNC (SYSDATE, ‘MONTH’) →01-JUL-95
TRUNC (SYSDATE, ‘YEAR’) →01-JAN-95


TO_NUMBER
TO_CHAR
TO_CHAR
TO_DATE
CHARACTER
NUMBER
DATE









Explicit  Data-Type  Conversion

Elements  of  the  Date  Format  Modle
YYYY
SYSDATE, 25-4月 -05
TO_CHAR(SYSDATE,' DD MM YY') ,  →  25 04 05
TO_CHAR(SYSDATE,'DD MM YYYY') ,  → 25 04 2005
YEAR
TO_CHAR(SYSDATE,'DD MM YEAR') ,  → 25 04 TWO THOUSAND FIVE
MM
TO_CHAR(SYSDATE,'DD MM YY') ,  → 25 4月 05
MONTH
TO_CHAR(SYSDATE,'DD MONTH YY') ,  → 25 4月 05
MON
TO_CHAR(SYSDATE,'DD MON YY') ,  → 25 4月 05
DY
TO_CHAR(SYSDATE,'DY MM YY') ,  → 星期一 04 05
DAY
TO_CHAR(SYSDATE,'DAY MM YY') ,  → 星期一 04 05
DD
TO_CHAR(SYSDATE,'DD MM YY') ,  → 25 04 05

Sample  Format  Elements  of  Valid  Date  Fromats
WW or W
一年的第幾週or這個月的第幾週
DDD or DD or D
Day of year,month,or week

Date  Fromat  Elements:Time  Formats
AM or PM
TO_CHAR(SYSDATE,'AM HH DD MM YY'), → 下午 08 25 04 05只要設定一個就可以了
A.M. or P.M.
只要設定一個就可以了
HH or HH12 or HH24
TO_CHAR(SYSDATE,'HH DD MM YY'), → 08 25 04 05
TO_CHAR(SYSDATE,' HH12 DD MM YY'), → 08 25 04 05
TO_CHAR(SYSDATE,'HH24 DD MM YY'), → 20 25 04 05
MI
TO_CHAR(SYSDATE,'AM HH MI SS DD MM YY'), →下午 08 33 01 25 04 05
SS
TO_CHAR(SYSDATE,'AM HH MI SS DD MM YY'), →下午 08 33 01 25 04 05
SSSSS
TO_CHAR(SYSDATE,'HH24 MI SSSSS DD MM YY'), → 20 33 73981 25 04 05

Number  Format  Elements 設定之格式要寫在 '  ' 裡
9
99999 →1234
0
099999 →001234
$
$999999 →$1234
L
L999999 →FF1234
.
999999.99 →1234.00
,
999,999 →1,234
TO_CHAR(salary, '$99,999.00'), → $24,000.00
MI
999999MI →1234-  表示負號用的
PR
999999PR <1234>  表示負號用的
EEEE
99.999EEE 1.234E+03

General  Functions
NVL
給null value一個實際值
NVL(commission_pct,0)
NVL(hire_date,’01-JAN-97’日期要引號
NVL(job_id,’No Job Yet’ 字串也要引號
NVL2
NVL2(commission_pct,’SAL+COMM’,’SAL’),
SAL+COMM  當commission_pct不是null時就顯示
SAL          為null時則顯示SAL
NULLIF
NULLIF(LENGTH(first_name),LENGTH(LAST_name));
4 ; 6 ; 4     4 ; 4 ; 4
前後2者傳回值相等時,為null,不相等時,則為前一個傳回值
COALESCE
COALESCE(commission_pct,salary,10),
當commission_pct不為null時就顯示commission_pct的值,若為null時,就顯示salary的值

Conditional  Expressions
CASE
一個IF-THEN-ELSE的判斷句
CASE job_id WHEN 'IT_PROG' then  1.10*salary
            WHEN 'SA_REP'  then  1.20*salary
ELSE        salary  END  
當job_id為IT_PROG時slary*1.10,為SA_REP時slary*1.20,其餘的一樣為salary
DECODE
一個IF-THEN-ELSE的判斷句
DECODE( job_id ,'IT_PROG', 1.10*salary,
                'SA_REP' , 1.20*salary,
          salary )
當job_id為IT_PROG時slary*1.10,為SA_REP時slary*1.20,其餘的一樣為salary

Types of Joins
Equijoin
為一簡單或是內部的join
SELECT e.employee_id,e.last_name,d.department_id
  FROM employees e,departments d
 WHERE e.department_id=d.department_id; 值相同的join
Nonequijoin
SELECT e.salary,e.last_name,j.grade_level
  FROM employees e,job_grades j
WHERE e.salary BETWEEN j.lowest_sal AND j.highest_sal;
值不相同的,可用>= or<=,但是BETWEEN是最常用的
Outer Join
允許資料not match,主要表格(PT)均呈現,次要表格(ST)可不呈現。(+)為次要表格
SELECT e.department_id,e.last_name,d.department_name
  FROM employees e,departments d
WHERE e.department_id(+) =d.department_id;
Self Join
只在同個table執行
SELECT e.last_name||'  work for  '||d.last_name
  FROM employees e,employees d
WHERE e.manager_id = d.employee_id;

Joining Tables Using SQL
Cross Joins
作向量積的join
FROM employees 可改寫
FROM employees
 Cross join departments
Natural Joins
和Equijoin join 一樣 欄位名稱一定要一樣
FROM employees e,departments d
WHERE e.department_id=d.department_id  可改寫為
FROM employees 
NIATURAL JOIN departments
JOIN  USING
指定欄位的JOIN,不能用別名
FROM employees e,departments d
WHERE e.department_id=d.department_id
FROM employees e JOIN departments d
USING (department_id);

Creating Join with the on Clause

FROM employees e JOIN employees m
  ON  (e.manager_id = m.employees_id);

Creating Three-Way Join with the on Clause

WHERE d.dempartment_id = e.dempartment_id
   AND  d.location_id = l.location_id
JOIN departments d
 ON d.dempartment_id = e.dempartment_id
JOIN locations l
 ON d.location_id = l.location_id;

Oracle
SQL:1999
Equijoin
Natural or Inner Join
Outerjoin
Left Outer Join (Left;Right;Full)
Selfjoin
Join ON
Nonequijoin
Join Using
Cartesian Product
Cross Join

Left Outer Join
主要表格在左,次要表格在右,為之
FROM employees e, departments d
WHERE e.department_id = d.department_id(+); 
FROM employees e
LEFT OUTER JOIN departments d
ON (e.department_id = d.department_id);
Right Outer Join
主要表格在右,次要表格在左,為之
FROM employees e, departments d
WHERE e.department_id(+) = d.department_id; 
FROM employees e
RJGHT OUTER JOIN departments d
ON (e.department_id = d.department_id);
Full Outer Join
用於去年比較分析表
FROM employees e
FULL OUTER JOIN departments d
ON (e.department_id = d.department_id);

Tyoes of Group Functions
AVG
平均值,資料只能是數值,字串和日期不行
AVG(salary)
AVG(commission_pct);含null值時商變小
AVG(NVL(commission_pct,0));將null轉成0
COUNT
求資料列數的rows,number of rows,null不會顯示
COUNT(*);returns the number of rows in s table
COUNT(commission_pct);null不會顯示
COUNT(DISTINCT department_id);去除重複的資料在顯示rows
MAX
求最大值,任何資料型態都可
MAX(salary);MAX(hire_date)
MAX(AVG(salary)) 先求平均在找最大值
MIN
求最小值,任何資料型態都可
MIN(salary);MIN(hire_date)
STDDEV
標準平均差
SUM
加總,資料只能是數值,字串和日期不行
SUN(salary)
VARIANCE
變異數

Creating Groups of Data  資料分群組
GROUP BY
預設為ASC的排序,不能用欄位別名;任何一個欄位或是敘述不是一個合計的功能時,必須用GROUP BY
SELECT department_id, AVG(salary)
  FROM employees
 GROUP BY department_id先依照部門分組再算AVG(salary)
 BRDER BY AVG(salary);也可在接指定排序欄位
SELECT department_id,COUNT(last_name)
  FROM employees;  要改寫成
SELECT department_id,COUNT(last_name)
  FROM employees
 GROUP BY department_id;
HAVING
用來限制GROUPS
SELECT department_id,AVG(salary)
  FROM employees
 WHERE AVG(salary)>8000
 GROUP BY department_id; →要改寫成
SELECT department_id,AVG(salary)
  FROM employees
HAVING AVG(salary)>8000
 GROUP BY department_id;

Subquery Syntax

在Subquery裡不要用ORDER BY
SELECT last_name
  FROM employees
 WHERE salary >(SELECT salary
                  FROM employees
                 WHERE last_name ='Abel');
()內的條件會先去找出來,在和原來的salary比對

Types of Subquery
傳回一個資料
當在Subquery傳回的資料為多筆或是無資料時;則不能對應
SELECT last_name,SALARY
  FROM employees
 WHERE salary =(SELECT MIN(salary)
                  FROM employees);
()內傳回的為一單個資料
傳回一個以上的資料

IN
Equal to any member in the list
SELECT last_name
  FROM employees
 WHERE salary IN (SELECT salary
                   FROM employees
                  WHERE last_name ='Abel'); →
為一筆資料對應回去,也可寫 =
AND
任一的對應
SELECT last_name,job_id,salary
  FROM employees
 WHERE salary < ANY (SELECT salary
                       FROM employees
                      WHERE job_id='IT_PROG')
   AND job_id<>'IT_PROG'; 
判斷()內為傳回多筆資料(9000,6000,4200);回上層判斷要<這3筆資料,再和ANDㄧ起判斷;
ALL
完全的對應
SELECT last_name,job_id,salary
 FROM employees
WHERE salary < ALL (SELECT salary
                       FROM employees
                      WHERE job_id='IT_PROG')
   AND job_id<>'IT_PROG'; 
判斷()內為傳回多筆資料(9000,6000,4200);回上層判斷為ALL則是要<這3筆資料的最小的那一個,再和ANDㄧ起判斷
<ANY
小於最大值
>ANY
大於最小值
=ANY
Is equivalent to IN
<ALL
小於最小值
>ALL
大於最大值

當在Subquery裡有傳回的值為null,需將null排除
SELECT last_name
  FROM employees
 WHERE employee_id not in
          (SELECT manager_id
             FROM employees
            WHERE manager_id is not null);

出現一輸入視窗,欄位鍵入式查詢
適用於
WHERE conditions

ORDER BY clauses

Column expressions

Table names

Entire SELECT statements