Oracle SQL 笔记


1 Oracle SQL 笔记 文件修改控制 修改记录编号 修改内容 修改人 修改日期 v0.01/1 将原先笔记整理,加入代码和注意样式 郭大喜 2009-5-26 v0.02/1 加入附录 郭大喜 2009-5-27 [附加说明] 1. “修改记录编号”的填写内容为:本次修改后的版本号+“/”+流水号,例如:V1.01/1。 2. 一次修改可以修改文档的多个位置,流水号为对该版本修改的流水号。当版本变时,流 水号归为 1。 2 正文 ................................................................................................................................................ 5 SQL DAY1 ................................................................................................................................................ 5 1.1SQL 介绍 ..................................................................................................................................... 5 ■ SQL(Structur Query Language 结构化查询语言)是操作关系型数据库中的对象。 ........................... 5 ■ sqlplus 访问数据库命令(本地访问/远程访问) .............................................................................. 5 1.2 select 查询语句.......................................................................................................................... 6 1.3 函数 ........................................................................................................................................... 8 ■ Oracle 中的空值 .................................................................................................................................... 8 ■ column 命令(这是个 sqlplus 命令) .................................................................................................. 8 ■选择操作 where 子句 .............................................................................................................................. 9 ■ order by 排序子句 .............................................................................................................................. 10 1.4 Oracle 数据库函数(单行函数) ........................................................................................... 10 1,字符函数................................................................................................................................................. 10 2,数值函数................................................................................................................................................. 10 3,日期函数 .............................................................................................................................................. 11 4,不同数据类型间转换函数 .................................................................................................................. 11 5,函数嵌套 .............................................................................................................................................. 12 6, 日期的补充 ........................................................................................................................................... 12 7, NVL(XX,XX) ............................................................................................................................................. 13 8、设置编码: .......................................................................................................................................... 13 SQL DAY2 ........................................................................................................................................... 13 2.1 多表查询 ................................................................................................................................. 13 2.1.1 等值连接.......................................................................................................................................... 13 2.1.2 非等值连接 ...................................................................................................................................... 14 2.1.3 自连接 ............................................................................................................................................. 14 2.1.4 外连接 ............................................................................................................................................. 15 2.2 组函数 ..................................................................................................................................... 15 2.2.1 group 组 ............................................................................................................................................ 15 2.2.2 having 子句 ....................................................................................................................................... 16 2.3 子查询 ..................................................................................................................................... 17 2.4 数据库设计 ............................................................................................................................. 18 2.4.1 概述 .................................................................................................................................................. 18 2.4.2 ER 图(实体关系图) ........................................................................................................................... 18 2.4.3 范式 ................................................................................................................................................. 19 2.5 约束 ......................................................................................................................................... 19 2.6 约束的应用 ............................................................................................................................. 20 一对多 ....................................................................................................................................................... 20 一对一 ....................................................................................................................................................... 20 多对多 ....................................................................................................................................................... 21 实体关系的表现 ........................................................................................................................................ 21 2.7 建表和其他相关操作 ............................................................................................................. 23 ■ 创建表(DDL): ..................................................................................................................................... 23 ■ Oracle 数据库中的数据类型............................................................................................................... 23 ■ primary key 约束: .............................................................................................................................. 24 3 ■ foregin key(fk)外键约束: ..................................................................................................................... 24 ■ on delete 级联删除 ............................................................................................................................. 24 SQL DAY3 .............................................................................................................................................. 25 3.1 约束 ......................................................................................................................................... 25 3.2 约束续 ..................................................................................................................................... 26 3.2.1 非空约束(not null) ..................................................................................................................... 26 3.2.2 unique 唯一约束 ............................................................................................................................. 26 3.2.3 check 约束 ........................................................................................................................................ 26 3.4 DML 操作 ................................................................................................................................. 27 3.4.1 insert 操作,插入记录 ..................................................................................................................... 27 3.4.2 update 修改操作 .............................................................................................................................. 27 3.4.3 delete 删除操作 ............................................................................................................................... 28 3.5 事务 transaction ..................................................................................................................... 28 3.6 alter table 命令 ........................................................................................................................ 29 增加字段: ................................................................................................................................................ 30 删除字段: ................................................................................................................................................ 30 给列改名:9.2.0 才支持 .............................................................................................................................. 30 修改字段 ................................................................................................................................................... 30 解除约束:(删除约束) ............................................................................................................................. 30 使约束失效或者生效 ................................................................................................................................ 31 更改表名 ................................................................................................................................................... 31 删除表: ................................................................................................................................................... 31 3.7 序列(sequence) ........................................................................................................................ 31 创建 sequence ........................................................................................................................................... 31 查看 sequence ........................................................................................................................................... 32 3.8 视图 view ................................................................................................................................ 32 介绍 ........................................................................................................................................................... 32 创建视图 ................................................................................................................................................... 32 试图的约束 ................................................................................................................................................ 33 内嵌视图 ................................................................................................................................................... 33 联合视图 ................................................................................................................................................... 33 删除视图 ................................................................................................................................................... 33 更新视图 ................................................................................................................................................... 34 对视图进行 DML 操作规则 ...................................................................................................................... 34 行号(rownum) ...................................................................................................................................... 34 3.9 关于同义词: .......................................................................................................................... 34 3.10 索引(index) ....................................................................................................................... 35 索引介绍 ................................................................................................................................................... 35 rowid .......................................................................................................................................................... 35 索引创建 ................................................................................................................................................... 36 哪些字段应该建索引 ................................................................................................................................ 36 查找索引 ................................................................................................................................................... 36 替换变量 ................................................................................................................................................... 37 3.11 数据字典 ................................................................................................................................ 37 4 附.................................................................................................................................................. 38 一、各数据库自增列 ........................................................................................................................ 38 二、ORACLE 相关 ................................................................................................................................ 39 创建用户与授权语法 .................................................................................................................... 39 创建用户 ................................................................................................................................................... 39 用户授权 ................................................................................................................................................... 39 实例操作 ........................................................................................................................................ 39 5 正文 SQL day1 1.1SQL 介绍 ■ SQL(Structur Query Language 结构化查询语言)是操作关系型数据库中的对象。 - DDL(Data Definition Language 数据定义语言) 用于建表或删表操作,以及对表约束进行修改。类似画表头。 对结构的操作 create table alter table drop table - DML(Data Manipulation Language 数据操作语言) 增删改查;向表中插入记录、删除记录、修改记录和查找记录。 insert update delete merge select 投影,过滤(选择)查询,关联查询(表连接)。 - 事务 Transaction 控制语言 commit,rollback,savepoint - DCL 授权语句 grant ■ sqlplus 访问数据库命令(本地访问/远程访问) - %sqlplus 用户名/密码 - 查看当前环境 %which sqlplus /oracledata/oracle/product/9.2.0/bin/sqlplus %echo $ORACLE_SID 数据库对应的实例名 ORACLE_BASE=/oracledata/oracle ORACLE_HOME=/oracledata/oracle/product/9.2.0 ORACLE_SID=tarena - SQL>show user 显示当前用户的用户名 - SQL>connect sd0702/sd0702 SQLPLUS 命令 - 在 sqlplus 中可以使用 ! 可以在 shell 和 sqlplus 间切换,!shell 命令 可以在 sqlplus 中 使用 shell 命令。实际上是 sqlplus 开了子进程来执行 shell 命令。 - Oracle 数据库中的表分两类: 用户表(用户使用操作的表) 系统表(数据库系统维护的表,数据字典) 6 1.2 select 查询语句 ■常用表字段介绍 SQL> desc s_emp;(员工表) Name Null? Type ----------------------------------------- -------- ---------------------------- ID(员工编号) NOT NULL NUMBER(7) LAST_NAME NOT NULL VARCHAR2(25) FIRST_NAME VARCHAR2(25) USERID VARCHAR2(8) START_DATE(入职日期) DATE COMMENTS VARCHAR2(25) MANAGER_ID(领导的员工号) NUMBER(7) TITLE(职位) VARCHAR2(50) DEPT_ID(部门号) NUMBER(7) SALARY(月薪) NUMBER(11,2) COMMISSION_PCT(提成,年收入的百分之多少) NUMBER(4,2) SQL> desc s_dept;(部门表) Name Null? Type ----------------------------------------- -------- ---------------------------- ID(部门 ID) NOT NULL NUMBER(7) NAME(部门名) NOT NULL VARCHAR2(25) REGION_ID(地区号) NUMBER(7) SQL> desc s_region;(地区表) Name Null? Type ----------------------------------------- -------- ---------------------------- ID NOT NULL NUMBER(7) NAME NOT NULL VARCHAR2(20) COMMENTS NUMBER ■ - 投影操作,只查看选择的字段的信息。 选择操作,查看字段中的特定某些信息。 多表查询,通过表间连接,查询出多表中的信息 - select table_name from user_tables;(查询系统表) 以上的查询语句就是查询本用户下所拥有的所有表的表名。 - desc [表名] 这是一条 sqlplus 命令,注意他不是 sql 语句,这条命令用于查看 表的结构 [字段名] [字段的类型],这是使用完 desc 命令后显示的表结构。 - sql 语句要以";"结尾,来表示 sql 语句结束,如果不加";"系统不会执行此条 sql 7 语句,并提示。可用 l 或 list 调出缓存,再加“/”执行。 sqlplus 的 buffer 中会缓存最后一条 sql 语句,可以使用"/"来执行这最后一 条 sql 语句,也可以使用 edit 命令来编辑最后一条 sql 语句。l 命令(list)( sqlplus 命令)可以显示 buffer 中最后一条命令。 - !oerr ora [错误号] ,系统可以显示错误的原因和如何修改。 host exit 类似!,开了一个子进程 如果命令错误输入可以使用 edit 或 ed 来修改输入错误。 实际上是在编辑缓存文件中的最后一条 sql 语句。也可以使用 (change) c / 错误字段/正确字段,来进行替换操作进行修改。 ■ select [表的字段名 1],[表的字段名 2], ... from 表名; select * from 表名; 查询表中所有字段的信息 关键字不能拆分,sql 语句,以及表名,字段名是大小写不敏感的。 sqlplus 设置 set pause on 回车响应,分屏显示,只在本会话中有效 set pause off 关闭分屏显示。 set pause 'please press enter key' 设置分屏显示的提示信息。 set pause on 先输出提示信息,回车响应,分屏显示 set head off 提头输出关闭 set feed off 结尾输出关闭 set echo off 回写关闭 spool 文件名.sql 写入指定文件 spool off 关闭写入。 清屏命令 !clear 或 clear screen 在 Oracle 中字符显示是左对齐,数值右对齐。 在 select 语句中可以使用数学表达式。 select [表达式(必须包含本表字段名)],[...],.... from 表名; 运算的优先级的先乘除后加减,同级自左向右运算,括号改变优先级。 ■ select [字段名或表达式] ["别名"],[...] ["..."],.... from 表名; 可以通过在字段名或表达式后加空格"别名",可以给列,或者表达式结果其别 名。 字符串拼接使用||符号 select 目标字段名||" "||目标字段名 from 表名; 8 注意:在 Oracle 中的字符串要用'..'包含 别名中需要使用空格,或是大小写敏感时需要用".."包含。 sql 脚本,也就是在文件中写有 sql 语句的文件,可以在 sqlplus 中运行。 引入 sql 脚本 %sqlplus 用户名/密码 @sql 脚本 注意:在用户名密码输入结束后一定要加空格然后再写@sql 脚本 1.3 函数 ■ Oracle 中的空值 空值会当无穷大处理,其实空值根本就不会存储,只是看作是无穷大。 Oracle 中控制处理函数 NVL(字段名,值),这个字段中的空值替换为指定值, 如果不为空,则会返回其原值。 例:select (salary*12)*(NVL(commission_pct,0)/100+1) salary,first_name from s_emp; distinct 关键字,去掉重复行(这个关键字会触发排序操作) 9i 中,会先排序,然后去掉重复的。 例: select distinct dept_id,title from s_emp; 注意: distinct,会对关键字之后 from 之前的字段进行联合排重操作。 ■ column 命令(这是个 sqlplus 命令) column 命令 列格式的定义 column 目标列名 查看这个类是否定义了格式 格式: column 目标列名 format a.. 设置列宽。 例:column last_name heading 'Employee|Name'(设置题头) FORMAT A15 这其中的'|'是换行符 column salary justify left format $99,990.00(定义数字显示格式) 注意:如果不满足显示的格式,就会把数据显示为"#" column 列名 clear (清除列格式定义) column 也可以定义有别名的列的格式。 9 column "别名" 格式定义 注意:只有 sqlplus 命令才有简写,并且在使用 sqlplus 命令时结尾也不能加分 号。 环境变量:$ NLS_LANG:语言 国家_地区.字符集 数据库本身的字符集 %ECHO $NLS_LANG %setenv NLS_LANG 'SIMPLIFIED CHINESE_CHINA.ZHS16GBK' %setenv NLS_LANG 'AMERICAN_AMERICA.US7ASCII' ■选择操作 where 子句 where 子句使用在 select ... from ... 后面,用来选择所需(符合条件的)的记 录 where 后面只能跟单行函数。 ● where 后面跟的是表达式 也就是 XXX=XXX, XXX between X and X ,XXX in(X,X,X)like '...' 通配查询 ● between ... and ... ,表示结果在这之间,between and 是一个闭区间, 也就相当于... <= ... and ... >= ... 。 ● !=,<>,^=,这三个都标识不等于,<=,>=,=,这些运算符都可以使用。 ● ... in (va1,val2,...) 判断结果是否在这个枚举中存在 和 =any(val1, val2, …) 意思相同 应该将分布大的往前放。 ● like '...' 字符串通配查询,'%'表示多个字符,'_',表示一个字符。要注意大小写敏感。 例:select table_name from user_tables where table_name like'S\_%' escape '\' ● ... and ... 表示只有两个条件同时满足 ● ... or ... 表示条件只要满足其中只一就可以 ● all ... 是要求都满足条件。 ● not .....,则是可以与以上的条件产生反效果。 空值会对 not in 造成影响,也就是不等于任何值,但是空值例外。 ● ... is null 是用来判断值是不是空。 ● not in 等价于<>all 注意: 1、Oracle 中的字符串是严格区分大小写的。 2、注意数据类型,数字类型直接写,字符用'......' ,缺省格式的 Date 可以用'......', 只有别名才用" "包含。 3、选择合适的运算符 4、where 条件后尽量避免表达式和类型转换 10 ■ order by 排序子句 order by 排序子句 ASC(默认,升序) DESC(降序) 后面可以跟字段名、表达式还有 POSTION(位置) order by 目标列名(别名) 排序顺序(不写排序顺序,会默认为升序排序) 例:select first_name from s_emp order by first_name; select first_name from s_emp order by first_name desc; 注意 1、升序空值在结果的末尾,降序空值在结果的最前面,可以将空值理解为无穷大 2、执行顺序:from – where – select – order by 3、where 后面不能跟别名 1.4 Oracle 数据库函数(单行函数) Oracle 中的函数和 C 中的函数差不多,也是有函数名,参数表,和返回值类型组成 的 1,字符函数 字符是大小写敏感的 lower(...) 转小写 upper(...) 转大写 initcap(...) 首字母大写 concat(...,....) 字符串拼接 substr(...,起始位置,取字符个数) 求指定子串 可以使用"-"表示从右向左取,取的时候可以从左往友取。 例:select substr(first_name,-2,2) sub from s_emp;(取后两个) select substr(first_name,2,2) sub from s_emp;(取前两个) dual 表,是专门用于函数测试和运算的,他只有一条记录 D/X 2,数值函数 round(数据,保留小数点后几位)四舍五入 可以用负数表示小数点前,0,表示小数点后第一位,也就是保留个位,-1 表示个位(保留到十 位)。 例:select round(15.36,1) from dual; 11 trunc(数据,保留的位数(小数点后位数)) 截取数字函数 截取个位之后补 0 例:select trunc(123.456,1) from dual; 3,日期函数 ■ 日期格式:全日期格式 世纪信息,年月日,时分秒。 缺省日期格式,日-月-年 dd-mon-rr 修改当前会话的日期格式,会按照指定的格式输出日期 alter session set nls_date_format='yyyy mm dd hh24:mi:ss'; INSERT INTO EMP VALUES (7934, 'MILLER', 'CLERK', 7782, TO_DATE('23-JAN-1982', 'DD-MON-YYYY','NLS_DATE_LANGUAGE = American'), 1300, NULL, 10); ■ 返回当前日期 sysdate 例:select sysdate from dual; 日期是格式敏感的 months_between(date1,date2) 求两个日期间相隔了多少个月 add_months(date,月数)加减指定数量的月份 ,月数可以为负,负值就是减去相 应的月数。 next_day(date,星期数)返回 date 后的第星期几 例:select next_day(sysdate,2) from dual; last_day(date)返回月末的日期 round(sysdate,'MONTH') 以月四舍五入,上下半月 round(sysdate,'YEAR') trunc(date,'年或月或日或时分秒')截取日期 例:下个月第一天的日期 select trunc(add_months(sysdate,1),'month') from dual; 4,不同数据类型间转换函数 to_char(date,'日期格式') 将日期转成字符 日期格式要用有效格式,格式大小写敏感 to_char(number,'fmt') fmt 是数字格式将数字转字符 12 'yyyy mm dd hh24:mi:ss' 年月日时分秒, 'year'(全拼的年), 'mm'(数字表示的月) 'month'(全拼的月), 'day'(星期的全拼), 'ddspth' (日期的全拼) 'yy mm dd' 例:select to_char(sysdate,'yyyy mm dd hh24:mi:ss')from dual; to_number('...') 将字符转换成数字 to_date('...','日期格式') 将字符串转成日期 例:select to_char(to_date('2006 11 03','yyyy mm dd'),'dd-month-yy') from dual; 例:找出三月入职的。’mm’=3 1* select first_name,start_date from s_emp where to_char(start_date,'mm')='03' SQL> / FIRST_NAME START_DAT ------------------------- --------- Carmen 03-MAR-90 LaDoris 08-MAR-90 Audry 04-MAR-90 George 08-MAR-90 Bela 17-MAR-91 5,函数嵌套 例:select to_char(to_date('2006 11 03','yyyy mm dd'),'dd-month-yy') from dual; 6, 日期的补充 DD-MON-RR 格式 字符大小写敏感,日期模式敏感 YY 格式:始终把当前的世纪信息直接取过来 RR 格式:插的时候,把要插入年分为前 50 年和后 50 年,把当前年也分为前后 50 年 13 7, NVL(XX,XX) 对二参数的类型进行匹配 8、设置编码: (Windows) set NLS_LANG=american_america.us7ascii (Unix) setenv NLS_LANG AMERICAN_AMERICA.ZHS16GBK #setenv NLS_LANG SIMPLIFIED CHINESE_CHINA.ZHS16GBK nls national language support 国家语言支持 SQL Day2 2.1 多表查询 如果多表查询时不加 where 子句,也就是过滤条件或者是使用了无效的条件,就会 产生两表之间记录的相互逐条匹配(组合),产生很多无效的结果(迪卡尔积)。 注意 在使用表连接时,要注意查询的表间的关系信息 连接形式(PK,FK) 表之间的字段所表示的信息的关系 表连接(多表查询):分为内连接和外连接 内连接的特点:做精确匹配 - Equijoin (等值连接) - Non-equijoin - Self join 一个表的两个字段有关系往往用自连接. 外连接:一个都不能少.外连接=等值连接+NULL; 2.1.1 等值连接 select [表别名 1.字段名 1],[表别名 2.字段名 2],... from 表 1 表别名 1 ,表 2 表别名 2 14 where 表别名 1.字段名 3=表别名 2.字段名 4; 表连接时,当表与表之间有同名字段时,可以加上表名或表的别名,加以区分,使 用时要用 表名.字段名或表别名.字段名(列名)。当表的字段名是唯一时,可以不用加上表 名或表的别名。 注意:当为表起了别名,就不能再使用表名.字段名。 例:select a.first_name,a.last_name,b.name from s_emp a,s_dept b where a.dept_id=b.id; 例:找出 Mark 在哪个地方上班 select e.first_name, r.name from s_emp e,s_dept d,s_region r where first_name='Mark' and d.region_id = r.id and e.dept_id = d.id 2.1.2 非等值连接 select [表别名 1.字段名 1],[表别名 2.字段名 2],... from 表 1 表别名 1 ,表 2 表别名 2 where 表别名 1.字段名 3 ..... 表别名 2.字段名 4 ....可以使比较运算符,也可以使其他的除了'='的运算符 例:算出员工的工资级别分布 select e.ename, d.grade,e.sal from emp e,salgrade d where e.sal between d.losal and d.hisal; 2.1.3 自连接 用别名把一张表中的数据分成两部分,然后在使用条件过滤。 select [表别名 1.字段名 1],[表别名 2.字段名 2],... from 表 1 表别名 1 ,表 1 表别名 2 where 表别名 1.字段名 3=表别名 2.字段名 4; 例:select a.first_name ename,b.first_name cname from s_emp a,s_emp b where a.manager_id=b.id; 15 会丢失最大的领导记录 以上所提到的表连接,都叫做内连接,严格匹配两表的记录。 2.1.4 外连接 会使用一方表中的所有记录去和另一表中的记录按条件匹配,空值也会匹配,这个 表中的所有记录都会显示,数据库会模拟出记录去和那些不匹配的记录匹配。 例:select a.first_name enamei,a.id,nvl(b.first_name,’boss’) cname,b.id from s_emp a,s_emp b where a.manager_id=b.id(+); 注意 1、要把那一方的记录全部都显示出来,就在那一方后加上+,还有注意条件(+)跟在 要全部显示的那个表的字段后。 2、(+)用来模拟出个空记录和另一张表中空记录进行匹配。 2.2 组函数 2.2.1 group 组 ■ group by 分组子句,按指定的分组规则分组 ,这个 group by 子句可以跟在 select 语句后或是 having 后面。group by 子句也会出发排序操作,会按分组字段排序。 select [组函数或分组的字段名] ,... from 表名 group by [字段名 1],[字段名 2],.....; 例: select avg(salary) from s_emp group by dept_id; 注意 1、组函数可以处理一组数据,返回一个值。 2、除了 count()外,其余组函数会忽略空值,组函数是处理所有的非空值,但不排重。 ■ avg sum 二函数的参数只能是 number 型的。 count max min 三函数的参数可是任何类型 count(..),用来统计记录数,可以使用排重命令。count(...)默认使用的是 all。 max(..),min(..)求最大值和最小值, count(*),统计表中记录数。 16 例:求出所有员工的平均提成 SQL> select avg(nvl(commission_pct,0)) from s_emp; AVG(NVL(COMMISSION_PCT,0)) -------------------------- 2.6 例:求各个部门的平均工资 select max(d.name), avg(e.salary), max(r.name) from s_emp e, s_dept d , s_region r where e.dept_id = d.id and d.region_id=r.id group by d.id; 例:求各个部门不同工种的平均工资: select dept_id , title, avg(salary) from s_emp group by dept_id , title; 注意 1、只要写了 group by 子句,select 后就只能用 group by 后的字段或者是组函数。 2、如果 select 后全用组函数,也可不加上 group by 2.2.2 having 子句 ■ where 子句只能够过滤记录,只能放单行函数。 having 可以过滤组函数结果或是分组的信息,且写在 group by 子句后。 (where 单行函数,having 组函数) 例:除了 32 部门以外的,其它各个部门的平均工资 select dept_id, avg(salary) from s_emp group by (dept_id ) having dept_id!=42; select dept_id, avg(salary) from s_emp where dept_id!=42 group by (dept_id ) ;(此种 sql 效率要高,先过滤再计算) 注意 要先过滤掉不需要的记录,然后再进行分组操作,提高效率。 17 2.3 子查询 ■ 子查询,就是可以嵌在任何的 sql 语句中的 select 语句。 在 select 语句中嵌套子查询时,会先执行子查询。一般的会将子查询放在运算符的 右边。 注意 1、在使用子查询时,要注意这个运算符是单行的(也就是只能是单值),还是多行 运算符(范围,多值)。配合使用子查询返回的结果必须符合运算符的用法。 2、子查询中,会自动做排序排重的。 例:查询谁跟 Smith 的工种一样,去掉 Smith 本人。 select first_name,title from s_emp where title=any( select title from s_emp where last_name='Smith') and upper(last_name)!='SMITH'; select first_name,title from s_emp where title in( select title from s_emp where last_name='Smith') and upper(last_name)!='SMITH'; 例:哪些人的工资比本部门的平均工资高 select e.first_name,e.salary,s.avgsal from s_emp e,(select dept_id,avg(salary) avgsal from s_emp group by dept_id) s where e.dept_id=s.dept_id and e.salary>s.avgsal; 例:哪个部门里没有员工(用子查询的方式来实现): select deptno from dept 18 where deptno not in ( select deptno from emp ); 例:哪些部门的平均工资比 32 部门的平均工资高: SELECT dept_id, AVG(salary) FROM s_emp GROUP BY dept_id HAVING AVG(salary) > (SELECT AVG(salary) FROM s_emp WHERE dept_id = 32); 2.4 数据库设计 2.4.1 概述 数据库表设计,把业务需求转换成可操作的表。 1,需求分析,了解客户的业务需求(业务技能)。 2,设计,通过 ER 图(实体关系图) 3,建表 4,测试 5,形成产品 2.4.2 ER 图(实体关系图) 将一类事物的共性抽象出来成为一个实体,并且表现出来实体间的关系。 * 强制 必要的(也就是要求必须非空)indispensable o 可以可 s 选 # 唯一标识 unique identifier 唯一的值 #* 唯一且非空 primary with 实体关系 one to one 一对一关联, one to many 一对多关联, many to many 多对多关联 19 反射关联,自身的属性之间的关联 ER 图转换成表 2.4.3 范式 第一范式,所有的属性都必须是单值,也就是属性只表示单一的意义。 (记录可以重复,没有任何限制) 第二范式,属性要求唯一且非空, (记录不可重复,但是数据可能会出现冗余)。 第三范式,非主属性只能依赖于主属性,不能依赖于其他非主属性。 (解决数据冗余问题) 2.5 约束 ■ 约束是针对表中的字段进行定义的。 ■ primary key (主键约束 PK)保证实体的完整性,保证记录的唯一 主键约束,唯一且非空,并且每一个表中只能有一个主键, 有两个字段联合作为主键,只有两个字段放在一起唯一标识记录,叫做联合主键。 用 PK,就已经满足了第二范式。 ■ foreign key (外键约束 FK)保证引用的完整性, 外键约束,外键的取值是受另外一张表中的主键或唯一值得约束,不能够取其他值,只 能够引用主键会唯一键的值, 被引用的表,叫做 parent table(父表),被引用列要是 PK 或 UK 引用方的表叫做 child table(子表),FK 引用 要想创建子表,就要先创建父表,后创建子表, 记录的插入也是如此,先父表后子表, 删除记录,要先删除子表记录,后删除父表记录, 要修改记录,如果要修改父表的记录要保证没有被子表引用。 要删表时,要先删子表,后删除父表。 child 表 parent 表 FK PK 20 ■ unuque key(唯一键),值为唯一,并不要求非空 ■ index(索引)是数据库特有的一类对象,view(视图) 索引就是用来提高查询数据效率的,是数据库中的数据。 视图是个逻辑单元,不对应具体的表。 ■ 联合主键,任何一个键可重复,但联合在一起就不可重复了。 2.6 约束的应用 一对多 一个 class 对应多个学生。 FK 一边的对象(学生)可以是多个的,被引用的(班级)是唯一的,所以形成了一对多关系 一对一 PK 互相引用或直接建一个表 id (PK) name address s_id (PK, FK) ShenFen_desc ShenFen_num Person 表 ShenFenZheng 表 id (PK) name address class_id (FK) id (PK) cass_desc class_num Student 表(多) Class 表(一) 21 多对多 引用对方表的主键,当作本身的主键,所以这个表的主键,既是主键又是外建 实体关系的表现 一对一建表语句 student table create table student( id number, name varchar2(32), address varchar2(32) primary key(id) ); shenfenzheng table create tabel shenfenzheng( sid number primary key, num number unique not null, foreign key (sid) references student(id) ); 一对多 class table Student 表 Course 表 s_id (FK) c_id (FK) Grade 联合主键 选课表 s_id (PK) name address c_id (PK) Course_name 22 一 create table class( cid number, class_num number, desc varchar2(32), primary key(cid) ); student table 多 create table student( id number, name varchar2(32), address varchar2(32) class_id number, primary key(id),foreign key (class_id) references class(cid) ); 多对多 create table class ( id number(10,0) not null, name varchar2(15) not null, sdate date, edate date, primary key (id) ); create table class_course ( classid number(10,0) not null, courseid number(10,0) not null, primary key (classid, courseid) ); create table course ( id number(10,0) not null, name varchar2(15) not null, perion number(10,0), primary key (id) ); 23 alter table class_course add constraint fk_class foreign key (classid) references class(id); alter table class_course add constraint fk_course foreign key (courseid) references course(id); 2.7 建表和其他相关操作 ■ 创建表(DDL): create table 表名(字段名 1 类型(数据长度)[default ...] 约束条件, 字段名 2 类型(数据长度)[default ...] 约束条件...); SQL>create table test(c1 number, c2 number default 1); 一个用户一个 schema 配置文件,可在其中配置权限 SQL>grant select on emp to sd0702; SQL>select count(*) from asd0703.emp; ■ Oracle 数据库中的数据类型 varchar2(长度),可变长字符串,varchar2 是 oracle 的类型,varchar 是标准中的类 型,介意使用 varchar2。 char(长度) 定长 number(..,..),number 表示浮点数,或者是整数 number(4,2) 小数点后最大两位,总位数四位 number(2,4) 小数点后 4 位,有效位 2 位 long 大文本的,范围到 2G,存的时候是和其它一样存在表中,规定是一个表只能 有一个 long 类型 clog 字符的大对象,相当于文本文件在表中只存放一个相当于只针对值,最大 4 个 G blog 二进制的大对象,也是以相当于指针的形式存放的,音视频等,在存大对象 时,推荐用 blog. 24 ■ primary key 约束: 列级约束定义形式: create table test(c number primary key); 表级约束定义形式: create table test(c number, primary key(c) ); create table test(c1 number constraints pkc1 primary key ); 此约束有名字:pkc1 create table test(c number, c2 number , primary key (c ,c1) ); 用表级约束可以实现联合主键 ■ foregin key(fk)外键约束: 先定义父表,再定义子表 列级约束定义: carete table parent(c1 number primary key ); create table child(c number primary key, c2 number references parent(c1)); 表级约束定义: create table child( c number primary key, c2 number, foreign key(c2) references parent(c1)); ■ on delete 级联删除 on delete cascade 级联删除,在子表 FK 中设置;Oracle 不支持级联更新,这样删 除部门时,会连员工一起删除的。 on delete set null 删除部门时,不删除人,有关员工的记录只去掉部门号 SQL> create table parent(c1 number primary key); SQL> create table child ( 2 c1 number primary key, 3 c2 number references parent(c1) on delete cascade); SQL> insert into parent values (1); SQL> insert into child values (1,1); SQL> delete from parent; SQL> select * from child; no rows selected 25 SQL day3 3.1 约束 ■ 找出所有员工 select first_name from s_emp where id not in (select manager_id from s_emp where manager_id is not null) 能用连接的不用子查询 ■ 列约束和表约束 约束可以是列约束或表约束: 表级 PRIMARY KEY 约束 FOREIGN KEY 约束 列级 UNIQUE 约束 CHECK 约束 DEFAULT 定义 为空性 列约束被指定为列定义的一部分,并且仅适用于那个列 表约束的声明与列的定义无关,可以适用于表中一个以上的列。 当一个约束中必须包含一个以上的列时,必须使用表约束。 例如,如果一个表的主键内有两个或两个以上的列,则必须使用表约束将这两列加入主键内。 假设有一个表记录工厂内的一台计算机上所发生的事件。假定有几类事件可以同时发生, 但不能有两个同时发生的事件属于同一类型。这一点可以通过将 type 列和 time 列加入双 列主键内来强制执行。 26 CREATE TABLE factory_process (event_type int, event_time datetime, event_site char(50), event_desc char(1024), CONSTRAINT event_key PRIMARY KEY (event_type, event_time) ) 3.2 约束续 3.2.1 非空约束(not null) ■ 这是一个列级约束,只能在列上做操作 在建表时,在数据类型的后面加上 not null ,也就是在插入时不允许插入空值。 SQL>desc table_name 就可以查看 例:create table student( id number primary key, name varchar2(32) not null, address varchar2(32) ); 3.2.2 unique 唯一约束 ■ 唯一约束,是允许为空值的,会忽略空值,可以多个;唯一约束,要求插入的记 录中的值是唯一的。 例:create table student( id number, name varchar2(32), address varchar2(32), primary key (id), unique (address) ); 注意 SQL SERVER 的 UK 中不允许出现多个空值。 3.2.3 check 约束 ■ 检查约束,可以按照指定条件,检查记录的插入。 check 中不能使用伪列,不能使用函数,不能引用其他字段。 27 例:create table sal ( a1 number , check(a1>1000 and a1<2000) ); ■ not null 只能定义成列级约束,其余的可列级也可表级约束 除了 not null 约束,其余约束无法通过 as 拷贝其它表结构的约束、 (其余部分请参考前两天笔记) 3.4 DML 操作 3.4.1 insert 操作,插入记录 ■ insert into 表名 values(值 1,值 2,......); 注意这种方法插入记录时,要对所有字段进行插入,没有非空约束时,又不想插入 值时,要用空值替代,并且要按照字段的顺序插值(要清楚表结构),且要注意数据类型一 致。 ■ insert into 表名(字段名 1,字段名 2,.....) values(值 1,值 2,......); 这种方法可以对指定的字段进行插入,不想插值的就可以不写,前提是该字段没有 非空约束。 例:insert into student value(1,'xxx','xxx'); insert into student(id,name,address) value(1,'xxx','xxx'); ■ 插入数据,从另一个表中 insert into table_name(column...) select column... from table_name_2 where condition ■ 只要表结构,不要数据的小技巧 create table s_emp_42 as select * from s_emp where 1=2;//永假式,从而导致不拷贝进数据 3.4.2 update 修改操作 update table 表名 set 字段名 1=数据 1 或表达式 1, 字段名 2=数据 2 或表达式 2 [where ....=....]; 28 例:update shenfenzhen set num=99 where sid=2; 3.4.3 delete 删除操作 delete from 表名 [where ...=...]; 例:delete from shenfenzhen where sid=2; 用 delete 操作删除的记录可以通过 rollback 命令回滚操作,会恢复 delete 操作删 除的数据。 delete 操作不会释放表所占用的空间,delete 不是和删除记录多的大表。delete 操 作会占用大量的系统资源。删除大表一般用 trucate table 表名; 3.5 事务 transaction 1、OLTP(联机事务处理 OnLine Transaction Process) 2、原子操作,也就是不可分割的操作,必须一起成功一起失败。 要是实现一个原子操作,就要把这个原子操作(操作数据库数据(DML 操作))放在事务 中。 3、事务的结束动作 就是 commit;语句 rollback;语句,DDL,DCL 语句执行会自动提交 commit;。 sqlplus 正常退出是会做提交动作的 commit;,当系统异常推出是,会执行回滚操作 rollback;。 事务的开始,一个事务的开始就是上一个事务的结束。 一个没有结束的事务,叫做活动的事务 (active transaction),活动的事务中修改的数据, 只有本会话才能看见。 readcommited,只可以读取已经作提交操作的数据,本会话可以看到自己的所作的没有 提交的操作。 4、commit;提交操作,事务的结束 29 rollback;回滚操作,会将先前的活动事务中的操作(DML 操作)的结果进行回滚,撤销 全部操作,恢复成事务开始时的数据,也就是恢复成事务开始时的状态。 5、事务隔离级别: ORACLE 默认是 read committed,读已经提交的数据 语句级读一致性. 6、在活动事务中,当多个用户同时对同一张表进行操作时,会对表加上表级共享锁, 当用户对操作该表某一条记录进行操作时会对该条记录加上行级排它锁,只允许一个用 户对该条记录进行 DML 操作,只有提交操作 commit;或回滚操作 rollback;时,才可让其他用 户操作对该记录进行 DML 操作,也就是释放了该条记录的行级排它锁。 如果没有提交操作或回滚操作,那么该用户就不能对该条记录加锁,该用户的 DML 操 作就会进入等待状态,但是在对表作 drop 操作(DDL 操作)时,如果还有用户在操作该表, 也就是没有释放表级共享锁,就会直接报错。 事务越大,就会消耗更多的资源,并长时间持有事务会造成无法进行其他的操作,事物 提交太频繁的话,会对 I/O 造成很大的负担,所以要合理确定事务的大小。 表级共享锁 行级排它锁 table 表级共享锁 nowait 方式 row 行级排他锁 wait 方式锁的力度越高,并行越低. select 不加锁 select for update 加锁 DML 加锁 DDL 加锁 commit 释放锁. 可以通过杀会话的动作可以解锁. 解锁:alter user hr account unlock; alter user hr identified by hr; select username from dba_users where username='HR'; 注意 做 DML 时,锁不动,肯定有其它事务在做这张表的操作。 3.6 alter table 命令 alter table 命令用于修改表的结构(这些命令不会经常用): 30 增加字段: alter table 表名 add(字段字,字段类型) 删除字段: alter table 表名 drop column 字段; (8i 以后才支持) 给列改名:9.2.0 才支持 alter table 表名 rename column 旧字段名 to 新字段名; 修改字段 alter table 表名 modify( 字段,类型) (此时应注意的问题,更改时要看具体值情况之间的转达换, 改为字符类型时,必须 要为空) not null 约束是使用 alter table .. modify (..,not null),来加上的。 增加约束: alter table 表名 add constraint [约束名] 约束(字段); 只能够增加表级约束。 解除约束:(删除约束) alter table 表名 drop 约束; (对于主键约束可以直接用此方法,因为一张表中只有一个主键约束名, 注意如果主键 此时还有其它表引用时删除主键时会出错) alter table father drop primary key cascade; (如果有子表引用主键时,要用此语法来删除主键,这时子表还存在只是子表中的外键约 束被及联删除了) alter table 表名 drop constraint 约束名; (怎样取一个约束名: a、人为的违反约束规定根据错误信息获取! b、查询视图获取约束名!) 31 使约束失效或者生效 alter table 表名 disable from primary key; (相当于把一个表的主键禁用) alter table 表名 enable primary key; (enable 时会自动去检查表的记录是不是符合要求,如果有脏数据时必须要先删除脏数 据才可以 enable) 一般用于批量导数据的时候;存在自连接的时候。 更改表名 rename 旧表名 to 新表名; 删除表: trucate table 表名; (表结构还在,数据全部删除,释放表所占的空间,不支持回退,常用删除大表) 这个操作完了,回到 create table 的状态。 3.7 序列(sequence) 创建 sequence create sequence 序列名; 不带参数时默认为从 1 开始每次递增 1。 oracle 中为了提高产生序列的效率一般一次性产生 20 个序列放入当前会话的序列池中 备用以加快效率,序列会出现不连续的动作回退操作不会影响序列取值。 sequence 的参数: increment by n 起始值 start with n 递增量 maxvalue n 最大值 minvalue n 最小值 cycle|no cycle 轮回 cache n 缓存(第一次取时会一次取多少个 id 存起来,不用每次去访问序列 表中的记录) 32 查看 sequence desc user_sequences ; select sequence_name , cache_size , last_number from user_sequences where sequence_name like 's_'; select 序列名.currval from dual 查看当前的序列数 select 序列名.nextval from dual 查看下一个序列数,它会自动给当前的序列加1 取当前值不成功时,应该先取下下一个值,再取当前值。 清空当前会话的内存: alter system flush shared_pool; (执行此命令要有 DBA 权限,一般用户执行出错) 修改序列:(此命令不常用,只需了解就行不必深究) alter sequence 序列名 修改项; 删除序列 sequence drop sequence 序列名; 3.8 视图 view 介绍 视图就相当于一条 select 语句,定义了一个视图就是定义了一个 sql 语句,视图不占空间, 使用 view 不会提高性能,但是能简单化 sql 语句 (扩展知识: oracle 8i 以后的新视图) mv 物化视图(占存储空间,把 select 结果存在一个空间,会提高查询视图,增强实时性, 但是存在刷新问题,物化视图中的数据存在延迟问题,主要应用在数据仓库中用要用于聚合 表) 使用视图的好处:控制数据访问权限。 简单视图允许 DML 操作。 复杂视图一般不允许 DML 操作。 创建视图 create or replace views test_vi 33 as select * from test1 where c1=1; or replace 的意义,如果 view 存在就覆盖,不存在才创建。 force|no force ,基表存在是使用,不存在是则创建该表。 此时往表 test1(base table 基表)中插入数据时:表中没能变化,视图中的数据发生改 变 从视图中插数据时相对应的表会发生改变: 往视图中插数据时,会直接插进基表中,查看视图中的数据时,相当于就是执行创建时 的 select 语句。 限制对数据库的访问,简化查询。 简单视图:来自于单表,且 select 语句中不能包括函数,能进行 DML 操作。 复杂视图:来源于多张表,不能执行 DML 操作。 试图的约束 with read only 视图只读约束(O) with check option 不允许插入与 where 条件不符的记录,类似于 check 约束的功能(V) 内嵌视图 在 select from 后也可以使用子查询,这个写法也叫做内嵌视图 例 select first_name,salary,avgsal from s_emp e, (select dept_id,avg(salary) avgsal from s_emp group by dept_id) s where e.dept_id=s.dept_id and e.salary>s.avgsal; 联合视图 create or replace view v_union as select * from temp union all select * from temp1; 可以创建 temp,temp1 两个表的联合的视图 删除视图 drop views 视图名; 34 更新视图 alter view v-test compile 当查询一个视图有错误时,可能是基表已经不存在了。 此时,如果再建上基表之后,必须还要 alter view compile。 因为视图是系统通过编译 sql 语句得到的一个虚拟表,也就是说这个表是基于系统的一 次编译后的 sql 语句而存在的;如果基表改变了,但视图还是基于原来被编译的 sql 语句, 所以我们需要用 alter view v_test compile 来重新编译视图 对视图进行 DML 操作规则 1、如果视图中有如下特性,不要删除记录。 视图中有组函数 视图中有 group by 子句 视图中有 distinct 指令 2、如果视图中有如下特性,不可修改记录 规则 1 中所有特性 视图的字段通过表达式定义的 视图中有 rownum 伪列 3、如果视图中有如下特性,不可添加记录 规则 1 和 2 中所以特性 不能被视图查询出的所有非空字段 行号(rownum) rownum 特点:rownum 要么等于 1 要么小于某个值, 不能直接等于某个值, 不能大于 某个值。 rownum 常用于分页显示。 rownum 只用于读入内存的数据。 3.9 关于同义词: 同义词:相当于别名的作用(***只需了解***)系统自建的同义词: user_tables create synonym asd_s_emp for asd_0606.s_emp ; 目的就是为了给 asd_0606_s_emp 表起另一个代替的名称 asd.s_emp;注意这个同义词只 能自己使用; create public synonym p_s_emp fro asd_0606.s_emp; 创建公共的同义词,但是要权 35 限. 删除同义词: drop synonym 同义词名称 3.10 索引(index) 索引介绍 创建索引:Creating indexes(概念很重要对系统的性能影响非常大) 建索引的目的就是为了加快查询速度。 索引就相于一本的书的目录。索引占系统空间,属于表的附属物。删除一个表时,相对 应的索引也会删除。索引是会进行排序。 truncate 表时索引结构在,但是数据不存在。 可以基于索引的扫描,没有索引只好进行全表扫描了。 full table scan 全表扫描,没有索引时,就会进行全表扫描操作。 用索引就是为了快速定位数据:(理解时就以字典的目录为例) 创建索引就是创建 key 和记录的物理位置(rowid)组成的键值对。索引是有独立的存 储空间,但是和表是逻辑关联的,索引和表的关系是依附关系,表被删除了,索引也没有存在的 意义也就被删除了 注意 1、在建表时会根据表中的 PK 和 UK 自动的建立唯一性索引。 2、select . . . where c1 is null 一定会进行全表扫描,因为索引中不存空值 rowid 查看表的 rowid: select rowid,first_name from s_emp; rowid 定义的信息有:object block table 表示记录的物理位置,每条记录都有自己的 rowid,这样通过 rowid 值可以唯一地标识 数据库中的一行。 索引中包括被索引的字段和这条记录的 ROWID,Oracle 在索引中找到对应的键值后,根 据这个键值对应的 ROWID,就可以找到表中的这条对应的记录。 36 索引创建 建索引后会使 DML 操作效率慢,但是对用户查询会提高效率,这就是我们建索引的最终 目的。 创建一个索引: create index 索引名 on 表名 (字段名); create insex testindex on test(c1, c2); 索引分为唯一性索引,联合索引。 create unique index . . . create index ind_dept on scott.dept(dname,loc); 索引中是不会维护空值的。 长时间 DML 操作后,效率明显不行时,要进行重新建索引。 alter index rebuild 或者删除重新建 二者区别在于:rebuild 速度快,但原先旧的索引还在;后者是重新进行排序,需要一 定时间。 哪些字段应该建索引 创建索引就是为了减少物理读,索引会减少扫描的时间。所查询的数据与所有数据的百 分比,表越大,查询的记录越少,索引的效率就越高。(要注意作比较时,是和全表扫描进 行比较的) 经常出现的地方: 1>经常要用 where 的子句的地方 2>表连接的字段适合建索引,所以 FK 也适合建索引 注意 1、函数会导致索引用不了。 如 upper()函数等,不要用在索引的列上。 2、表达式也会导致索引用不了。 where salary+5=2000 不行,要想效率高,直接减下。 3.隐式数据类型转换,会导致索引用不了。 where c1 = 2; //c1 是字符型,自动转换是将字符转为别的类型。会调用 to_number 函数,会降低效率,不推荐用。 where n1=’2’; //n1 是数字型的,此时会将’2’转为数字 2,索引可以用上。 4、有时,用上索引会慢,想采取全表扫描,可以直接写上 where c1+0=1000 查找索引 系统表有二: user_indexes 37 放着索引名和其唯一性信息。 user_ind_columns 索引名,表名和作用在哪个字段上。 查出 S_EMP 中的索引 SQL> SELECT ic.index_name, ic.column_name, ic.column_position col_pos,ix.uniqueness FROM user_indexes ix, user_ind_columns ic WHERE ic.index_name = ix.index_name AND ic.table_name = 'S_EMP'; 替换变量 用&符号来定义替换变量支持交互性提示,对于字符性的数字,一定要写在单引号之间 set verify on 替换开启 set verify off 替换关闭 定义变量: define p_dname='abc'; 用 define 定义的替换变量的作用范围是整个 sqlplus 更改交互的提示信息: accept p_dname prompt ' 提示信息'; accept 就是可以加入提示信息其他方面和 define 功能相同 相当于开关变量,用于控制是否显示新旧的 sql 语句 例 select id,last_name,salary from s_emp where title='&job_title'; 3.11 数据字典 数据字典是由系统维护的,包含的数据库的信息 ■ 数据字典视图 38 user_XXXXX 用户视图 all_XXXXX 所有视图 dba_XXXXX 数据库中所有视图 v$_XXXXX 动态性能视图 ■ dist 或 distionary 表示数据字典的数据字典。 ■ 查约束 - user_constraints 用户的表中约束的表 constraints_name 字段存放的是约束名, r_constraints_name 字段表示外键引用子何处 这两个字段之间有自连接的关系,也就是约束名和外键约束名之间的自连接。 constraints_type p pk r fk c check 和 notnull 用 SEARCH_CONDITION 来区分 u uk - user_cons_column 表,是用户的列级约束表 column_name 字段存放的是约束字段的名字, position 字段存放的是约束在联合键中的位置. 附 一、各数据库自增列 MySql Oracle SQL Server 建表 语句 id int auto_increment primary key, id number(2) primary key; create sequence derekseq; id int identity primary key, 插值 方式 不用提供字段和值 values( derekseq.nextval ) 不用提供字段和值 39 二、Oracle 相关 创建用户与授权语法 创建用户 create user 名称 identified by 口令 default tablespace " 默 认 表 空 间 名 " temporary tablespace "temp" account unlock default tablespace :默认表空间名 temporary tablespace :临时表空间名,默认 temp account :用户状态,默认 unlock 未锁定;lock 锁定 create user "test" profile "default" identified by "test" default tablespace "test" temporary tablespace "temp" account unlock; 也可写成 create user "test" profile "default" identified by "test" default tablespace "test" ; 用户授权 grant "connect,resource,dba" to "someuser" with admin option; with admin option :管理选项 授予 usertest dba 权限 grant dba to "usertest" with admin option; revoke "resource" from "scott"; 取消授权 实例操作 1、以管理员身份登录 %sqlplus "/ as sysdba" 以 SYSDBA 这个角色登陆 SQLPLUS,SYSDBA 只是个角色,它本身并没有密码。 2、创建用户 SQL> create user xiyangyang identified by xiyangyang; 3、授权 SQL>grant connect,resource,create session,create table to xiyangyang; 4、创建测试表(Oracle9) 40 $ORACLE_HOME/rdbms/demo/summit2.sql $ORACLE_HOME/sqlplus/demo/demobld.sql
还剩39页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 10 金币 [ 分享pdf获得金币 ] 0 人已下载

下载pdf

pdf贡献者

追梦java

贡献于2012-08-15

下载需要 10 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf