0
点赞
收藏
分享

微信扫一扫

OCP笔记2:SQL和sqlplus使用

巧乐兹_d41f 2022-04-19 阅读 6
数据库

从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;
 

举报

相关推荐

0 条评论