从sqlplus登录,可以执行的语句五花八门,这里要注意区别3种:
 1. sqlplus命令,例如col col_name for a30
 2. Oracle系统管理命令,例如startup,show parameter
 3. SQL命令,必须以;结尾,前两种不用以;结尾
关于SQL的语法,熟悉的就不多说了,只说一些需要提醒的:
伪列:
 rownum 记录在结果集中的位置。
 rowid 记录在表中的位置。
 序列的 CURRVAL 和 NEXTVAL。
 USER:
     SELECT USER From DUAL
 当前日期和时间戳:SYSDATE 和 SYSTIMESTAMP
     SELECT SYSDATE, SYSTIMESTAMP From DUAL
伪表:
 DUAL
查看表、对象定义:
 describe 对象名
NULL:
 NULL不是0,不是\0字符、也不是空格,它是数据库专有值,表示未赋值。
 数学表达式中,包含了NULL,则结果为NULL。
 nvl(col, 0),如果col为NULL,则转换为0,PG中对应的函数:coalesce(col, 0)
 NVL2(expr1,expr2,expr3) 如果expr1非空,则返回expr2,否则返回expr3
 nullif(expr1,expr2) 如果expr1和expr2相同,则返回null,否则返回expr1
||表示连接字符串:
 select 'desc '|| table_name from user_tables;
distinct去重:
 注意,一个select list里只能有一个distinct,select list如果有多个列,distinct是对它们组合成的行去重,而不是对单独某个列去重。
 select distinct deptno,job from emp;   --- 正确
 select empno,distinct deptno from emp; --- 错误
 select distinct empno,distinct deptno from emp;  --- 错误
修改当前回话日期格式:
 alter session set nls_date_format ='yyyy-mm-dd hh24:mi:ss';
对于NULL的比较:
 1. 可以借助nvl
 2. is null, is not null
 包含 null 值的列排序时, 默认把 null 值看做无限大:
 在升序排序时, null 最后
 在降序排序时, null 最前
order by:
 1. order by 后面不能跟 LOB、 LONG、 LONG ROW 类型的列。
 2. select语句中有 distinct,order by 后面的列,必须出现在select列表中。
模糊查询 like:
 select * from emp2 where ename like 'S%';      --走索引
 select * from emp2 where ename like '%S%';   --全表扫描,不走索引
查看执行计划:
 explain plan for select * from emp2 where ename like 'S%';
 @?/rdbms/admin/utlxplp  --?表示$ORACLE_HOME
收集统计信息:
 execute dbms_stats.gather_table_stats('schema1','t1');
 execute dbms_stats.gather_schema_stats('schema1');
 execute dbms_stats.gather_database_stats();
函数和存储过程:
 1. 函数有1个返回值,而存储过程是通过参数返回的,可以有多个或者没有
 2. 调用的区别,函数可以在查询语句中,直接调用,而存储过程必须单独调用
 一般情况下,函数是用来计算并返回一个计算结果,而存储过程,是用来完成特定的数据操作(比如修改、插入数据库表或执行某些DDL语句等等)oracle中存储过程都属于某个包,例如上面的execute dbms_stats.gather_schema_stats('schema1');
 3. 单行函数可以嵌套任意层级,执行顺序是由内到外。
隐式数据类型转换:
 数值和日期转换函数,会用到格式掩码,所谓格式掩码就是一个控制数值和函数打印格式的字符串。
case条件表达式:
 对于每一行的job列,根据其值,做不同处理:
 select empno,ename,sal,job,
case job when 'ANALYST' then sal*1.1
                when 'CLERK' then sal*1.15
                when 'MANAGER' then sal*1.2
                else sal*1.25
end new_sal 
 from emp order by job;
 第二种形式:
 select empno,ename,sal,job,
case when job='ANALYST' then sal*1.1
          when job='CLERK' then sal*1.15
          when job='MANAGER' then sal*1.2
          else sal*1.25
end new_sal 
 from emp order by job;
 也可以用来处理NULL值:
 select comm,case when comm is null then 0 else comm end new_comm from emp;
decode函数有同样的功能:
 select empno,ename,job,sal,
           decode(job,'ANALYST', sal*1.1,
                              'CLERK', sal*1.15,
                              'MANAGER', sal*1.20,
                              sal*1.25) new_sal
 from emp order by job;
聚合函数group by:
 聚合函数是,多行输入,一行输出,多行就是,group by分组后,属于同一组的那些行。
 group by中的列可以不出现在select列表中,而select列表中的列,如果不再聚合函数中,必须出现在group by从句中。
对聚合函数的结果进行过滤:
 不能使用where,而是使用having,例如:
 select deptno,max(sal) from emp group by deptno having max(sal) >2900;
 having子句可以放在group by前面,也可以放在group by 后面。
 分组函数最多嵌套两层(两个函数), 嵌套时必须有 group by:
 select max(avg(sal)) from emp group by deptno; (按deptno分组以后,每组内,对sal列先算平均值,再求所有组中最大的)
多表连接查询:
 连接查询,可以把所有的表罗列在from中,然后在where中把查询条件列出来,也可以使用join,超过两个表的连接,都可以等价转换为两个表连接的组合。
 多表连接时尽量使用别名,这样能减少内存使用,提高性能。
内连接(inner join):
 连接时指定条件,两个表中符合条件的行,组成一个新行。其中的using <列名> 就相当于以这个列相等为条件做JOIN,前提是两个表都有这么个同名的列,而且类型相同。
外连接:分左连接(left outer join)、右连接(right outer join)和全外连接(full outer join),结果集除了包括两个表中符合join条件的行,对于左连接,还包括左边表不符合条件的行,对于右连接,还包括右边表不符合条件的行,对于全外连接,还包括左右两边不符合条件的行,不符合条件的行只包含一次。
Oracle的外连接也可以用where表达式表示:
 例如:... where t1.col(+) = t2.col 表示结果包括t2的所有行,... where t1.col = t2.col(+) 表示结果包括t1的所有行,但是这是错误的:... where t1.col(+) = t2.col(+)。
natural join:以两表中同名同类型的列,做等值join,如果有多列同名同类型,则共同作为join条件。
join 条件也可以是非等值:
 非等值可用于join on或from where
self join:
 一个表自己和自己连接,可以看做两个一样的表做join查询,一般使用两个别名,也可以使用左连接或右连接。
子查询:
 子查询在主查询之前执行,可以出现在select、where、having、from从句中,子查询必须放在括号内,单行操作符对应输出单行结果的子查询,多行操作费对应输出多行结果的子查询。
 和多行子查询搭配的表达式:in、not in、any、all、exists。
 not in 表达式中如果出现null,则总是返回False,我们通常的理解相反。
多列子查询:
 select empno,ename,sal,job from emp
 where (job,sal) = (select job,sal from emp where empno=7788)
 and empno<>7788;
 等价于
 select empno,ename,sal,job from emp
 where job=(select job from emp where empno=7788)
 and sal=(select sal from emp where empno=7788)
 and empno<>7788;
多行多列子查询:
 select empno,ename,sal,job from emp
 where (job,sal) in (select job,sal from emp where deptno=10)
 and empno<>7788;
关联子查询:
 普通子查询:在主查询执行之前,子查询首先执行一次,子查询的结果要在主查询中使用。
 关联子查询:需要重复执行子查询。
 例如,查询比其所在部门平均工资高的员工:
 select e.ename,e.sal,e.deptno
 from emp e where e.sal > (select avg(s.sal) from emp s
 where e.deptno = s.deptno);
 对每个员工,都要执行一次子查询。
 关联子查询有等价的join查询:
 select e.name, e.deptno, e.sal, avg(s.sal) x from emp e join emp s on e.deptno = s.depno group by e.name, e.deptno, e.sal having e.sal > x;
sqlplus使用:
设置列宽:
 col col_name for a30
在 sqlplus 中,执行脚本:
 SCOTT@PROD> @/home/oracle/p1_01.sql
定义变量:
 define _val = 5
 删除变量
 undefine _val
 在SQL中,使用&<变量名>引用变量
 Q1: select * from t1 where a = &_val;
 如果_val没有事先定义,每次执行Q1时,都会要求输入_val的值,但如果使用&&_val引用_val,则只会要求输入一次。
sqlplus命令行中的set并不是设置变量,而是设置sqlplus相关功能:
 set timing on
 set timing off
SQL执行过程日志:
 spool /home/oracle/emp1.sql
 select * from emp;
 spool off;
  










