oracle学习笔记
一 oracle数据库安装 下载软件 1 oracle官方网址:www.oracle.com 2 oracle 11g官网下载地址:http://www.oracle.com/technetwork/database/enterprise-edition/downloads/index.html pl/sql : https://www.allroundautomations.com/registered/plsqldev.html 环境变量设置 1 在dos环境下进行设置 set oracle_sid=orcl set oracle_home=F:\oracle\product set nls_lang=simplified chinese_china.zhs16gbk 或 set nls_lang=american_america.zhs16gbk set nls_date_format='yyyy-mm-dd hh24:mi:ss' 2 在用户下面设置环境变量 grant select any dictionary to mandy; 给mandy查看数据字典的权限 show parameter nls; 显示数据字典 alter session set nls_language='american'; 修改语言(中文simplified chinese) alter session set nls_territory='america'; 修改国家(中国 china) alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss';--当前会话有效 plsql配置连接 1 位置 工具 首选项 连接 2 设置 Oracle主目录名 = F:\PLSQL\instantclient_11_2 OCI库 = F:\PLSQL\instantclient_11_2\oci.dll 必须添加oci.dll 3 tnsname.ora文件设置,oracle_home下面的tasname.ora与oci库下面的tasname.ora文件内容统一。 F:\oracle\product\NETWORK\ADMIN 下面直接有tasnames.ora(若无,复制一份在下面) 在系统环境变量下设置oracle_home=F:\oracle\product 4 在即时客户端的目录里新建文件夹 network ,network里在新建 admin,在admin目录下建一个后缀名为.ora的文件: tnsnames.ora plsql连接其它数据库配置 1 在dos命令窗口执行 netca 配置本地网络服务 2 使用ip地址与电脑名连接 sqlplus scott/scott@SDWM-20160811NN:1521/orcl 3 在配置文件中进行设置 plsql配置文件地址:F:\PLSQL\instantclient_11_2下面的tasnames.ora文件 oracle配置文件地址:F:\oracle\product\NETWORK\ADMIN 下面直接有tasnames.ora plsql配置文件 打开命令窗口时生效 1 配置文件地址:F:\PLSQL\PLSQL Developer 对下面的login.sql文件编辑 sqlplus启动时的配置文件位置,让格式永久生效。 1 查找路径 regedit注册表中查出oracle_home路径. 2 文件路径为 %ORACLE_HOME%\sqlplus\admin\glogin.sql下面的glogin.sql中进行设置。 环境脚本的执行 1 写好的环境脚本,通过属性查找到相应位置,选择用户或创建专用用户 2 执行:@ 环境脚本的保存路径\环境脚本名称 3 显示文件 get F:\a.sql 运行sql文件 @(或start)F:\a.sql。 关闭启动数据库命令 1 关闭数据库 shutdown immediate 启动数据库 srartup 查看数据库名称 1 show parameter db_name; 二 SQL查询基础 sql语言 1 sql结构化查询语言(structured query language) 2 sql是操作和检索关系型数据库的标准语言。在Oracle mysql db2数据库管理系统上应用 3 使用sql语句,程序员和管理员可以完成如下任务 改变数据库对象的结构 更改系统的安全配置 变更用户对数据库对象的操作权限 在数据库中检索需要的信息 对数据库的信息进行更新 sql语句分类 1 DML语句(数据操作语言data manipulation language) select/insert/update/delete/merge/select...for update 2 DDL语句(数据定义语言data definition language) create/alter/drop/truncate/grant/revoke 3 事务控制语句(transaction control language) commit/rollback/savepoint select 语句的功能 1 从数据库中查询数据 2 列查询:查询表的部分或所有行 3 行查询:设定条件查询表的部分或所有行 4 连接:将多个表组合起来进行查询 select 语法 select * [distinct]column | expression[alias] from table where 条件; --select 查询关键字 --* 查询所有的列 --distinct 去掉重复 --column|expression选择指定的字段(列)或表达式 --alias 给所选择的列取别名 --from table 指定表 --where 后面是筛选条件 --注意:最后的分号必须加上,表示一个sql语句结束 概念 1 keyword关键字,照写。例 select和from是关键字 2 clause是sql语句的一个部分 例 select col1...是一个子句,from也是一个子句 3 statement 是两个或多个子句的组合 例 select * from emp是一个sql语句 查询列 1 select * from emp;--查询表中所有的列 2 select empno,ename,sal from emp;--查询员工编号 姓名 工资三列 查询行 1 select * from emp where ename='SCOTT';--查出名字叫scott这个人的所有信息 2 select empno,ename,sal from emp where ename='FORD';--查出ford的编号 姓名 工资 算述表达式 1 select ename,sal*(1+0.2) from emp;--给每个员工涨20%工资 2 select ename,sal+500 from emp;--给每个员工工资加500 列别名 1 select ename 姓名,sal*(1+0.2) newsal from emp;--别名 姓名 newsal 字符串连接 1 select first_name||','||last_name fullname from employees; 去除重复的行 1 select distinct deptno from emp; 三 SQLPLUS的使用 登录 用户 1 conn / as sysdba --操作系统认证方式登录 2 conn scott/scott --密码方式登录 3 show user --显示当前登录用户 4 discon --取消连接,退出登录 sqlplus帮助 1 help index 查看所有sqlplus命令 2 help set 查看set命令的具体用法 格式化 1 set linesize 120 --设置行宽为120 2 set pagesize 100 --设置每页显示100行 3 set feedback on --显示反馈信息 4 set timing on --显示sql执行了多长时间 5 set time on --提示符显示为时间 格式化列 1 column name format a30 (简写:col name for a30)--将字符类型的列name,列宽设置为30 2 column sal format 99,990(简写:col sal for 99,990)--设置数字类型列sal,三位分隔的方式 3 column sal clear --清楚sal列的格式 编辑命令行 1 list2 将第二行设置为当前行 2 change/enmae/ename(c/enmae/ename) --将当前行的enmae字符串替换成ename 3 edit 在文本编辑器中,编辑最后一次执行的sql。 保存执行的sql 1 save d:\a.sql --最后一次执行的sql保存到文件中,没有新建,若有覆盖 2 save d:\a.sql append --文件存在,则追加在文件末尾。只能保存最后执行的一句sql。 3 spool d:\b.sql --开始保存一下执行的操作和结果 spool off --结束,保存到这里为止 spool d:\b.sql append --以追加的方式保存 显示和运行脚本 1 get d:\a.sql --把文件中的内容显示出来 2 运行sql文件 @d:\a.sql 或者 start d:\a.sql 替换变量 1 & 定义变量,从键盘输入变量值,不在内存中保存 2 && 定义变量,从键盘输入变量值,在内存中保存,下次可以继续用 3 define 定义变量 4 undefine 清除变量定义 查看当前设置的sqlplus相关参数 1 show all --查看当前配置的所有参数 2 show linesize --查看某个具体参数当前设置的值 清屏 1 clear screen(clear scr) --清楚屏幕上的显示信息 查看表结构,分屏显示 1 describe table_name (desc table_name)--显示某个表的所有列名,列类型 2 set pause on --分屏显示结果 3 set pause 'please input enter'--分屏显示,并加提示信息'please input enter' 4 set pause off --关闭分屏显示 查看错误信息 1 sql>!oerr ora 00942 或者 $oerr ora 00942 --查看ora-00942错误的详细信息 2 show errors --显示pl/sql错误信息 让格式永久生效 1 $oracle_home/sqlplus/admin/glogin.sql --将格式写在文件中 2 $oracle_home是指oracle的安装路径,并不是具体的资料夹 四 常用资料查询 联机文档 1 帮助用户正确操作和使用oracle数据库,oracle公司给出的一份最权威的官方文档 2 若书籍和其它资料上与官方联机文档说法不一致,以联机文档为准。 查看联机文档 1 Oracle公司所有产品的联机文档总入口 http://docs.oracle.com/ 2 数据库各版本联机文档入口 http://docs.oracle.com/en/database/database.html 3 联机文档下载,熟悉联机文档的大体结构和内容 4 联机文档查资料 查oracle有哪些数据类型 sql reference 5 查看语法图 6 查看执行计划 set autotrace on --打开执行计划查看 set autotrace off--关闭执行计划查看 set autotrace on explain --只显示查询结果和执行计划 set autotrace on statistics --只显示结果和统计信息 set autotrace traceonly --不显示查询输出,显示执行计划和统计信息 set autot traceonly explain --只显示执行计划 set autot traceonly statistics --只显示统计信息 --connect / as sysdba --@?\rdbms\admin\utlxplan --@?\sqlplus\admin\plustrce.sql --grant plustrace to public; 五 数据类型 字符类型 oracle数据库的核心是表,表中的列使用到的常见字符类型如下 1 char(n) 存储固定长度的字符串,参数n指定了长度,如果存储的字符串长度小于n,用空格填充,默认长度是1,最长不超过2000字节 2 nchar(n) 辅助字符集,特征同char 3 varchar2(n) 存储可变长度的字符串,length指定了该字符串的最大长度。默认长度1,最长不超过4000字节 4 nvarchar2(n) 辅助字符集,特征同varchar2. --辅助字符集,只能用unicode字符集,AL16UTF16或UTF8其中的一种 5 Oracle支持的字符集 1 单字节字符集 分为7bit和8bit,ascii就是7bit,iso8859-1就是8bit iso8859-1是ascii的严格超级。单字节字符集,1byte=1character。 1char=1byte , char(5byte)=5bytes , char(5char)=5*1byte=5bytes 2 多字节字符集 分为可变长度字符集,固定长度字符集。 双字节中文字符集 1char=2bytes , char(5char)=5*2bytes=10 bytes 对于多字节字符集 1char=n bytes 如:1char=3bytes 3 unicode字符集 官网 www.unicode.org. 数值类型,日期类型 1 number(p,s) 既可以存储浮点数,也可以存储整数,p表示有效位(p默认是38),s是小数位数(默认0) 2 date 存储日期和时间,世纪,4位年,月,日,时,分,秒 3 timesamp 存储日期的年月日,时分秒,以及秒后9位(默认6位),同时包含时区。 ROWID rowid是存储每条记录的实际物理地址,rowid值可以唯一标识表中的一行。 --最快到达行,最快访问 索引中叶节点rowid 可以改变 --dbms_rowid rowid数据包 select dbms_rowid.rowid_object(rowid) object_id, dbms_rowid.rowid_relative_fno(rowid) rfile, dbms_rowid.ROWID_BLOCK_number(rowid) block, dbms_rowid.rowid_row_number(rowid) row#, emp.* from emp; delete from emp where rowid not in (select min(rowid) from emp group by empno) --去重 ROWNUM 在Oracle表的使用过程中,实际表中还有一些附加的列,称为伪列。伪列就像表中的列一样,但是在表中 并不存储。伪列只能查询,不能进行增删改操作。 1 rownum是一个伪列(不是真正的列,在表中并不真实存在) 2 rownum是oracle数据库读取数据的顺序 --在emp表中,工资按降序排列,显示5到10行数据 select b.* from (select rownum rn,a.* from (select rownum,emp.* from emp order by sal desc) a) b where rn>=5 and rn<=10; 六 函数 Oracle sql提供了用于执行特定操作的专用函数,这些函数大大增强了sql语言的功能。函数可以接受零个或者多个输入参数,并返回一个输出结果。 Oracle数据库中主要使用两种类型的函数: 单行函数:对每一个函数应用在表的记录时,只能输入一行结果,返回一个结果,常用单行函数 1 字符函数:对字符串操作 2 数值函数:对数字进行计算,返回以恶数字 3 日期函数:对日期和时间进行处理 4 转换函数:可以将一种数据类型转换为另外一种数据类型 5 条件函数:case...when和decode条件判断函数 分组函数(聚合函数):聚合函数可以对多行数据进行操作,并返回一个结果 如:sum(x)返回结果集中x列的总和。 字符函数 字符函数可以是表中的列,也可以是一个字符串表达式,常用函数 1 ASCII(X) 返回字符x的ASCII码。互反函数:chr() select ascii('A'),ascii('a'),ascii(''),ascii('示') from dual; 2 concat(x,y) 连接字符串x和y 同|| select concat('010','8888')||'66' from dual; 3 instr(x,str,n1,n2) 在x中查找str,可以指定从n1开始,也可以指定从第n2次开始 select instr('oracle traning','ra',1,2) from dual;--返回9 4 length(x) 返回x的长度 lengthb(x)返回字节的长度 select length('hello') from dual; 5 lower(x) x转换为小写 select lower('ABC') from dual; 6 upper(x) x转换为大写 select upper('abc') from dual; 7 ltrim(x,trim_str) 把x的左边截去trim_str字符串,缺省截去空格 select ltrim('abaaxxbaa','ab') from dual;--截取左边全部a和b(遇符号,其它字符结束)。 8 rtrim(x,trim_str) 把x的右边截去trim_str字符串,缺省截去空格 select rtrim('adxxabdadasbaab','ab') from dual; 9 trim(trim_str from x)把x的两边截去trim_str字符串,缺省截去空格 select trim('a' from 'a bbabb abba=aa') from dual;--去除两边的a,截取集只能有一个字符。 10 replace(x,old,new) 在x中查找old,并替换为new select replace('abcABC','ab','x') from dual;--整体替换,区分大小写 11 translate(expr,from_string,to_string) 替换字符与被替换字符一一对应关系 select translate('abcd','ab','d') from dual;--b对应空(相当于删除),替换字符不能为空 12 substr(x,n1,n2) 返回x的字串,从n1开始,截去n2个字符,缺省n2,默认到结尾 select substr('abc',1,2) from dual; --从位置1开始,返回2个长度。 13 initcap(x) 返回x字符串第一个字母变为大写,其它字母小写 select initcap('ab cde'),initcap(chr(97)) from dual; 14 lpad(x,n,y) 在字符串x左边用y字符串填充,到长度为n为止。如果x长度大于n,返回x左边n个字符,如小于n,x和y 连接后大于n,返回连接后的右边n个字符。 select lpad('hello',10,'*') from dual; 15 rpad(x,n,y) 在字符串x右边用y字符串填充,到长度为n为止。 select rpad('hello',10,'*') from dual; 数值函数 数值函数可以是表中的列,也可以是一个字符串表达式,常用的数值函数 1 abs(x) 返回x的绝对值 返回数字 select abs(100),abs(-100) from dual; 2 ceil(x) 大于或等于x的最小整数值 select ceil(5.3) from dual;--返回6 3 floor(x) 小于或等于x的最大整数值 select floor(5.9) from dual;--返回5 4 mod(x,y) 返回x除以y的余数 select mod(8,3) from dual; --返回2 5 round(x[,y]) x在第y位四舍五入 select round(55.66,2),round(55.66,-1),round(55.66) from dual; 6 trunc(x[,y]) x在第y位截断 select trunc(55.66,2),trunc(55.66,-1),trunc(55.66) from dual; 7 sign(x) 判断x的正负,只返回-1,0,1三个值 select sign(1.1),sign(-1.1),sign(0) from dual; 8 least(x,y) 返回x,y中最小的值 select least(23,-9,99) from dual; 9 greatest(x,y) 返回x,y中最大的值 select greatest(23,09,99,-68) from dual; 日期函数 1 sysdate 系统当前时间,精确到秒 select sysdate from dual; 2 current_date 当前会话时间 select current_date from dual; 3 systimesamp 系统当前时间,精确到秒后9位(默认6位),包含时区 4 months_between(d1,d2) 返回d1,d2两个日期的差值,单位为月 select months_between(date'2008-8-8',sysdate) from dual; 5 add_months(d,n) 在日期d上增加n个月,返回新的日期 select add_months(sysdate,1) from dual; 6 next_day(d,n) 返回从d这天开始算起,下一个周n的日期 select next_day(sysdate,2) from dual; --下一个周一的日期 7 last_day(d) 返回d这个月的最后一天 select last_day(sysdate) from dual; 8 round(d,fm) 返回d中的fm部分,四舍五入 select round(sysdate,'mm') from dual; 9 trunc(d,fm) 返回d中的fm部分,直接截断 select trunc(sysdate,'dd') from dual; 转换函数 主要用于各类数据类型之间的转换 1 to_char(d/n[,fmt]) 把日期或数字转换为fmt指定格式的字符串 select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual;--系统时间转换为字符串 select to_char(systimestamp,'yyyy-mm-dd hh:mi:ss.ff tzh:tzm') from dual;--把时间戳转换为字符串 select to_char(sysdate,'mm') from dual;--系统时间转换为显示月份字符串 select to_char(sal,'$999,999.00') from dual;--将数字转换为字符串 2 to_number(x[,frm]) 把一个字符串以fmt格式转换为一个数字 select to_number('$125,136,366.00','$999,999,999.00') from dual; select to_number('1.23e+10','9.99eeee') from dual; 3 to_date(x[,fmt]) 把一个字符串以fmt格式转换为日期格式 select to_date('12-sep-2016 pm 02:49:29','dd-mon-yyyy pm hh:mi:ss','nls_date_language=american') from dual; 4 to_timestamp 转换为时间戳 select to_timestamp_tz('2016-09-12 03:45:36.894123456 pm +08:00','yyyy-mm-dd hh:mi:ss.ff am tzh:tzm','nls_date_language=american') from dual; 5 cast(expr as data_type) 用于将某种数据类型的表达式显式转换为另一种数据类型 select cast(sysdate as timestamp) from dual; 6 convert(char,dest_char_set[,source_char_set]) 字符集转换 7 case...when 条件转换函数 case when有两种表现形式 1 case 变量 when 值1 then 结果1 when 值2 then 结果2 else '其它' end --else可以选择不要 示例: select ename,job,( case job when 'MANAGER' then job when 'CLERK' then job end) from emp; 2 case when 表达式1 then 结果1 when 表达式2 then 结果2 else '其它' end 示例: select ename,sal, case when deptno=10 then '会计部' when deptno=20 then '研究部' when deptno=30 then '销售部' else '其它部门' end from emp; 8 decode函数 语法 decode (empression,search1,result1, search2,result2, ... default) --如果expression=search1,返回result1 --如果expression=search2,返回result2 --都不相等使用默认值 示例: select ename,sal, decode(deptno, 10,'会计部', 20,'研究部', 30,'销售部', '其他部门') from emp; 七 DDL语句 DDL语句(数据定义语言data definition language) 常用的DDL语句 1 create 创建对象,如建表或视图 2 alter 修改对象的结构,如修改表结构 3 drop 删除对象, 如删除表,索引,视图,序列 4 truncate 清空表的数据 create 建表 1 普通建表 create table t(id int,name varchar2(10)); 2 用其它表的结构和数据建表 create table t as select * from emp; --只能拷贝非空约束 create table t as select * from emp where 1=2;--只拷贝结构 3 表建在某个表空间 create table t (id int) tablespace users; select tablespace_name,file_name from dba_data_files;--查看表空间及位置 列的相关操作 1 添加列 alter table t add (b number(10)); 2 删除列 alter table t drop column t; 3 修改列的数据类型 alter table t modify (name varchar2(20)); 4 修改列名 alter table t rename column id to idd; 5 将某列标记为不可用 alter table t set unused column b; select * from dba_unused_col_tabs;--查询那些标记为unused列 select object_id from dba_objects where owner='SCOTT' and object_name='T'; select name from col$ where obj#='object_id'; 6 将标记为不可用的列删除 alter table t drop unused columns; 表的相关操作 1 修改表名 alter table t rename to test; 2 将表改成只读状态 alter table t read only; 3 将表改成读写状态 alter table t read write; 4 删除表 drop table t; drop table t purge; 5 清空表的数据 truncate table t; 查看表结构 1 desc t --查看列名和列类型describe 2 DBMS_METADATA.GET_DDL --获取对象的元信息 3 SELECT DBMS_METADATA.GET_DDL('TABLE','T','SCOTT') FROM DUAL;--set long 500设置字符串长度 八 DML语句 DML语句(数据操作语言data manipulation language) 1 select ... for update 2 select 3 insert 4 update 5 delete 6 merge into select/select... for update 普通select不会阻塞其它读写 select ename,sal from emp where empno=7839; select...for update会阻塞其它读写(有锁) select ename,sal from emp where empno=7839 for update; insert插入语句 insert可以插入一条记录 insert into t values(1,'hello'); insert into t(id) values (2); 插入多条记录 insert into t select empno,ename from emp; 可以同时插入多个表 insert all/insert first 1 create table t1(a int primary key,b int); create table t2(x int primary key,y varchar2(10)); insert all when mod(rn,2)=1 then into t1(a,b) values (rn,object_id) when mod(rn,2)=0 then into t2(x,y) values (rn,object_name) select rownum rn,object_id,object_name from all_objects where rownum<=20; 2 有交叉数据时用insert first insert first when rn>=10 then into t1(a,b) valuse (rn,object_id) when fr<=15 then into t2(x,y) values (rn,object_name) select rownum rn,object_id,object_name from all_objects where rownum<=20; update update变更数据 update t set ename='SMITH' where di=1; 修改多列的值 update t set ename='james',sal=3000 where id=12; 用字查询来变更 1 update t set id=15, name=(select ename from emp where empno=7839) where id=12; 2 update t set (id,name)= (select empno,ename from emp where empno=7839) where id=12; 删除数据 delete删除数据,可以删除表中部分数据,或是所有数据 1 delete from t where id=7839; 2 delete from t;(或者delete t;) truncate 删除表中所有的数据 truncate table t; drop 删除表,视图等 1 drop table t; 2 drop table t purge; 三者的区别 1 delete可以删除部分数据,也可以删除全部数据,truncate清空数据。 2 delete删除记录日志,可以回滚,删除速度慢于truncate。truncate不能回滚。 3 delete不移动高水位,truncate移动高水位。 4 回收站查看删除的表 show recyclebin FLASHBACK TABLE T TO BEFORE DROP;--闪回到删除之前。 purge recyelebin --清空回收站 mgrge into语句 1 merge into可以在一个sql语句中对一个表同时执行insert和update操作 2 merge命令从一个或多个数据源中选择行来update或insert到一个表或视图中 3 update或insert子句是可选的 4 update或insert子句可以加where条件 5 update子句后面可以跟delete子句去删除一些不需要的行 merge intoy语法 merge into --要插入或更新的表 using --要匹配的表 on --要匹配的条件 when matched then --匹配的时候 update --更新 delete --删除 when not matched then --不匹配时 insert --插入 示例: merge into oldemp o using newemp n on (o.empno=n.empno) --此列有多个相同值时无法更新 when matched then update set o.sal=n.sal delete where (o.ename='KING') --此处后面不需要跟表名 --delete where (o.ename='SMITH') --update后面跟delete时必须是更新后的数据才能删除。 when not matched then insert (o.empno,o.ename) values(n.empno,n.ename); --可以用minus进行检验 九 约束 1 约束是强加在表上的规则或条件。确保数据满足业务规则,保证数据的完整性。 2 当对表进行DML或DDL操作时,如果此操作会造成表中的数据违反约束条件或规则的话,系统就会拒绝执行这个操作。 3 约束可以是列一级别的 也可以是表级别的 4 定义约束时没有给出约束的名字,ORACLE系统将为该约束自动生成一个名字,其格式为SYS_Cn,其中n为自然数。 5 建议在创建表或增加约束时,给约束定义有意义的名称 约束的作用 1防止无效的垃圾数据进入数据库,维护数据库的完整性。完整性指正确性与一致性 2使数据库的开发和维护都更加容易 约束分类 1 NOT NULL 非空约束 1.1 NOT NULL非空约束确保字段必须要输入值,不能为空 1.2 可以在建表时加NOT NULL约束 CREATE TABLE T_NULL(ID NUMBER NOT NULL,NAME VARCHAR2(10)); 1.3 也可以先建表,然后再将列加上NOT NULL约束 ALTER TABLE T_NULL MODIFY ID NOT NULL; 2 UNIQUE 唯一约束 2.1 表中每一行中所定义的这列或几列的值都不能相同 2.2 必须保证唯一性,即不能重复 2.3 唯一约束允许有null值 2.4 建表时添加唯一约束 CREATE TABLE T_UN (ID NUMBER CONSTRAINT UK_T_UN_ID UNIQUE,NAME VARCHAR2(10)); 2.5 先建表,再加约束 ALTER TABLE T_UN MODIFY ID CONSTRAINT UK_T_UN_ID UNIQUE; 3 PRIMARY KEY 主键约束 3.1 主键约束唯一的标识表中的每一行,不能重复 3.2 主键约束不允许有NULL值 3.3 PRIMARY KEY=NOT NULL + UNIQUE 3.4 建表时添加主键 CREATE TABLE T_PK (ID NUMBER(10) PRIMARY KEY,NAME VARCHAR2(10)); 3.5 先建表,再加主键 ALTER TABLE T_PK MODIFY ID PRIMARY KEY; 3.6 每个表只能有一个主键约束 4 FOREIGN KEY 外键约束 4.1 外键是一张表与另一个表之间联接的字段 4.2 外键必须是另一个表中的唯一约束列或主键列 4.3 外键的用途是确保数据的完整性(确保每个实体是唯一,域完整性,关联完整性) 4.4 建表的时候加外键 CREATE TABLE T_DEPT (DEPTNO NUMBER(2) CONSTRAINT PK_DEPT1 PRIMARY KEY, DNAME VARCHAR2(14) , LOC VARCHAR2(13)) ; CREATE TABLE T_EMP (EMPNO NUMBER(4) CONSTRAINT PK_EMP1 PRIMARY KEY, ENAME VARCHAR2(10), JOB VARCHAR2(9), MGR NUMBER(4), HIREDATE DATE, SAL NUMBER(7,2), COMM NUMBER(7,2), DEPTNO NUMBER(2) CONSTRAINT FK_DEPTNO1 REFERENCES T_DEPT(DEPTNO)); 4.5 先建表再加外键 ALTER TABLE t_emp ADD CONSTRAINT FK_DEPT FOREIGN KEY(deptno) REFERENCES t_dept(deptno); 4.6 级联删除 alter table T_EMP add constraint FK_DEPTNO1 foreign key (DEPTNO1) references T_DEPT(DEPTNO) on delete cascade; 4.7 级联的数据设置为null alter table T_EMP add constraint FK_DEPTNO1 foreign key (DEPTNO1) references T_DEPT(DEPTNO) on delete set null; 5 CHECK 检查约束(条件约束) 5.1 有特殊需求的地方,可以用check约束 CREATE TABLE T_CK (ID NUMBER(10),NAME VARCHAR2(10),AGE INT CHECK(AGE>0 AND AGE<200)); 5.2 在一列上可以定义任意多个check约束 约束命名 1 约束命名的一般规则 1.1 非空约束 NN_表名_列名 1.2 唯一约束 UK_表名_列名 1.3 主键约束 PK_表名_列名 1.4 外键约束 FK_表名_列名 1.5 条件约束 CK_表名_列名 修改约束名字 ALTER TABLE T_NULL RENAME CONSTRAINT TO NN_T_NULL_ID 约束类型 CONSTRAINT TYPE 1.1 C (check constraint on a table) 1.2 P (primary key) 1.3 U (unique key) 1.4 R (referential integrity) 1.5 V (with check option, on a view) 1.6 O (with read only, on a view) 查看约束 select table_name,constraint_name,constraint_type from user_constraints where table_name='emp'; 删除约束 1.1 根据约束名称,删除约束,通用 ALTER TABLE T_EMP DROP CONSTRAINT FK_DEPTNO1; 1.2 删除主键约束 ALTER TABLE T_EMP DROP PRIMARY KEY; 1.3 删除唯一约束 ALTER TABLE T DROP UNIQUE(ID); 约束生效和失效 1.1 让约束失效 ALTER TABLE T_EMP DISABLE CONSTRAINT FK_DEPTNO1; 1.2 让约束生效 ALTER TABLE T_EMP ENABLE CONSTRAINT FK_DEPTNO1; 表 DATAFILE 数据文件 SELECT * FROM V$DATALILE --查看数据文件 表空间 DBA_TABLESPACES --DBA表空间 SELECT * FROM DBA_TABLESPACES; --查看表空间 DAB_DATA_FILES --数据文件 SELECT * FROM DBA_DATA_FILES; --查看数据文件 段 segment 由extent(区)组成,extent由black(块)组成 DBA_SEGMENTS DBA下面所有的段 OWNER用户 SEGMENT_NAME表名 SELECT * FROM DBA_SEGMENTS WHERE SEGMENT_NAME='EMP'; 区EXTENT 最低8个块BLACK SELECT * FROM DBA_EXTENTS WHERE OWNER='MANDY'; 块BLOCK 一个block=8kb SELECT DISTINCT BLACKS FROM DBA_EXTENTS WHERE BLACLS>8; 建表语句 查找DDL语句 METADATA 源数据 TABLESPACE USERS指定表空间 SELECT DBMS_METADATA.GET_DDL('TABLE','EMP','MANDY') FROM DUAL; READ ONLY 只读/ WRITE 读写 ALTER TABLE EMP READ ONLY --只能读 ALTER TABLE EMP WRITE --读写状态 临时表 temporary 只在当前会话窗口有效 CREATE GLOBAL TEMPORARY TABLE TEST1 (ID NUMBER(10),NAME VARCHAR2(10)) ON COMMIT DELETE ROWS;--默认ON COMMIT DELETE ROWS CREATE GLOBAL TEMPORARY TABLE TEST2 (IN NUMBER(10),NAME VARCHAR2(10)) ON COMMIT PRESERVE ROWS;--提交保存 十 查询 like 模糊查询 1.1 %表示任意多个字符 1.2 _表示任意一个字符 1.3 not like不匹配的 select * from emp where ename like '_A%'; 1.4 查看%和_本身,使用转义字符 show escape 查看转义字符(set escape on打开) 自定义转义字符 select * from emp where ename like '\_%' escape '';将\设置为转义字符 单引号转义 between and 求某个范围内的 not between and 求不在某个范围内的 in 求和in里面的列表中某一个或多个匹配的 not in 和in相反,求不匹配的 order by 排序子句 select * from emp order by dbms_random.value();随机排序 select * from emp order by nlssort(ename,'NLS_SORT=SCHINESE_PINYIN_M');按拼音排序 select * from v$nls_valid_values;数据字典 1.1 分组后可以使用分组函数 1.2 asc 升序排列 desc 降序排列 1.3 可以跟列名,多列,组合,随机 group by 分组子句 1.1 可以按一个字段分组,也可以按多个字段分组 1.2 分组后可以使用分组函数(聚合函数)sum,avg,max,min,count 1.3 group by 后面可以跟字段,不能跟别名和数字 1.4 having 筛选分组以后的数据,where筛选分组以前的数据。 多表连接查询 内连接 inner join查询两张表相匹配的记录 select ename,emp.deptno,dname from emp inner join dept on emp.deptno=dept.deptno;select ename,emp.deptno,dname from emp,dept where emp.deptno=dept.deptno; select ename,emp.deptno,dname from emp ,dept where emp.deptno=dept.deptno and (sal>1000 or emp.deptno=10);--此处需要加括号 自然连接 natural join select ename,dname,deptno from emp natural join dept; select e,ename,d,dname,deptno from emp e join dept d using(deptno); 非等值连接 select a.ename,a.sal,b.grade from emp a,salgrade b where a.sal between losal and hisal; 自连接 self join将自身表的一个镜像当作另一个表来对待 select a.empno,a.ename,a.sal,b.empno mno,b.ename mname from emp a,emp b where a.mgr=b.empno; 外连接 左外连接left outer join(简写leftjoin)以左边表为基础,条件不匹配的,null补充 右外连接right outer join(rightjoin)以右边的表为基准,条件不匹配的,null补充 全外连接full outer join(fulljoin)条件不匹配的,都用null补充 select a.empno,a.ename,b.empno mno,b.ename mname from emp a,emp b where a.mgr=b.empno(+); SELECT * FROM EMP LEFT JOIN DEPT ON EMP.DEPTNO = DEPT.DEPTNO 条件连接 select * from emp, salgrade a where a.hisal >= emp.sal and a.losal <= emp.sal; 反连接 antijoina not in select * from emp where comm not in (select comm from emp where ename = 'KING') --空值 标量子查询 标量子查询出现在select从句,当使用到外部连接或使用到聚合函数时可以使用 select ename,(select dname from dept where dept.deptno=emp.deptno) from emp;--相当于外连接 相关子查询 (两个表相关) 关联子查询 select * from emp a where sal > (select avg(sal) from emp b where a.deptno = b.deptno) 半连接 semijoins exists where 字句中不能用or select * from emp A where not exists (select * from emp b where b.comm = a.comm and (b.ename = 'SCOTT' or b.ename = 'ALLEN')); --and后面or条件需要加括号 --与not in 的区别 SELECT * FROM EMP WHERE COMM NOT IN (SELECT COMM FROM EMP WHERE ENAME = 'KING' OR ENAME = 'ALLEN') /*not in与not exists在处理时有对空值的处理不一样*/ any ,all 用法与区别 --查找工资大于最低工资的员工信息 select * from emp where sal>(select min(sal) from emp); select * from emp where sal<any (select sal from emp); select * from emp where sal>= all (select sal from emp)--注意空值 SELECT * FROM EMP A WHERE SAL< ANY (SELECT SAL FROM EMP B WHERE B.DEPTNO=A.DEPTNO) 集合查询 并集(union/union all) 将两张表的数据合并,union去除重复值,union all不去除重复值 交集(intersect) 获取两张表都有的记录 差集(minus) 从一张表中去除另一张表的记录。表的顺序不一样结果不一样。 十一 null值专题 1 当列没有值时,可以表示为null,当列值未知或者无意义时也可以使用null 2 由于null表示数据是不确定的,未知的,所以null不能等于或者不等于任何值或另一个null 判断null值 1 判断列值是否为nulls,只能使用is null与is not null 2 如果使用其它条件对nulls进行判断比较,得到的结果都是unknown select * form emp where comm is null; null运算 1 null和任何值运算,结果为null 2 连接符除外 select null||'abc',''||'abc' from dual; nvl函数 NVL (expr1, expr2) expr1不为NULL,返回expr1;expr1为NULL,则返回expr2。两者类型要一致 select ename,nvl(comm,0) from emp; nvl2函数 NVL2 (expr1, expr2, expr3) expr1不为NULL,返回expr2;expr1为NULL,返回expr3。 select ename,nvl2(comm,0,comm) from emp; coalesce函数 coalesce(expression_1, expression_2, ...,expression_n)返回多个值中第一个不为空的 select coalesce(comm,0) from emp; decode函数 在decode函数判断中,oracle认为null=null select ename,decode(comm,null,0,comm) from emp; case when函数 select ename,(case when comm is null then 0 else comm end) from emp; 组合函数中的null 组合函数中忽略空值 select count(*),count(comm) from emp; 子查询中的null 1 select ename,comm from emp where comm in (select comm from emp where ename='ALLEN' OR ename='SCOTT'); 2 select ename,comm from emp where comm not in (select comm from emp where ename='ALLEN' OR ename='SCOTT'); 3 select * from emp A where not exists (select * from emp b where b.comm = a.comm and (b.ename = 'SCOTT' or b.ename='ALLEN')); --无返回结果 可以使用exists 集合操作中的null 集合运算中 null=null 约束中的空值 组合约束中,只要有一列是非null值 则 null=null NULL的排序 null默认排在最后 select ename,comm from emp order by comm; null排在最前 select ename,comm from emp order by comm nulls first; null排在最后 select ename,comm from emp order by comm nulls last; 空值相等的函数 sys_op_map_nonnull(null) select * from emp where sys_op_map_nonnull(null)=sys_op_map_nonnull(null); 十二 事务 事务是指一组逻辑操作单元,使数据从一种状态变换到另一种状态,为确保数据库中数据的一致性,数据的操纵应当是离散的成组的逻辑单元,当全部完成时,数据的一致性可以保持,当这个单元中的一部分操作失败,整个事务应视为错误,所有从起始点以后的操作应当回退到开始状态。 为了有效的控制事务(transactions),oracle引入了两个显示的事务控制命令,一个是commit,一个是rollback。 事务控制语句 commit rollback savepoint 可以设置DML语句自动提交事务 set autocommit on 事务开始和结束 1 一个事务是以第一个可执行的sql语句开始 2 当发生下列事件之一时结束 commit语句提交 rollback语句回滚 执行DDL语句自动提交 执行DCL语句自动提交 用户正常退出sqlplus自动提交 用户非正常退出sqlplus自动回滚 系统崩溃,自动回滚 锁 多用户数据库管理系统的一个主要任务是对并发(concurrency)进行控制,即对多个用户同时访问同一数据进行控制。当缺乏有效的并发控制时,修改数据的操作就不能保证正常,危害数据完整。 oracle使用锁(lock)来控制对数据的并发访问,当更新数据时,数据库服务器锁定被修改的数据直到此更新被提交,这期间,任何用户都不能修改被锁定的数据,保证系统的数据完整性。 DML锁 也称作数据锁(data lock),它锁定DML语句操作的特定数据行(行锁)或表中的所有数据行(表锁) DDL锁 保护对象的结构(表或视图的定义),也称数据字典锁 排他DDL锁 共享DDL锁 可中断解析锁(breakable parse locks) 系统锁 保护内部数据结构 行锁实验 表锁实验 死锁实验 行锁和表锁 select sid from v$mystat where rownum=1;会话id。 查看锁 select * from emp where ename='SCOTT' for update; select sid, type, id1, id2, decode(lmode, 0,'none', 1,'null', 2,'row share', 3,'row exclusive', 4,'share', 5,'share row exclusive', 6,'exclusive') lock_type, request, ctime, block from v$lock where sid = 8; select * from emp where ename='SCOTT' for update nowait;--nowait不在等待 select * from emp where ename='SCOTT' for update wait 20;--等待20秒 update emp set sal=2000 where empno=7369; 查看锁 select oracle_username username, session_id sid, decode(locked_mode, 0,'none', 1,'null', 2,'row share', 3,'row exclusive', 4,'share', 5,'share row exclusive', 6, 'exlusive') lock_type, object_name, xidusn, xidslot, xidsqn from v$locked_object, dba_objects where v$locked_object.object_id = dba_objects.object_id; 查看谁拿到锁 select decode(request, 0, 'holder', 'waiter:') || sid as sid, 2,id1, 3,id2, 4,lmode, 5,request, 6,type, 7,ctime from v$lock where (id1, id2) in (select id1, id2 from v$lock where request > 0) order by id1, ctime desc; select * from v%lock; --查看锁情况 十三 其他对象 sequence 序列 序列(sequence)是序列号生产器,可以为表中的行自动生成序列号,产生一组等间隔的数值(类型为数字)。主要用途是生产表的主键值,可以在插入语句中引用,也可以通过查询检查当前值,或使序列增至下一个值。 创建序列需要create sequence 系统权限 sequence序列语法 CREATE SEQUENCE seq名 [ INCREMENT BY n ] --每次增加多少,默认1 [ START WITH n ] --从几开始,默认1 [ { MAXVALUE n | NOMAXVALUE }] --最大值 ,NOMAXVALUE,没有上限(10 的27 次方 ) [ { MINVALUE n | NOMINVALUE }] --最小值,NOMINVALUE ,没有下限(10的-26次方) [ { CYCLE | NOCYCLE } ] --表示达到上限后,是否回头再循环重新开始 [ { CACHE n | NOCACHE } ] --为增加效率,将值放在缓存中,默认每次放20个. [ { ORDER | NOORDER } ] --是否顺序产生值 获取原始创建语句 select dbms_metadata.get_ddl('sequence','seq_a') from dual; SELECT * FROM USER_SEQUENCES WHERE SEQUENCE_NAME='SEQ_A'; 修改sequence alter sequence seq increment by 20 maxvalue 9999 nocache nocycle --start with 不能修改 sequence 的值不一定连续 1 多个用户同时用一个sequence时,在某一个用户看来,值是不连续的(或多个表) 2 回滚的时候,因为sequence是一个独立的对象,当你的数据回滚时,它并不回滚,所以回滚的那些值就表示已经用掉了,不会再重新生成。 3 系统崩溃的时候,放在内存中的,即使是没有使用的值,也会被丢弃掉,不再使用。 sequence的伪列 nextval,currval 1 nexval表示获取下一个值。 2 currval表示获取当前值,在使用currval之前,必须使用nextval,否则当前值没有。 视图view 1 视图是基于一个表或多个表或视图的逻辑表,本身不包含数据 2 视图基于的表称为基表。 创建视图 create /*or replace*/ view v_emp_dept10 as select * from emp where deptno=10; 添加约束只能更改20号部门的数据 with check option create view v_emp_dept20 as select * from emp where deptno=20 with check option; 创建只读视图 with read only create view v_emp_dept30 as select * from emp where deptno=30 with read only; 没有基表创建视图 前面加force create force view v_emp5 as select * from emp5 where deptno=20; 数据字典里面查看视图 select view_name from all_views where view_name='v_emp5'; 查看视图的列能否被修改 select * from user_updatable_columns where table_name='v_emp_dept10'; 视图的优点 1 对数据库的访问,视图可以有选择性的选取数据库里的一部分 2 用户通过简单的查询可以从复杂查询中得到结果 3 维护数据的独立性,视图可从多个表检索数据 4 对于相同的数据可产生不同的视图 视图分为简单视图和复杂视图 1 简单视图只从表里获取数据,复杂视图从多表 2 简单视图不包含函数和数据组,复杂视图可以包含 3 简单视图可以实现DML操作,复杂视图不可以 视图中那些情况,不能进行DML操作 1 包含组函数 +group by子句 2 包含distinct关键字 3 rownum列 4 包含表达式的列 物化视图 materialized view 1 创建物化视图日志 create materialized view log on emp with rowid; create materialized view log on emp with primary key ; 2 创建物化视图 create materialized view mv_emp build immediate --immediate 立即直接 deferred 推迟 refresh complete --刷新 fast增量刷新 complete 完全刷新 never不刷新 on demand --demand有需要时刷新 commit立即刷新 start with sysdate next to_date(to_char(sysdate+1,'yyyy-mm-dd')||'00:00:00','yyyy-mm-dd hh24:mi:ss') as select * from emp; 3 删除物化视图 drop materialized view mv_emp 4 手动更新需要在命令窗口执行exec 需要提交 exec dbms_mview.refresh('MV_EMP','F') --f是增量刷新 5 select * from user_segments; 查看视图日志 MLOG$_EMP select * from mv_emp; --查看视图 同义词 1 同义词是数据库方案对象的一个别名,用于简化对象访问和提高对象访问安全性 2 在使用同义词时,oracle数据库将它翻译成对应方案对象的名字 3 与视图类似,同义词并不占用实际存储空间,只在数据字典中保存了同义词的定义 4 在oracle中的大部分数据库对象,如表 视图 同义词 序列 存储过程 包 都可以根据实际情况为他们定义同义词。 创建同义词 create synonym emp1 for emp; 查看对象类型 select object_name,object_type from all_objects where owner='HR' and object_name='EMP'; 删除同义词 drop synonym emp1; 十四 用户和权限 创建/删除用户 CREATE USER TEST IDENTIFIED BY TEST;第一个test是用户名,第二个登陆密码。 --查询用户属性 SELECT USERNAME,CREATED,ACCOUNT_STATUS FROM DBA_USERS WHERE USERNAME='TEST'; SELECT USERNAME,ACCOUNT_STATUS,LOCK_DATE FROM DAB_USERS WHERE USERNAME='TEST'; 删除用户 DROP USER TEST; 删除用户及该用户下所有对象 DROP USER TEST CASCADE; 锁定/解锁用户 用户加锁 ALTER USER TEST ACCOUNT LOCK; 用户解锁 ALTER USER TEST ACCOUNT UNLOCK; 用户解锁并重新设置密码 ALTER USER HR ACCOUNT UNLOCK IDENTIFIED BY HR; --如果装完数据库没有该用户,你可以用unistall重新把他装上去的。程序运行执行dbca.bat 权限 1 权限是执行特殊sql语句的权利 2 数据库管理员(dba)是一个具有授予用户访问数据库对象的能力的高级用户。 3 用户需要系统权限来访问数据库,需要对象权限来操作数据库中对象的内容。 权限分类 系统权限 如连接数据库权限,建表权限 1 CREATE SESSION 2 CREATE TABLE 3 CREATE SEQUENCE 4 CREATE VIEW 5 CREATE PROCEDURE 对象权限 如 某张表的查询,删除权限 1 GRANT SELECT ON EMP TO HR; 2 GRANT UPDATE,INSERT,DELETE ON EMP TO HR; 3 GRANT ALL ON EMP TO HR; 4 GRANT CONNECT TO TEST; 5 GRANT SELECT ANY TABLE TO TEST; 6 GRANT RESOURCE TO TEST; 7 GRANT SELECT ANY DICTIONARY TO TEST; 权限的授予和回收 授予权限,用grant语句 GRANT CREATE SESSION,CREATE TABLE TO TEST; 回收权限,用revoke语句 REVOKE CREATE TABLE FROM TEST; 系统权限级联授权,不能级联收回 WITH ADMIN OPTION 对象权限级联授权,可以级联收回 WITH GRANT OPTION 角色 1 权限不仅可以授予用户,也可以授予角色 2 角色是命名的可以授予用户的相关权限的组,该方法使得授予,撤回和维护权限容易的多。 3 一个用户可以使用几个角色,并且几个用户也可以被指定相同的角色 4 角色为数据库应用程序创建 5 用户也可以将被授予的权限给其他用户或者角色,角色是相关权限的命名分组。 创建角色 CREATE ROLE REMP; 将权限授予角色 GRANT SELECT ON SCOTT.EMP TO REMP; 将角色授予用户 GRANT REMP TO TEST; --主要用来管理权限 GRANT CREATE SESSION TO PUBLIC --给所有连接权限 SELECT * FROM USER_SYS_PRIVS; --用户系统权限查看 SELECT * FROM ROLE_ROLE_PRIVS; --角色权限查看 SELECT * FROM USER_ROLE_PRIVE; --用户有哪些角色查看 SELECT ROLE,TABLE_NAEM,COLUMN_NAME,PRIVILEGE FROM ROLE_TAB_PRIVS; --角色里表和列的权限 SELECT PRIVILEGE FROM ROLE_SYS_PRIVS WHERE ROLE='RESOURCE';--角色resource下面的权限 SELECT TABLE_NAME FROM DICTIONARY WHERE TABLE_NAME LIKE '%PRIVS';--从数据字典里面查看带有权限的 查看当前用户 1 SHOW USER 2 SELECT SYS_CONTEXT('USERENV','SESSION_USER') FROM DUAL; 3 SELECT SYS.LOGIN_USER FROM DUAL; 4 SELECT USER FROM DUAL; CREATE PUBLIC SYNONYM EMP FOR V_DEPT_EMP; --创建一个公共同义词 十五 高级sql及应用 with语句的优点 1 增加sql可读性。如:对于特定with子查询取个有意义的名字 2 with子查询只执行一次,将结果存储在用户临时表空间中,可以引用多次,增强性能 --with语句主要用在select语句中 示例: --查找emp表中的第五到第十行数据 --先取emp表的rownum with emp_rn as (select rownum rn,emp.* from emp) select * from emp_rn e where e.rn>=5 and e.rn<=10; --查询出部门总薪水大于所有部门平均总薪水的部门 --step1:查询出部门名和各部门的总薪水 with dept_costs as (select a.dname dname,sum(b.sal) dept_total from dept a,emp b where a.deptno=b.deptno group by dname), --利用上一个with查询的结果,计算部门的平均总薪水 avg_costs as (select avg(dept_total) dept_avg from dept_costs) --avg_costs as (select sum(dept_total)/count(*) dept_avg from dept_costs) --从两个with查询中比较并输出结果 select dname,dept_total from dept_costs where dept_total>(select dept_avg from avg_costs) order by dname; --with 语句不能用在update delete 中。 分析函数 处理一些复杂的需求 如: 1 查找上一年度各个销售区排名前10的员工 2 按区域查找上一年度订单总额占区域订单总额20%以上的客户 3 查找上一年度销售最差的部门所在的区域 4 查找上一年度销售最好和最差的产品 上面的查询与我们日常查询的区别 1 需要对同样的数据进行不同级别的聚合操作 2 需要在表内将多条数据和同一条数据进行多次的比较 3 需要在排序完的结果集上进行额外的过滤操作 用分析函数排名 1 dense_rank() 有重复的数字不跳着排列,如:两个并列第一,后面是第二名 示例:在emp表中查出每个部门工资前三的员工信息 select * from (select deptno,ename,sal,dense_rank() over(partition by deptno order by sal desc) drk from emp) where rk<=3; 2 rank() 有重复的数字跳着排列,两个并列第一,后面是第三名 示例:在emp表中查出每个部门工资前三的员工信息 select * from (select deptno,ename,sal,rank() over(partition by deptno order by sal desc) rk from emp) where rk<=3; 3 row_number() 不管重复值,会依次按顺序排序 示例:在emp表中查出每个部门工资前三的员工信息 select * from (select deptno,ename,sal,row_number() over(partition by deptno order by sal desc) rn from emp) where rk<=3; --联合展示 select * from (select deptno,ename,sal, dense_rank() over(partition by deptno order by sal desc) drk, rank() over(partition by deptno order by sal desc) rk, row_number() over(partition by deptno order by sal desc) rn from emp ) where drk<=3; --用排名分析函数时 order by 子句不能少 --在emp表中抽样 每隔一行取数据 select ename,sal,mod(rn,2) as m from (select row_number() over(order by ename) rn,ename,sal from emp) x where mod(rn,2)=1; 聚合函数对应的分析函数 1 sum() select empno,ename,sal,sum(sal) over(partition by deptno) from emp; select empno,ename,sal,sum(sal) over(partition by deptno order by sal) from emp; select deptno,ename,sal,sum(sal) over(order by ename) 连续求和, sum(sal) over() 总和, 100*round(sal/sum(sal) over(),4) as 占总和比列 from emp; --查看执行计划 --step1 explain plan for select ename,sal,sum(sal) over(order by empno) s from emp order by empno; --step2 select * from table(dbms_xplan.display(null,null,'all')); --默认窗口子句是 range between unbounded preceding and curent row 分析函数之窗口子句 --只能用在order by后面 1 rows 表示以行来开窗,什么类型都可以,可以多列 select e.empno,e.sal, sum(e.sal) over(order by e.sal) s1, sum(e.sal) over(order by e.sal rows between unbounded preceding and current row) s2 from emp e; 2 range 表示以偏移量来开窗,与当前行的偏移量。只能用number和date类型,且只能有一列 select e.empno,e.sal, sum(e.sal) over(order by e.sal) s1, sum(e.sal) over(order by e.sal range between unbounded preceding and current row) s2 from emp e; /*between unbounded preceding and unbounded following n preceding n following current row current row */ 示例: select ename,sal,hiredate,sum(sal) over(order by hiredate range between interval '2' day preceding and interval '2' day following ) hd from emp; --求最后一个值和最开始一个值 select deptno,ename,sal, first_value(sal) over(partition by deptno) deptsal, last_value(sal) over(partition by deptno) deptsal2 from emp; --求百分比 select sal,ratio_to_report(sal) over() from emp; 3 默认窗口子句是 range between unbounded preceding and curent row --默认前面所有行到当前行 4 lead(arg1,[n,arg3]) 向下,取下面第n行的记录 lag(arg1,[n,arg3]) 向上,取上面第n行的记录 三个参数: 第一个参数列名,第二个参数偏移量,第三个参数是超出记录窗口时的默认值(默认显示为null,可以指定)。 示例: select ename,sal,lead(sal) over(order by sal) s from emp; select ename,sal,lead(sal,2,-1) over(order by sal) s from emp; select ename,sal,lag(sal,2,-1) over(order by sal) s from emp; 增强型分组函数 1 rollup 单向组合 --使用在group by子句后面 select deptno,sal,sum(sal) from emp group by rollup(deptno,sal); --后面的列依次递减 deptno,sal sal null 2 cube 多向组合 --cube(a,b,c)-->(a,b,c) (a,b) (a,c) (b,c) (a) (b) (c) select deptno,job,sum(sal) from emp group by cube(deptno,job); 3 grouping 函数标识组合列 select deptno,job,grouping(deptno),grouping(job),sum(sal) from emp group by rollup(deptno,job); --grouping 下面 1 表示汇总的列 4 grouping sets 自定义组合方式 select deptno,job,sum(sal) from emp group by grouping sets ((deptno,job),()); 层次查询(等级查询hierarchical query) 等级查询/层次查询语法 select [level],column,expr... from table [where condition] start with condtion connect by [prior column1=column2|column1=prior column2]; 层次查询之SYS_CONNECT_BY_PATH 1 sys_connect_by_path(column,char),其中column是字符型或能自动转换成字符型的列名 2 它的主要目的是将父节点到当前节点的层次路径按照指定的模式展现出现 3 这个函数只能用在层次查询中 示例: select level,sys_connect_by_path(ename,'|') full_name from emp --where level=4 start with mgr is null connect by prior empno=mgr; select ename,lpad(' ',2*level-1)||sys_connect_by_path(ename,'|') "path" from emp start with mgr is null connect by prior empno=mgr; --connect_by_isleaf select ename,connect_by_isleaf isleaf, lpad(' ',2*level-1)||sys_connect_by_path(ename,'|') "path" from emp start with mgr is null connect by prior empno=mgr; 行列转换 1 实际应用中,需要行转成列或者需要列转成行 2 oracle 11g新特性 pivot:行转列 unpivot:列传行 pivot语法-行转列 select... from... pivot[xml] (pivot_clause pivot_for_clause pivot_in_clause) where... --pivot_clause:定义被聚合的列(pivot是一种聚合操作)聚合操作的函数和处理对象 --pivot_for_clause:定义被分组和转换的列,依据那个列进行行转列 --pivot_in_clause:定义pivot_for_clause子句中的列的过滤器(例如使用值的范围来限制结果) --pivot_in_clause中每个值的聚合都将被转换成单独的列 --因为要将数据行取值转成列,我们需要告诉Oracle那些取值成列,并且这些取值成列的过程中,列顺序是怎样的。 示例: select * from score pivot (sum(grade) for subject in('language','english','math')); --可以使用decode 示例: --行转列 select name, sum(decode(subject, 'language', grade)) language, sum(nvl(decode(subject, 'math', grade), 0)) math, sum(nvl(decode(subject, 'english', grade), 0)) english from score group by name; unpivot语法-列转行 select... from... unpivot[include|exclude nulls] (unpivot_clause pivot_for_clause unpivot_in_clause) where... --include|exclude nulls:这个选项用来控制unpivot是否包含null的记录,默认不包含nulls --unpivot_clause:对应的具体值 --pivot_for_clause:对应转换后列的名称 --unpivot_in_clause:具体列到行的列名 --使用union all 进行列转行 select name, 'language' subject, language grade from score2 union all select name, 'math' subject, math grade from score2 union select name, 'english' subject, english grade from score2 order by name; --使用insert all 进行列转行 --创建一张表 create table score3( name varchar2(10), subject varchar(10), grade number(3)); --插入数据 insert all into score3 values(name,'language',language) into score3 values(name,'english',english) into score3 values(name,'math',math) select name,language,english,math from score2; --使用unpivot select * from score2 unpivot (grade for subject in(language,english,math)); --列转行 包 wmsys.wm_concat select deptno,wmsys.wm_concat(ename) from emp group by deptno; select wm_concat(ename) from emp; 分页 分页就是取第n行到第m行的数据 --第一种方法 select * from (select a.*,rownum rn from emp a) where rn>=5 and rn<=10; --第二种方法 select * from emp a where rownum<=6 and a.empno not in (select b.empno from emp b where rownum<=4);--not in 先执行 --第三种方法 select * from ( select a.*,row_number() over(order by empno desc) rk from emp a) where rk<=10 and rk>=5; --第四种方法 select * from emp where rownum<=10 minus select * from emp where rownum<=5; 十六 --2016-10-11 --plsql图标直接打开文件可以看到其相应的配置文件 --工具--〉首选项 --sublime text软件使用 --表 --rowid 伪列 特殊情况下可以改变 select rowid,emp.* from emp; dbms_rowid --包里面找到相应的列 --删除插入过程中rowid不会重复利用,oracle自动管理 导致块的利用率低 --8kb I/O select dbms_rowid.rowid_object(rowid) object_id, dbms_rowid.rowid_relative_fno(rowid) rfile, dbms_rowid.ROWID_BLOCK_number(rowid) block, dbms_rowid.rowid_row_number(rowid) row#, emp.* from emp; --去重 select * from emp where rowid in ( select min(rowid) from emp group by empno); delete from emp where rowid not in (select min(rowid) from emp group by empno) --删除后增加改变rowid --merge 合并 --update emp set sal=sal+1 delete from emp where empno in (select empno from ((select * from emp minus (select * from scott.emp)))) insert into emp select * from scott.emp minus select * from emp; select * from emp; select * from newemp; --创建新表 create table newemp as select * from emp where deptno=30; insert into newemp(empno,ename) values (1111,'scott'); update newemp set sal=2000 where empno=7499; --用merge into更新emp表中数据 merge into emp o using newemp n on (o.empno=n.empno) when matched then update set o.sal=n.sal delete where o.ename='JONES' when not matched then insert (o.empno,o.ename,o.sal) values (n.empno,n.ename,n.sal) --database link 主要用于数据库之间的拷贝和传送 link连接 select * from user_role_privs; select * from user_sys_privs; --where sqlplus /set oracle_home 查看oracle_home地址 --sqlplus scott/scott@orcl_mandy 连接其它数据库 --只有当前用户可以用这个数据连接 grant create database link to mandy;--授权创建数据连接 create database link dblink_mandy connect to scott identified by "scott" using 'orcl_mandy'; --创建公用的数据连接 grant create public database link to mandy;--授权创建公用数据连接 create public database link dblink_mandy connect to scott identified by "scott" using 'orcl_mandy'; --删除 drop database link dblink_mandy --删除数据连接 drop public database link dblink_mandy--删除公用数据连接 select * from wzh_ods_emp@dblink_mandy; --创建拷贝表 create table wzh_emp as select * from wzh_ods_emp@dblink_mandy select * from wzh_emp; --copy sqlplus命令 copy from scott@orcl_mandy append emp_test using select * from emp; copy from scott@orcl_mandy create emp_test using select * from emp; copy from scott@orcl_mandy insert emp using select * from emp;--需要原表 copy from scott/scott@orcl_mandy replace emp_tset using select * from emp; --在sqlplus命令窗口 可以不登陆用户,登陆到sqlplus copy from scott@orcl_mandy to mandy@orcl_lf append emp_test using select * from emp; --hwm 高水位 ANALYZE TABLE EMP COMPUTE STATISTICS;--统计信息 先执行然后执行下面sql语句 select * from user_segments where segment_name='EMP'; SELECT * FROM USER_TABLES WHERE TABLE_NAME='EMP'; select * from emp; INSERT INTO EMP SELECT * FROM SCOTT.EMP; 用delete删除数据测试 --降低高水位 两种方法 --重建表 create table emp_t as select * from emp; drop table emp purge; alter table rename emp_t to emp; --truncate回收空间 数据全部删除直接用truncate truncate table emp; --表里面有数据 --1 通过移动表空间需要双倍的空间 1 alter table emp move tablespace users; --修改表空间 2 alter table emp enable row movement; --设置成行移动 行来移动 alter table emp shrink space; shrink 收缩 alter table emp disable row movement; --ddl语句会改变rowid create table emp1 as select 1 id from dual; alter table emp move tablespace user; 临时表 --临时表 temporary 只在当前会话窗口有效 SELECT DBMS_METADATA.GET_DDL('TABLE','T_EMP','MANDY') FROM DUAL;--查看建表语句 --事务独立 commit create global temporary table t_emp(id int,name varchar2(10));--默认ON COMMIT DELETE ROWS create global temporary table t_emp1(id int,name varchar2(10)) on commit delete rows;--提交删除 --会话独立 session 一个连接 create global temporary table t_emp2(id int,name varchar2(10)) on commit preserve rows;--提交保留 insert into t_emp1 values (1,'a'); insert into t_emp2 values (2,'b'); select * from t_emp1; select * from t_emp2; commit; select * from t_emp1;--提交时删除数据 select * from t_emp2;--提交时保留数据 create global temporary table t_emp3 as select * from scott.emp;--create为ddl语句 create global temporary table t_emp4 on commit preserve rows as select * from scott.emp;--加提交保留 select * from t_emp3; select * from t_emp4; 表 表空间 表数据文件查看 --表 select * from v$datafile; name中以dbf结尾的是数据文件 --表空间 select * from dba_tablespaces; --表空间 由数据文件组成 select * from dba_data_files; --数据文件 --SYSTEM SYSAUX系统 数据字典 --UNDOTBS1 日志 --TEMP 临时 --创建alter tablespace users add datafile 'F:\ORACLE\ORADATA\ORCL\USERS02.DBF' size 10m; --删除alter tablespace users drop datafile 'F:\ORACLE\ORADATA\ORCL\USERS02.DBF' --块-区-段 段相当于表 以块为单位存储数据 --数据文件 select * from dba_data_files; select bytes/1024/8,blocks from dba_data_files; --段SQMENT 由extent组成,extent由block组成 select * from dba_segments where owner='MANDY' or SEGMENT_NAME='EMP'; SELECT SEGMENT_NAME,TABLESPACE_NAME,SEGMENT_TYPE,BYTES/1024/1024 MB FROM dba_segments where owner='MANDY' or SEGMENT_NAME='EMP'; --查看类型,表空间, --区EXTENT 最低8个块 select * from dba_extents where owner='MANDY' and SEGMENT_NAME='EMP'; --块BLOCK 一个block=8kb,数据仓库block大点 select DISTINCT BLOCKS from dba_extents WHERE BLOCKS > 8; SELECT DBMS_METADATA.GET_DDL('TABLE','EMP','MANDY') FROM DUAL; rowid --rowid 伪列 特殊情况下可以改变 select rowid,emp.* from emp; dbms_rowid --包里面找到相应的列 --删除插入过程中rowid不会重复利用,oracle自动管理 导致块的利用率低 --8kb I/O select dbms_rowid.rowid_object(rowid) object_id, dbms_rowid.rowid_relative_fno(rowid) rfile, dbms_rowid.ROWID_BLOCK_number(rowid) block, dbms_rowid.rowid_row_number(rowid) row#, emp.* from emp; --去重 select * from emp where rowid in ( select min(rowid) from emp group by empno); delete from emp where rowid not in (select min(rowid) from emp group by empno) database link 数据连接 --database link 主要用于数据库之间的拷贝和传送 link连接 select * from user_role_privs; select * from user_sys_privs; --where sqlplus /set oracle_home 查看oracle_home地址 --sqlplus scott/scott@orcl_mandy 连接其它数据库 --只有当前用户可以用这个数据连接 grant create database link to mandy;--授权创建数据连接 create database link dblink_mandy connect to scott identified by "scott" using 'orcl_mandy'; --创建公用的数据连接 grant create public database link to mandy;--授权创建公用数据连接 create public database link dblink_mandy connect to scott identified by "scott" using 'orcl_mandy'; --在dba用户下面授权 grant database link to mandy; drop database link dblink_mandy --删除数据连接 drop public database link dblink_mandy--删除公用数据连接 select * from wzh_ods_emp@dblink_mandy; --创建拷贝表 create table wzh_emp as select * from wzh_ods_emp@dblink_mandy select * from wzh_emp; hwm 高水位 ANALYZE TABLE EMP COMPUTE STATISTICS;--统计信息 先执行后执行下面sql语句 select * from user_segments where segment_name='EMP'; SELECT * FROM USER_TABLES WHERE TABLE_NAME='EMP'; select * from emp; INSERT INTO EMP SELECT * FROM SCOTT.EMP; 用delete删除数据测试 --降低高水位 两种方法 --重建表 create table emp_t as select * from emp; drop table emp purge; alter table rename emp_t to emp; --truncate回收空间 数据全部删除直接用truncate truncate table emp; --表里面有数据 --1 通过移动表空间需要双倍的空间 alter table emp move tablespace users; --修改表空间 alter table emp enable row movement; --设置成行移动 行来移动 alter table emp shrink space; alter table emp disable row movement; --ddl语句会改变rowid create table emp1 as select 1 id from dual; alter table emp move tablespace user; 行连接与行迁移 --行连接跟行迁移 --行连接 一个行存储在多个块中的情况 --行迁移 一个数据行不适合放入当前块而被重新定位到另一个块,在原始块中保留一个指针 --行迁移: 当一个行上的更新操作(原来的数据存在且没有减少)导致当前的数据不能在容纳在当前块,我们需要进行行迁移。一个行迁移意味着整 -- 行数据将会移动,仅仅保留的是一个转移地址。因此整行数据都被移动,原始的数据块上仅仅保留的是指向新块的一个地址信息。 -- 产生:update --行链接: 当一行数据太大而不能在一个单数据块容纳时,行链接由此产生。举例来说,当你使用了4kb的Oracle 数据块大小,而你需要插入一行数据是8k, -- Oracle则需要使用3个数据块分成片来存储。因此,引起行链接的情形通常是,表上行记录的大小超出了数据库Oracle块的大小。 -- 产生:insert -- 表上使用了LONG 或 LONG RAW数据类型的时候容易产生行链接。其次表上多于255列时Oracle会将这些过宽的表分片而产生行链接 --3.迁移行对索引读产生额外的I/O,对全表扫描没什么影响 -- 行链接则影响索引读和全表扫描 --每个块预留10%的空间 pct free insert不能用,主要用在update --2016-10-12 --查找表的行连接 F:\ORACLE\product\11.2.0\dbhome_1\RDBMS\ADMIN\utlchain.sql --在sqlplus命令中@执行 创建表 CHAINED_ROWS