ORACLE 数据库
create table student(
name varchar2(20),
age number(3)
);
insert into student values('Tom', 18);
insert into student values('张三', 20);
insert into student values('李四', 22);
insert into student values('王五', 26);
select * from student;
desc student;
drop table student;
delete from student;
delete from student where age=20;
commit;
- Insert(用于添加字段), Update(用于修改已有字段), Delete, Merge
- Create, Alte(用于添加列)r, Drop, Truncate
- Grant, Revoke
- Commit, Rollback, Savepoint
* 语法格式
- SELECT *|{<字段名>, ...}
- FROM <表名>;
* 在 Select 语句中,对 NUMBER 型数据可以使用算术运算符创建表达式.
- select empno, ename, sal, sal*12 from emp;
* 算术运算符( + - * / )
* 运算优先级
- 先乘除后加减
- 同级运算从左到右
- 表达式中可使用小括号强行改变运算顺序
- select empno, ename, sal, sal*12+1000 from emp;
- select empno, ename, sal, sal*(12+1000) from emp;
* 连接运算符'||'可以把列与字符,或其它表达式连接在一起,得到一个新的字符串,实现'合成'列的功能.
* 用法举例:
- select empno, ename || ' is a ' || job from emp;
- select empno, ename || '''s annual salary is ' || sal*12 from emp;
- select '姓名:' || ename || ', 工作: ' || job from emp;
* 字段别名
- 重命名查询结果中的字段,以增强可读性
- 如果别名中使用特殊字符,或者是强制大小写敏感需使用双引号
* 语法格式:
- SELECT <字段名>|<表达式>[[AS]<字段别名>],...
- FROM <表名>;
* 用法举例:
- select empno as 员工编号, ename 员工姓名, sal*12 "年 薪" from emp;
- select empno, ename "Ename", sal*12 "Anual Salary" from emp;
* 什么是空值
- 空值是无效的,未指定的,未知的或不可预知的值
- 空值不等同于空格或者0
* 空值举例:
- select empno, ename, job, sal, comm from emp;
##########[ 在表达式中使用空值 ]##########
* 算术表达式中如果出现空值,则整个表达式结果为空
* 连接表达式中出现的空值被当作一个空的(长度为零的)字符串处理
- select empno, ename, sal, comm, ename || ' - ' || comm, sal+comm from emp;
* 在缺省情况下,查询结果中包含所有符合条件的记录行,名括重复行.
- select deptno from emp;
* 使用 DISTINCT 关键字可林查询结果中清除重复行
- select distinct deptno from emp;
* DISTINCT 的作用范围是后面所有字段的组合
- select distinct deptno, job from emp;
* 查询结果缺省按照记录的插入顺序进行排序
* 也可使用 ORDER BY 子句对查询结果进行排序,排序方式包括升序(ASC, 缺省)和降序(DESC)两种:
- select empno, ename, sal from emp order by sal;
- select empno, ename, sal from emp order by sal desc;
* 按多字段排序
- select deptno, empno, ename, sal from emp order by deptno, sal;
* 使用字段别名排序
- select empno, ename, sal*12 annsal from emp order by annsal;
根据NULL排序
elect deptno, empno, ename, sal from emp order by nulls last;
* 查询所有 deptno=10 的数据
- select * from emp where deptno=10;
* 语法格式
- SELECT *|{[DISTINCT]<字段名>|<表达式>[<别名>],...}
- FROM <表名>
- [WHERE <查询条件>];
* 查询语句中使用字符串和日期
- 字符串和日期值要用单引扩起来
- 字符串大小写敏感
- 日期值格式敏感,缺省的日期格式是'DD-MON-RR'
- select * from emp where ename='SMITH';
- select * from emp where hiredate='02-4月-81';
* 获取当前缺省日期格式
- select sysdate from dual;
* 运算符 含 义
- = 等 于
- > 大 于
- >= 大于等于
- < 小于
- <= 小于等于
- <> 大等于
* 查询所有 sal > 2900 的数据
- select * from emp where sal > 2900;
* 查询所有 deptno <> 20 的数据
- select * from emp where deptno <> 20;
- select * from emp where job <> 'MANAGER';
--------------------------------------------------
* 运算符 含 义
- BETWEEN...AND... 界于两值之间(包括边界,注意:小值在前面)
- IN(set) 出现在集合中
- LIKE 模糊查询
- IS NULL 为空值
* 查询工资(sal) 在1600-2900之间的数据
- select * from emp where sal between 1600 and 3200;
- select * from emp where sal between 1600 and 3200 order by sal;
- select * from emp where sal between 1600 and 3200 order by sal desc;
- select distinct deptno, sal from emp where sal between 1600 and 3200 order by sal;
* 查询姓名(ename)出现在('SMITH', 'CLARK', 'KING', 'TOM')里的数据
- select * from emp where ename in('SMITH', 'CLARK', 'KING', 'TOM');
* 查询姓名(ename)不出现在('SMITH', 'CLARK', 'KING', 'TOM')里的数据
- select * from emp where ename not in('SMITH', 'CLARK', 'KING', 'TOM');
* 使用 LIKE 运算符执行模糊查询(通配查询)
- % 表示零或多个字符
- _表示一个字符
- 对于特殊符号可使用 ESCAPE 标识符来查找
* 查询姓名(ename)是'S'开头的数据
- select * from emp where ename like 'S%';
* 查询姓名第个字是'A'的数据
- select * from emp where ename like '_A%';
* 查询姓名有下划线'_'的数据
- select * from emp where ename like '%\_%' escape '\';
* 使用 IS NULL 运算符进行空值判断
* 查询 comm 为空的数据
- select * from emp where comm is null;
* 查询 comm 不为空的数据
- select * from emp where comm is not null;
* 运算符 含 义
- AND 逻辑"与"
- OR 逻辑"或"
- NOT 逻辑"非"
* 注意:如果三个逻辑运算符同时用上,则优先级:NOT>AND>OR
* 查询部门编号(deptno)等于20并且工资(sal)大于2000的数据
- select * from emp where deptno=20 and sal>2000;
* 查询部门编号(deptno)等于20或者工资(sal)大于2000的数据
- select * from emp where deptno=20 or sal>2000;
* 查询部门编号(deptno)出现在(20, 30, 40)的数据
- select * from emp where deptno in(20, 30, 40);
* 查询部门编号(deptno)不出现在(20, 30, 40)的数据
- select * from emp where deptno not in(20, 30, 40);
* 优先级 运算符
- 1 *, /
- 2 +, -
- 3 ||
- 4 =, >, >=, <, <=, <>
- 5 IS [NOT] NULL, LIKE, [NOT] IN
- 6 [NOT]BETWEEN..AND..
- 7 NOT
- 8 AND
- 9 OR
* 可使用小括号强行改变运算顺序
- select * from emp where job='SALESMAN' or job='CLERK' and sal>=1280;
- select * from emp where (job='SALESMAN' or job='CLERK') and sal>=1280;
* 数据类型 说明
- char 字符型,最大长度2000B,缺省长度为1B
- nchar 基于NLS国家字符集的字符型,最大长度2000B,缺省为1字符
- varchar2…………变长字符型,最大长度4000B
- nvarchar2 基于NLS国家字符集的字符型,其余同varchar2
- varchar 同varchar2
- number(m, n)……数值型,m为总位数,n为小数位数,总长度最大为38位
- date………………日期型,有效表数范围:公元前4712年1月1到公元后4712年12月31日
- long 变长字符型,最大长度2GB,不支持对字符串内容进行搜索
- raw 变长二进制数据类型,最大长度2000B
- long raw 变长二进制数据类型,最大长度2GB
- blob………………二进制大对象类型,最大长度4GB
- clob………………字符大对象类型,最大长度4GB
- nclob 基于NLS国家字符集的字符大对象类型,最大长度4GB
- bfile 在数据库外部保存的大型二进制文件大对象类型,最大长度4GB
* 测试1(char)
* 注意:位单为字节(不够指定长度也算指定长度空间)
- create table t1(name char(10),sex char(1));
- insert into t1 values('tom', 'm');(Y)
- insert into t1 values('tom', '男');(N)
- insert into t1 values('一二三四五', 'f');(Y)
- insert into t1 values('一二三四五六', 'f');(N)
* 测试2(nchar)
* 注意:位单为字符
- create table t2(name nchar(10), sex nchar(1));
- insert into t2 values('tom', '男');(Y)
- insert into t3 values('一二三四五六', 'f');(Y)
- insert into t2 values('一二三四五六七八九十', '男');(Y)
- insert into t2 values('一二三四五六七八九十一', '男');(N)
- insert into t2 values('一二三四五六七八九十', '男性');(N)
* 测试3(varchar2)(2000个中文,4000个英文)
* 注意:位单为字节(长度为数据的长度,超过长度报错)
- create table t3(name varchar2(10), sex varchar(2));
- insert into t3 values('一二三四五', '男');(Y)
- insert into t3 values('一二三四五六', '男');(N)
- insert into t3 values('一二三四五', '男性');(N)
- insert into t3 values('abcdefghij', 'aa');(Y)
- insert into t3 values('abcdefghijk', 'aa');(N)
- insert into t3 values('abcdefghij', 'aaa');(N)
- insert into t3 values('abcdefghij', 'a');(N)
- insert into t3 values('ABCDEFGHIJ', 'AA');(Y)
* 测试4(number)
* 注意:小数只保留指定位数
- create table t4(name varchar2(10), sal number(7, 2));
- insert into t4 values('AAA', 2.6);(Y)
- insert into t4 values('AAA', 11111.66);(Y)
- insert into t4 values('AAA', 123456.12);(N)
- insert into t4 values('AAA', 12456.123456);(Y)
* 测试5(date)
- create table t5(name varchar2(10), birth date);
- insert into t5 values('BBB', sysdate);(Y)
- insert into t5 values('BBB', '03-8月 -09');(Y)
* Oracle 函数分为单行函数和多行函数两大类
* 单行函数
- 操作数据项
- 接受参数并返回处理结果
- 对每一返回行起作用
- 可修改数据类型
- 可嵌套使用
* 单行函数分类
- 字符函数
- 数值函数
- 日期函数
- 转换函数
- 通用函数
* 字符大小写转换函数
* 函数 功能 用法 返回结果
- lower() 转换为小写 lower('John Smith') john smith
- upper() 转换为大写 upper('John Smith') JOHN SMITH
- initcap() 单词首字母大写 initcap('JOHN smith') John Smith
* 例:
- select lower('John Smith') from dual;->(john smith)
- select upper('John Smith') from dual;->(JOHN SMITH)
- select initcap('JOHN smith') from dual;->(John Smith)
*字符处理函数
* 函数 功能 用法 返回结果
- concat() 字符串连接 concat('Hello', 'World') Hello World
- substr() 截取子串 substr('HelloWorld', 4, 3) loW
- length() 返回字符串长度 length('Hello World') 11
- instr() 定位子串 instr('Hello World', 'or') 8
- lpad() 左侧填充 lpad('Smith', 10, '*') *****Smith
- rpad() 右侧填充 rpad('Smith', 10, '*') Smith*****
- trim() 过滤首尾空格 trim(' Mr Smith ') Mr Smith
- replace() 替换 replace('ABA', 'A', 'C') CBC
* 注意:函数可嵌套使用
* 例:
- select concat('Hello', 'World') from dual;->(HelloWorld)
- select concat(concat(ename, ' is a '), job) info from emp where empno=7369;->(SMITH is a CLERK)
- select substr('HelloWorld', 4, 3) from dual;->(loW)
- select substr(substr('HelloWorld', 3, 6), 3, 3) from dual->(oWo)
- select length('Hello World') from dual;->(11)
- select instr('Hello World', 'or') from dual;->(8)
- select lpad('Smith', 10, '*') from dual;->(*****Smith)
- select rpad('Smith', 10, '*') from dual;->(Smith*****)
- select trim(' Mr Smith ') from dual;->(Mr Smith)
- select replace('ABA', 'A', 'C') from dual;->(CBC)
* 函数 功能 用法 返回结果
- abs() 取绝对值 abs(-3.14) 3.14
- round() 四舍五入 round(3.1415) 3
round(3.1415, 3) 3.142
round(314.1592, -2) 300
- trunc() 截断 trunc(3.1415, 3) 3.141
- ceil() 向上取整 ceil(3.14) 4
- floor() 向下取整 floor(3.14) 3
- sign() 判断数值正负 sign(-3.14) -1
- sin().. 三角函数.. sin(3.14) .001592653
- power() 幂运算 power(4.5, 2) 20.25
- sqrt() 开平方根 sqrt(9) 3
- mod() 取模 mod(10, 3) 1
- exp() 基数为e的幂运算 exp(1) 2.71828183
- log() 对数运算 log(4, 16.0) 2
- ln() 自然对数运算 ln(7) 1.94591015
* 例:
- select abs(-3.14) from dual;->(3.14)
- select round(3.1415) from dual;->(3)
- select round(3.1415, 3) from dual;->(3.142)
- select round(314.1592, -2) from dual;->(300)
- select trunc(3.1415, 3) from dual;->(3.141)
- select trunc(3.1415, -3) from dual;->(0)
- select trunc(3.1415, 7) from dual;->(3.1415)
- select ceil(3.14) from dual;->(4)
- select floor(3.14) from dual;->(3)
- select sign(-3.14) from dual;->(-1)
- select sin(3.14) from dual;->(.001592653)
- select power(4.5, 2) from dual;->(20.25)
- select sqrt(9) from dual;->(3)
- select mod(10, 3) from dual;->(1)
- select exp(1) from dual;->(2.71828183)
- select log(4, 16.0) from dual;->(2)
- select ln(7) from dual;->(1.94591015)
* 关于日期类型
- Oracle内部以数字格式存储日期和时间信息:世纪,年,月,日,小时,分钟,秒
- 缺省的日期格式是DD-MON-YY
- 可使用sysdate函数获取当前系统日期和时间
* 日期型数据的算术运算
- 日期型数据可以直接加或减一个数值,结果仍为日期
- 两个日期型数据可以相减,结果为二者相差多少天
* 查询200-12-25减1991-12-25一共有多少天
- select to_date('25-12月 -09') - to_date('25-12月 -1991') from dual;
* 函数 功能 用法 返回结果
- add_months(x, y) 计算在日期x基础上增加y个月后的日期 add_months(sysdate, 2)
- last_day(x) 返回日期x当月最后一天的日期 last_day(sysdate)
- months_between(x, y) 返回日期x和y之间相差的月数 months_between(sysdate, hiredate)
- round(x, y) 将日期x四舍五入到y所指定的 round(sysdate, 'month')
日期单位(月或年)的第一天 round(sysdate, 'year')
- trunc(x, y) 将日期x截断到y所指定的 trunc(sysdate, 'month')
日期单位(月或年)的第一天 trunc(sysdate, 'year')
- next_day 计算指定日期x后的第一个星期几 next_day(sysdate, '星期二')
(由参数y指定)对应的日期
* 例:
- select add_months(sysdate, 2) from dual;->(05-10月-09)
- select last_day(sysdate) from dual;->(31-8月 -09)
- select hiredate, months_between(sysdate, hiredate) from emp;
- select months_between(sysdate, '17-12月-80') from dual;->(343.63907)
- select round(sysdate, 'month') from dual;->(01-8月 -09)
- select round(to_date('16-8月 -09'), 'month') from dual;->(01-9月 -09)
- select round(sysdate, 'year') from dual;->(01-1月 -10)
- select round(to_date('1-7月 -09'), 'year') from dual;->(01-1月 -10)
- select round(to_date('25-6月 -09'), 'year') from dual;->(01-9月 -09)
- select trunc(sysdate, 'month') from dual;->(01-8月 -09)
- select trunc(sysdate, 'year') from dual;->(01-1月 -09)
- select next_day(sysdate, '星期二') from dual;->(11-8月 -09)
- select next_day(next_day(sysdate, '星期二'), '星期二') from dual;->(18-8月 -09)
* 数据类型转换包括隐含转换和显式转换两方式,建议使用显式的数据类型转换,确保SQL语句的可靠性
* 字符类型 -> 数值类型 -> to_number()
* 字符类型 -> 日期类型 -> to_date()
* 数值类型 -> 字符类型 -> to_char()
* 日期类型 -> 字符类型 -> to_char()
* to_char()函数可以将日期型数值转换为字符串形式
* 格式:
- to_char(date) // 缺省转换为'dd-mm-yy'格式
- to_char(date, 'format_model') // 转换为模式串指定的格式
* 例:
- select empno, ename, sal, to_char(hiredate, 'yyyy-mm-dd') from emp;
- select to_char(sysdate, 'yyyy-mm-dd hh:mi:ss') from dual;
- select to_char(sysdate, 'yyyy-mm-dd hh24:mi:ss') from dual;
* 格式符 说明 举列
- yyyy 年份 2008
- mm 用数字显示月份 02
- dd 在当月中是第几天 28
- day 星期几 星期五
- am/pm 显示上午/下午 上午
- hh/hh12/hh24 小时 2:30 14:30
- mi 分钟 30
- ss 秒钟 46
* 说明:除上述格式符外,日期模式串中还可直接出现如下字符( - : ; / );
* 如要显示其它文本字符串则需使用双引号括起来;也可在械串的开头使用"fm"标
* 记以去掉数字前面的零
* 例:
- select to_char(sysdate, 'yyyy"年"mm"月"dd"日" day hh24:mi:ss') from dual;
- select to_char(sysdate, 'fmyyyy"年"mm"月"dd"日" day hh24:mi:ss') from dual;
* to_date()函数可以将字符串转换为日期型数值形式
* 格式:
- to_date(char) // 按缺省格式'dd-mm-yy'进行解析
- to_date(char, 'format_model') // 按模式串指定的格式进行解析
* 例:
- insert into t5 values('BOBO', to_date('2008-02-28', 'yyyy-mm-dd'));
- select to_date(to_char(sysdate, 'yyyy-mm-dd hh24:mi:ss'), 'yyyy-mm-dd hh24:mi:ss') from dual;
- select to_char(to_date(to_char(sysdate, 'yyyy-mm-dd hh24:mi:ss'), 'yyyy-mm-dd hh24:mi:ss'), 'dd/mm/yyyy') from dual;
* to_char()函数可以将数字值转换为字符串形式
* 格式:
- to_char(number)
- to_char(number, 'format_model')
* 例:
- select to_char(12345.678901) from dual;
- select to_char(12345.678901, '$99,999.0000') from dual;
* 数字模式符:
* 格式符 说 明
- 9 代表一位数字
- 0 代表一位数字,强制显示0
- $ 放置一个美圆符$
- L 放置一个本地货币符
- . 小数点
- , 千位指示符
* 例:
- select to_char(12345.6, 'L999,999.0000') from dual;
* to_number()函数可以将字符串转换为数字值形式
* 格式:
- to_number(char)
- to_number(char, 'format_model')
* 例:
- select to_number('12345.678901') from dual;
- select to_number('$12,345.6789', '$99,999.0000') from dual;
* 通用函数适用于任何类型数据(包括空值):
- nvl()
- nvl2()
- nullif()
- coalesce()
- case表达式
- decode()
* NVL()函数用于将空值null替换为指定的缺省值,适用于字符,数字,日期等类型数据
* 语法格式:
- NVL(exp1, exp2)
* 说明:
- 如果表达式exp1的值为null,则返回exp2的值,否则返回exp1的值
* 用法举例:
- select empno, ename, sal, comm, sal+nvl(comm, 0) from emp;
- select empno, ename, hiredate, nvl(hiredate, sysdate) from emp;
- select empno, ename, job, nvl(job, 'NO job yet') from emp;
* NVL2()函数用于实现条件表达式功能
* 语法格式:
- NVL2(exp1, exp2, exp3)
* 说明:
- 如果表达式exp1的值不为null,则返回exp2的值,否则返回exp3的值
* 用法举例:
- select empno, ename, sal, comm, nvl2(comm, sal+comm, sal) from emp;
* NULLIF()函数用于数据等价性比较并根据比较结果返回null或其中一个被比较的数值
* 语法格式:
- NULLIF(exp1, exp2)
* 说明:
- 如果表达式exp1与exp2的值相等返回null,否则返回exp1的值
* 用法举例:
- select name 原名, nullif(pen_name, name) 化名 from author;
* COALESCE()函数用于实现数据"接合"功能
* 语法格式:
- COALESCE(exp1, exp2, ...)
* 说明:
- 依次考察各参数表达式,遇到非null值即停止并返回该值
* 用法举例:
- select empno, ename, sal, comm, coalesce(sal+comm, sal, 0) 总收入 from emp;
* CASE()表达式用于实现多路分支结构
* 语法格式:
- CASE exp1 when comparison_exp1 then return_exp1
- [when comparison_exp2 then return_exp2
- when comparison_expn then return_expn
- else esle_exp]
- end [TempName]
* 说明:
- 如果 exp1 是 comparison_exp1 的时候,就返回 return_exp1
- [ comparison_exp2 的时候,就返回 return_exp2
- comparison_expn 的时候,就返回 return_expn
- else 就返回 esle_exp ]
- end [别名]
* 用法举例:
- select empno, ename, sal,
- case deptno when 10 then '财务部'
- when 20 then '研发部'
- when 30 then '销售部'
- else '未知部门'
- end 部门
- from emp;
* 和CASE()表达式类似,DECODE()函数也用于实现多路分支结构
* 语法格式:
- decode(col|expression, search1, result1
- [, search2, result2, ...,]
- [, default])
* 说明:
- 如果 col|expression 是 search1 的时候,就返回 result1
- [ search2 的时候,就返回 result2, ...]
- [, default])
- [别名]
* 用法举例:
- select empno, ename, sal,
- decode(deptno, 10, '财务部',
- 20, '研发部',
- 30, '销售部',
- '未知部门')
- 部门
- from emp;
* 单行孙数可以嵌套使用, 嵌套层次无限制
* 嵌套函数的执行顺序是由内到外
- select empno, lpad(initcap(trim(ename)), 10, '*') name, job, sal from emp;
##########[ 单行函数小结 ]##########
* 使用系统提供的单行函数可实现如下功能:
- 对数据进行计算
- 控制数据的输出格式
- 设置/改变日期的显示格式
- 进行数据类型转换
- 使用NVL函数处理空值
- 实现IF-THEN-ELSE多路分支逻辑
* 分组函数对一组数据进行运算,针对一组数据(多行记录)只返回一个结果,也称多行函数
* 常用分组函数
- 函数 功能说明 适用类型
- avg() 计算平均值 数值型
- count() 返回查询所行到的记录行数 任何类型数据
- max() 计算最大值 任何类型数据
- min() 计算最小值 任何类型数据
- sun() 求和 数值型
* 举例:
- select avg(sal), max(sal), min(sal), sum(sal) from emp;
- select max(hiredate), min(hiredate) from emp;
* count(*) 返回组中总记录数目
* count(exp) 返回表达式exp值非空的记录数目
* count(distinct(exp)) 返回表达式exp值不重复的, 非空的记录数目
* 举例:
- select count(*) from emp;
- select count(comm) from emp;
- select count(distinct(deptno)) from emp;
* 分组函数省略列中的空值
- select avg(comm) from emp;
- select sum(comm) from emp;
* 可使用NVL()函数强制分组函数处理空值
- select avg(nvl(comm, 0)) from emp;
* GROUP BY 子句将表中数据分成若干小组
* 语法格式
- select column, group_function(column)
- from table
- [where condition]
- [group by group_by_expression]
- [order by column]
* 例:
- select deptno, avg(sal) from emp group by deptno;
- select deptno, avg(sal) from emp where deptno > 10 group by deptno;
- select deptno, avg(sal) from emp group by deptno order by deptno desc;
* 说明:
- 出现在SELECT列表中的字段,如果不是包含在组函数中,那么该字段必须同时在 GROUP BY 子句中出现
- 包含在 GROUP BY 子句中的字段则不必须出现在 SELECT 列表中
- 可使用 where 子句限定查询条件
- 可使用 order by 子句指定排序方式
* 注意:
- 执行顺序: where -> group by -> select ... from ... -> order by..
##########[ 基于多字段分组 ]##########
- select deptno, job, avg(sal) from emp group by deptno, job;
##########[ 组函数的错误用法 ]##########
* 如果没有 GROUP BY 子句, SELECT 列表中不允许出现字段(单行函数)与分组函数混用的情况
- select empno, sal from emp; -> (Y)
- select avg(sal) from emp; -> (Y)
- select empno, initcap(ename), avg(sal) from emp; -> (N)
* 不允许在 WHERE 子句中使用分组函数
- select deptno, avg(sal)
- from emp
- where avg(sal) > 2000; -> (N)
- group by deptno;
- 注:这跟子句运行顺序有关,
- where 最先执行,
- 在执行 where 子句时,
- 还没有执行 group by 子句,
- 还不知道什么分组,
- 也没计算过 avg(sal) 组内的平均工资
* HAVING 子句用于过滤分组
* 语法格式
- select column, group_function(column)
- from table
- [where condition]
- [group by group_by_expression]
- [order by column];
* 例:
- select deptno, job, avg(sal)
- from emp
- where hiredate >= to_date('1981-05-01', 'yyyy-mm-dd')
- group by deptno, job
- having avg(sal) > 1200
- order by deptno, job;
##########[ 分组函数嵌套 ]##########
* 分组函数最多可嵌套两层
- select max(avg(sal))
- from emp
- group by deptno;
* SQL/Oracle 使用表连接从多个表中查询数据
* 语法格式:
- select 字段列表
- from table1, table2
- where table1.column1 = table2.column2
* 说明:
- 在 where 子句中指定连接条件
- 当被连接的多个表中存在同名字段时,必须在该字段前加上"表名."作为前缀
* 例:
- select empno, ename, job, emp.deptno, dname
- from emp, dept
- where emp.deptno = dept.deptno;
* 提示:加上前缀可以提高效率
##########[ 连接的类型 ]##########
* Oracle8i之前的表连接
- 等值连接(Equijoin)
- 非等值连接(Non-Equijoin)
- 外连接(Outer join)
- 左外连接
- 右外连接
- 自连接(Selfjoin)
* Oracle9i新引入的连接形式(支持SQL99规范):
- 交叉连接(Cross join)
- 自然连接(Natural join)
- 使用 Using 子句建立连接
- 使用 On 子句建立连接
- 外连接(Outer join)
- 左外连接
- 右外连接
- 全外连接
##########[ 多表连接 ]##########
* 多表连接中:
- 可使用 AND 操作符增加查询条件
- 使用表别名可以简化查询
- 使用表名(表别名)前缀可提高查询效率
- 为了连接 n 个表, 至少需要 n-1 个连接条件
##########[ 等值连接(Equijion) ]##########
* 什么是等值连接
- select empno, ename, sal, emp.deptno, dname
- from emp, dept
- where emp.deptno = dept.deptno;
##########[ 非等值连接(Not-Equijion) ]##########
* 问题:如何查得每个员工的工资等级
* 方法1:
- select empno, ename, sal, grade, losal, hisal
- from emp, salgrade
- where sal >= losal and sal <= hisal;
* 方法2:
- select empno, ename, sal, grade, losal, hisal
- from emp, salgrade
- where sal between losal and hisal;
##########[ 外连接(Outer jion) ]##########
* 使用外连接可以看到参与连接的某一方不满足连接条件的记录
* 外连接运算符为(+)
* 传统的外连接分为左外连接和右外边接两种
* 语法格式:
- select 字段列表
- from table1, table2
- where table1.column1(+)=table2.column2;
- select 字段列表
- from table1, table2
- where table1.column1=table2.column2(+);
* 例:
* 左外连接'(+)'放在右边,将左表中不符合条件的也显示出来
- select EMPLOYEE_ID, FIRST_NAME, SALARY, e.DEPARTMENT_ID, DEPARTMENT_NAME
- from employees e, departments d
- where e.DEPARTMENT_ID = d.DEPARTMENT_ID(+)
- order by EMPLOYEE_ID;
* 右外连接'(+)'放在左边,将右表中不符合条件的也显示出来
- select EMPLOYEE_ID, FIRST_NAME, SALARY, e.DEPARTMENT_ID, DEPARTMENT_NAME
- from employees e, departments d
- where e.DEPARTMENT_ID(+) = d.DEPARTMENT_ID
- order by EMPLOYEE_ID;
##########[ 自连接(Self jion) ]##########
* 问题:如何查得每个员工及其上司的工号和姓名
- select a.empno, a.ename, a.mgr, b.ename
- from emp a, emp b
- where a.mgr = b.empno
- order by a.empno;
##########[ SQL99 连接语法 ]##########
* SQL1999 规范中规定的连接查询语法
- select 字段列表
- from table1
- [cross join table2] |
- [natural join table2] |
- [join table2 using(字段名)] |
- [join table2 on(table.column_name = table2.column_name)] |
- [(left | right | full outer) join table2
- on(table1.column_name = table2.column_name)];
##########[ 交叉连接(Cross join) ]##########
* Cross join产生了一个笛卡尔集,其效果等同于在两个表进行连接时未使用 WHERE 子句阴定连接条件
* 举例:
- select empno, ename, sal, emp.deptno, dname
- from emp cross join dept;
##########[ 自然连接(Natural join) ]##########
* Natural join 基于两个表中的全部同名列建立连接
- 从两个表中选出同名列的值均对应相等的所有行
- 如果两个表中同名列的数据类型不同,则出错
- 不允许在参照列上使用表名或者别名作为前缀
* 举例:
- select empno, ename, sal, deptno, dname
- from emp natural join dept;
- 上面SQL语句等同于:
- select empno, ename, sal, emp.deptno, dname
- from emp, dept
- where emp.deptno = dept.deptno;
* 注意:第一种方法的deptno不能加上表名前缀,第二种方法必须加上表名前缀
* 如果不希望参照被连接表的所有同名列进行等值连接,自然连接将无法满足
* 要求,可以在连接时使用Using子句来设置用于等值连接的列(参照列)名.
* 举例:
- select empno, ename, sal, deptno, dname
- from emp join dept
- using(deptno);
* 不允许在参照列上使用表名或者别名作为前缀
* 如果要参照非同名的列进行等值连接,或想设置任意的连接条件,可以使用 ON 子句
* 举例:
- select empno, ename, sal, emp.deptno, dname
- from emp join dept
- on(emp.deptno = dept.deptno);
* 必须加上表名前缀(emp.deptno)
- 上面SQL语句等同于:
- select empno, ename, sal, emp.deptno, dname
- from emp, dept
- where emp.deptno = dept.deptno;
--------------------------------------------------
- select empno, ename, sal, emp.deptno, dname
- from emp join dept
- on(emp.deptno = dept.deptno and sal > 2500);
- 上面SQL语句等同于:
- select empno, ename, sal, emp.deptno, dname
- from emp, dept
- where emp.deptno = dept.deptno and sal > 2500;
* 使用SQL99连接语法,两个以上的表进行连接时应依次/分别指定相临的两个表之间的连接条件
* 语法格式:
- select 字段列表
- from table1
- [cross join table2] |
- [natural join table2] |
- [join table2 using(字段名)] |
- [join table2 on(table1.column_name=table2.column_name)] |
- [(left | right | full outer) join table2
- on(table1.column_name=table2.column_name)]
- [cross join table3] |
- [natural join table3] |
- [join table3 using(字段名)] |
- [join table3 on(table2.colimn_name=table3.column_name)] |
- [(left | right | full outer) join table3
- on(table2.column_name=table3.column_name)];
* 举例:
- SELECT EMPLOYEE_ID, FIRST_NAME, SALARY, DEPARTMENT_ID, DEPARTMENT_NAME, LOCATION_ID, CITY
- FROM EMPLOYEES JOIN DEPARTMENTS USING(DEPARTMENT_ID) NATURAL JOIN LOCATIONS;
- 上面SQL语句等同于:
- SELECT EMPLOYEE_ID, FIRST_NAME, SALARY, DEPARTMENT_ID, DEPARTMENT_NAME, LOCATION_ID, CITY
- FROM EMPLOYEES JOIN DEPARTMENTS USING(DEPARTMENT_ID) JOIN LOCATIONS USING(LOCATION_ID);
- 等同于:
- SELECT EMPLOYEE_ID, FIRST_NAME, SALARY, emp.DEPARTMENT_ID, DEPARTMENT_NAME, LOCATION_ID, CITY
- FROM EMPLOYEES emp JOIN DEPARTMENTS dep ON(emp.DEPARTMENT_ID = dep.DEPARTMENT_ID)
- JOIN LOCATIONS loc USING(LOCATION_ID);
- 等同于:
- SELECT EMPLOYEE_ID, FIRST_NAME, SALARY, emp.DEPARTMENT_ID, DEPARTMENT_NAME, dep.LOCATION_ID, CITY
- FROM EMPLOYEES emp JOIN DEPARTMENTS dep ON(emp.DEPARTMENT_ID = dep.DEPARTMENT_ID)
- JOIN LOCATIONS loc ON(dep.LOCATION_ID = loc.LOCATION_ID);
* 内连接(Inner Join)
- 在 SQL99 规范中,内连接只返回满足连接条件的数据
* 外连接(Outer Join)
- 左外联接(Left Outer Join)
- 两个表在连接过程中除返回满足连接条件的行以外,还返回左表中不满足条件的行,这种连接称为左外联接
- 右外联接(Right Outer Join)
- 两个表在连接过程中除返回满足连接条件的行以外,还返回右表中不满足条件的行,这种连接称为右外联接
- 满外联接(Full Outer Join)
- Oracle9i 开始新增功能,两个表在连接过程中除返回满足连接条件的行以外,还返回两个表中不满足条件的所有行,这种连接称为满外联接
* 举例:
* 不满足条件的不返回(内连接(Inner Join))
- SELECT EMPLOYEE_ID, LAST_NAME, SALARY, DEPARTMENT_ID, DEPARTMENT_NAME
- FROM EMPLOYEES JOIN DEPARTMENTS USING(DEPARTMENT_ID);
* 左表中不满足条件也返回(左外联接(Left Outer Join))
- SELECT EMPLOYEE_ID, LAST_NAME, SALARY, DEPARTMENT_ID, DEPARTMENT_NAME
- FROM EMPLOYEES LEFT JOIN DEPARTMENTS USING(DEPARTMENT_ID);
* 右表中不满足条件也返回(右外联接(Right Outer Join))
- SELECT EMPLOYEE_ID, LAST_NAME, SALARY, DEPARTMENT_ID, DEPARTMENT_NAME
- FROM EMPLOYEES RIGHT JOIN DEPARTMENTS USING(DEPARTMENT_ID);
* 将满足条件的和左表中不满足条件的还有右表中不满足条件的,都返回(满外联接(Full Outer Join))
- SELECT EMPLOYEE_ID, LAST_NAME, SALARY, DEPARTMENT_ID, DEPARTMENT_NAME
- FROM EMPLOYEES FULL OUTER JOIN DEPARTMENTS USING(DEPARTMENT_ID);
* 问题引入
- 如何查得所有比'张三'工资高的员工的信息
* 子查询
- 子查询在主查询前执行一次
- 主查询使用子查询的结果
- 语法格式:
- select 字段列表
- from table
- where 表达式 operator(select 字段列表 from table);
* 举例:
- select * from emp where sal > (select sal from emp where empno = 7654);
##########[ 使用子查询注意事项 ]##########
* 在查询是基于未知值时应考虑使用子查询
* 子查询必须包含在括号内
* 建议将子查询放在比较运算符的右侧,以增强可读性
* 除非进行 Top-N 分析,否则不要在子查询中使用 ORDER BY 子句
* 对单行子查询使用单行运算符
* 对多行子查询使用多行运算符
##########[ 单行子查询 ]##########
* 单行子查询只返回一行记录
* 对单行子查询可使用单行记录比较运算符
- 运算符 含义
- = 等于
- > 大于
- >= 大于等于
- < 小于
- <= 小于等于
- <> 不等于
* 举例:
- select * from emp
- where sal > (select sal from emp where empno = 7566);
##########[ 子查询空值/多值问题 ]##########
* 如果子查询未返回任何行,则主查询也不会返回任何结果
- select * from emp
- where sal > (select sal from emp where empno = 8888);
* 如果子查询返回单行结果,则为单行子查询,可以在主查询中对其使用相应的单行记录比较运算符
- select * from emp
- where sal > (select sal from emp where empno = 7566);
* 如果子查询返回多行结果,则为多行子查询,此时不允许对其使用单行记录比较运算符
- select * from emp
- where sal > (select avg(sal) from emp group by deptno); -> (N)
- SELECT EMPLOYEE_ID, LAST_NAME, SALARY FROM EMPLOYEES
- WHERE JOB_ID = (SELECT JOB_ID FROM EMPLOYEES WHERE LAST_NAME = 'Grant'); -> (Y)
##########[ 多行子查询 ]##########
* 多行子查询返回多行记录
* 对多行子查询只能使用多行记录比较运算符
* 运算符 含义
- IN 等于列表中的任何一个
- ANY 和子查询返回的任意一个值比较
- ALL 和子查询返回的所有值比较
* 举例:
- select * from emp where sal > any(select avg(sal) from emp group by deptno);
- select * from emp where sal > all(select avg(sal) from emp group by deptno);
- select * from emp where job in(select job from emp where ename = 'MARTIN' or ename = 'SMITH');
##########[ TopN查询 ]##########
* 在 ORACLE 中通常用子查询的方式来实现 TOP N 查询
* 语法格式:
- select 字段列表
- from (select 字段列表 from table order by 排序字段)
- where rownum <= n;
* 例:
- select * from (select * from emp order by sal desc) where rownum <= 5;
- select * from (select rownum myno, a.* from (select * from emp order by sal desc) a)
- where myno >= 5 and myno <= 10;
* 数据操作语言 DML (Data Manipulation Language) 用于操作数据库中的数据,包括:
- 插入新数据
- 修改已有的数据
- 删除不再需要的数据
- 数据合并
##########[ insert 语句 ]##########
* insert 语句用于向表中插入数据
* 语法:
- insert into table [(column[, column ...])]
- values (value[, value ...]);
* 举例:
- insert into dept values(88, '装备部', '北京');
- insert into dept(deptno, dname) values(99, '交通部');
* 说明:
- insert 语句每次只能向表中插入一条记录
- 缺省字段名列表时, 应为新插入记录中的每个字段设定新值
- 也可在 insert 语句中指定赋值字段列表, 中为部分字段显式设定新值, 其余字段将被缺省赋值为 null
##########[ 表间数据拷贝 ]##########
* 可以在 insert 语句中使用子查询, 实现表间数据拷贝:
- insert into dept1(id, name) select deptno, dname from dept;
* 说明:
- 此时不必再给出 values 子句
- 子查询中的值列表应与 insert 子句中的字段列表相对应
##########[ update 语句 ]##########
* update 语句用于更新表中数据
* 语法:
- update table
- set column = value [, column = value, ...
- [where condition];
* 举例:
- update emp set sal = sal + 88;
- update emp set sal = sal + 1000, comm = comm + 0.5 where empno = 7778;
- update dept1 set loc = nvl(loc, '未知');
* 说明:
- update 语句每次可更新多条记录
- 可使用 where 子句限定要更新的记录, 如果缺省 where 子句, 则更新表中的所有记录
##########[ delete 语句 ]##########
* delete 语句用于从表中删除数据
* 语法:
- delete [ from ] table
- [ where condition ];
* 举例:
- delete emp;
- delete from emp;
- depete emp where empno = 7788;
* 说明:
- delete 语句每次可删除多条记录
- 可使用 where 子句限定要删除的记录, 如果缺省 where 子句, 则删除表中的所有记录
##########[ merge 语句 ]##########
* merge 语句用于进行数所合并--根据条件在表中执行数据的修改或插入操作,如果要插入的记录在目标表中已
* 经存在,则执行更新操作,否则执行插入操作
* 语法
- merge into table [alias]
- using (table | view | sub_query) [alias]
- on(join_condition)
- when matched then
- update set col1 = col1_val, col2 = col2_val
- when not matched then
- insert(cloumn_list) values (cloumn_values);
* 举例:
- create table test1(eid number(10), name varchar2(20), birth date, salary number(8, 2));
- insert into test1 values(1001, '张三', sysdate, 2300);
- insert into test1 values(1002, '李四', sysdate, 6600);
- insert into test1 values(1003, '王五', sysdate, 5100);
- select * from test1;
- create table test2(eid number(10), name varchar2(20), birth date, salary number(8, 2));
- select * from test2;
- merge into test2
- using test1
- on(test.eid = test2.eid)
- when matched then
- update set name = test1.name, birth = test1.birth, salary = test1.salary
- when not matched then
- insert (eid, name, birth, salary) values(test1.eid, test1.name, test1.birth, test1.salary);
- select * from test2;
##########[ 事务控制 ]##########
* 事务(Transaction)
- 组成单个逻辑工作单元的一系列操作被称为事务
* 数据库事务组成
- 0 - 多条DML语句
- 1条DDL(Data Define Language) 语句
- 1条DCL(Data Control Language) 语句
* 事务控制
- 通过将一组相关操作组合为一个要么全部成功,要么全部失败的逻辑工作单元,以简
- 化错误恢复,提高应用程序的可靠性
* 事务必须满足 ACID 属性
- 原子性(Atomicity)
- 一致性(Consistency)
- 隔离性(Isolation)
- 持久性(Durability)
##########[ 事务的开始和结束 ]##########
* 事务开始于第一条可执行语句
* 事务结束:
- 遇到 commit 或 rollback 语句
- 遇到 DDL 或 DCL 语句
- 用户会话结束
- 系统崩溃
* 事务的提交和回滚
- 显式的提交和回滚操作是为了更好地保证数据的一致性
- 下述情况下事务会被自动提交
- 执行一个 DDL 语句
- 执行一个 DCL 语句
- 正常结束会话
- 会话异常终止/系统崩溃时事务会被自动回滚
##########[ Sql Plus 的自动提交 ]##########
* Sql Plus 中执行 SQL 语句时可以设置是否自动提交,缺省设置为非自动提交
* 查看设置:
- show autocommit;
- autocommit OFF
- autocommit IMMEDIATE
* 改变设置
- set autocommit on;
- set autocommit off;
##########[ 提交/回滚前数据状态 ]##########
* 当事务中数据状态的改变是可以恢复的
* 当前事务中的 DML 操作结果只对当前用户(会话)可见,其它用户(会话)看不到当前事务中数据状态的改变,直到当前事务结束
* 当前事务中 DML 语句所涉及到的行被锁定,其他用户(会话)不能对其进行修改操作
* 举例:
- 会话窗口1:
- set autocommit off;
- update dept set loc = 'China' where deptno = 55;
- 会话窗口2:
- update dept set dname = 'KKK' where deptno = 55;
- 这时 会话窗口2 则无反映,因为该数据已被锁定,会话窗口1 commit 之后则可以对其进行操作,同样,如
- 果 会话窗口2 没有对其 commit, 则该数据就被 会话窗口2 锁定.可以开 N 个会话窗口
* 注意:
- 会话窗口:
- 指的是登录两个不同的窗口,如:打开两个SQL*Plus Worksheet
- 登录的用户可以是同一个
- 每一个窗口就是一个会话
##########[ 事务提交后数据状态 ]##########
* 数据的修改永久生效,不可再撤销
* 数据以前的状态永久性丢失,无法恢复
* 所有的用户(会话)都将看到操作后的结果
* 记录锁被释放,其它用户可对这些进行修改操作
* 事务中的保存点( savepoints )被清除
##########[ 事务回滚后数据状态 ]##########
* 数据的修改被撤销
* 数据恢复到修改前的状态
* 记录锁被释放
##########[ 保存点 ]##########
* 通过保存点在当前的事务中创建标记,将来可回退到指定的标记(保存点)处,实现事务的部分回滚.
* 用法举例:
- insert into dept values(55, 'Adv', 'BJ');
- insert into dept values(56, 'Sec', 'SZ');
- savepoint sp1;
- insert into dept values(57, 'RRR', 'DG');
- insert into dept values(58, 'EEE', 'HY');
- ...
- select * from dept;
- rollback to sp1;
- select * from dept;
- insert into dept1 values(57, 'Adv', 'BJ');
- insert into dept1 values(58, 'Sec', 'SZ');
- savepoint sp1;
- insert into dept1 values(59, 'RRR', 'DG');
- savepoint sp2;
- insert into dept1 values(60, 'EEE', 'HY');
- select * from dept1;
- ...
- rollback to sp2;
- select * from dept1;
- rollback;
- select * from dept1;
* 说明:
- rollback to 保存点; -> 可以回退到指定的保存点,
- rollback; -> 可以回退到事务的最初
- 在保存点后面可以加上commit,数据被提交,则之前的保存点也丢失,不可以回退到commit之前设置的保
- 存点,rollback; -> 只能回退到commit之前的状态
- insert into dept1 values(50, 'Adv', 'BJ');
- insert into dept1 values(60, 'Sec', 'SZ');
- savepoint sp1;
- commit;
- insert into dept1 values(70, 'RRR', 'DG');
- savepoint sp2;
- insert into dept1 values(80, 'EEE', 'HY');
- select * from dept1;
- rollback to sp1; -> (N, 没有这个保存点, 数据已被提交)
- select * from dept1;
- rollback;
- select * from dept1;
##########[ 数据库对象 ]##########
* 常见数据库对象
- 对象 描述
- 约束条件 存放数据的基本数据库对象,由行(记录)和列(字段组)
- 视图 表中数据的逻辑显示
- 索引 根据表中指定的字段建立起来的顺序,用于提高查询性能
- 序列 一组有规律的整数值
- 同义词 对象象的别名
* 命名规则
- 必须以字母开头
- 可以包含字母, 数字, _, $, 和 #
- 同一方案(用户)下的对象不能重名
- 不能使用 Oracle 的保留字
##########[ 创建表 ]##########
* 创建表的前提条件
- 具备创建表的权限
- 有可用的存储空间
* 创建表语法
- create table [schema.]table (column datatype [default expr][, ...]]);
* 例:
- create table scott.test1 (
- eid number(10),
- name varchar2(20),
- hiredate date default sysdate,
- salary number(8, 2) default0
- );
* 说明
- 创建表时必须指定表名, 字段名, 字段类型
- create table 为 DDL 语句, 一经执行不可撤销
- create table test (
- tid number(10) default 0,
- name varchar2(20) default 'Noname',
- birth date default sysdate
- )
##########[ 使用子查询创建表 ]##########
* 在创建表的同时, 可以将子查询的结果直接插入其中:
- 新建表与子查询结果的字段列表必须匹配
- 新建表的字段列表可以缺省
* 语法格式
- create table [schema.]table(column [, ...])
- as subquery;
* 例:
- create table myemp1(编号, 姓名, 年薪)
- as select empno, ename, sal*12 from emp;
- create table myemp2
- as select empno, ename, sal*12 annsal from emp;
- create table myemp
- as select * from emp;
* 注意:
- 如果子查询中有表达式,必须使用别名
##########[ 修改表结构 ]##########
* 使用 alter table 语句可以修改表结构,包括:
- 添加字段
- 修改字段
- 删除字段
* alter 语句为 DDL 语句, 一经执行不可撤销
##########[ 添加字段 ]##########
* 在 alter table 语句中, 使用 add 字句添加新字段, 新字段只能被加到整个表的最后
* 语法:
- alter table table_name
- add (column datatype [default expr] [, column datatype] ...);
* 例:
- drop table test;
- create table test(tid number(10),name varchar2(20));
- insert into test values(10, 'AAA');
- alter table test
- add(
- sex varchar2(2),
- address varchar2(200) default '未知'
- );
- select * from test;
##########[ 修改字段 ]##########
* 在 alter table 语句中, 使用 modify 子句修改现有字段, 包括字段的数据类型,大小和默认值
* 语法:
- alter table table_name
- modify(column datatype [default expr][, column datatype]...);
* 例:
- alter table test
- modify(address varchar2(50) default '未知');
- desc test;
* 说明:
- 修改操作会受到当前表中已有数据的影响--当已有记录的相应字段只包含空值时,类型,大小都可以修改,否则修改可能失败
- 修改的缺省值设置,只对此后新插入的记录有效
##########[ 删除字段 ]##########
* 在 alter table 语句中, 使用 drop 子句删除字段--从每行中删除掉该字段占据的长度和数据,释放在数据块中占用的存储空间
* 语法:
- alter table table_name
- drop (column [, column] ...);
* 例:
- alter table test
- drop(sex, address);
- select * from test;
##########[ 清空表中的数据 ]##########
* truncate table 语句用于清空表中数据:
- 清除表中所有记录
- 释放表的存储空间
- 为 DDL 语句, 一经执行不可撤销
* 语法:
- truncate table table_name;
* 例:
- truncate table test;
* 注意:
- 跟 delete 区别很大, truncate table 不可回滚, delete 可以回滚
##########[ 删除表 ]##########
* drop table 语句用于删除表:
- 表中所有数据将被删除
- 此前未完成的事务将被提交
- 所有相关的索引被删除
- 为 DDL 语句, 一以执行不可撤销
* 语法:
- drop table table_name;
* 例:
- drop table test;
##########[ 重命名表 ]##########
* 使用 rename 语句可以改变现有表的名称
- 也可修改其他数据对象(视图,序列,同义司等)的名称
- 执行重命名操作的必须是对象的所有者
- 为 DDL 语句, 一经执行不可撤销
* 语法:
- rename old_name to new_name;
* 例:
- create table test(tid number(10),name varchar2(20));
- insert into test values(10, 'AAA');
- insert into test values(20, 'BBB');
- insert into test values(30, 'CCC');
- rename test to tt;
##########[ Oracle数据库中的表 ]##########
* 用户定义的表
- 用户自己创建并维护的一组表
- 包含了用户所需的信息
* 数据字典表
- 由 Oracle 表据库自动创建并维护的一组表
- 包含数据信息
##########[ 数据字典 ]##########
* 什么是数据字典
- 数据字典是 Oracle 数据库的核心, 用于描述数据库及其所有对象
- 数据字典由一系列只读的表和视图组成, 这些表和视图属 sys 用户拥有, 由 Oracle server 负责维护, 用户可以通过 select 语句进行访问
* 数据字典的内容
- 数据库的物理和逻辑结构
- 对象的定义和空间分配
- 完整性约束条件
- 用户
- 角色
- 权限
- 审计记录
* 数据字典视图可分为三类:
- dba - 所有方案包含的对象信息
- all - 用户可以访问的对象信息
- user - 用户方案的对象信息
* 举例:
* 查看当前用户拥有的所有表的名字;
- select table_name from user_tables;
* 查看当前用户可以访问的所有表的名字;
- select table_name from all_tables;
* 查看当前用户拥有的所有对象的类型
- select distinct object_type from user objects;
* 查看所有用户拥有的所有对象的类型
- select table_name from dba_table;
* 查看约束
- select * from user_constraints;
* 查看当前用户
- select user from dual;
* 查看当前用户拥有的权限
- select * from user_sys_privs
##########[ 约束 ]##########
* 约束 ( Constraint ) 是在表上强制执行的数据校验规则,用于保护数据的完整性,具体包抱如下五种:
- not null (非空)
- unique key (唯一)
- primary key (主键)
- foreign key (外键)
- check (检查)
* 相关说明:
- Oracle 使用 SYS_Cn格式命约束,也可以由用户命名
- 创建约束的时机
- 在建表的同时创建
- 建表后单独添加
- 可以在表级或列级定义约束
- 可以通过数据字典视图查看约束
##########[ 建表的同时创建约束 ]##########
* 语法格式
- create table [schema.]table(
- column datatype [default expr][column_constraint],
- ...
- [table_constraints]
- );
##########[ 非空约束(not null) ]##########
* 非空约束特点
- 确保字段值不能为空(null)
- 只能在字段级定义
* 举例
- drop table student;
- create table student(sid number(3), name varchar2(20), birth date constraint student_birth_nn not null);
- insert into student values(null, 'AAA', sysdate);
- select * from student;
##########[ 唯一性约束(unique) ]##########
* 唯一性约束特点:
- 唯一性约束用于确保所在的字段(或字段组合)不出现重复值
- 唯一性约束的字段允许出现空值
- Oracle 会自动为唯一性约束创建对应的唯一性索引
- 唯一性约束既可以在字段级定义,也可以在表级定义
* 举例:
- drop table student;
- create table student(
- sid number(3) unique,
- name varchar2(20)
- );
- insert into student values(10, 'AAA');
- drop table student;
- create table student(
- sid number(3),
- name varchar2(20),
- constraint student_sid_un unique(sid)
- );
- drop table student;
- create table student(
- sid number(3),
- name varchar2(20),
- constraint student_sid_un unique(sid, name) -> 列组合唯一
- );
##########[ 主键约束(primary key) ]##########
* 主键约束特点:
- 主键用于唯一标识表中的某一行记录,功能上相当非空且唯一
- 一个表中只允许一个主键,主键可以是单个字段或多字段的组合
- Oracle 会自动为主键字段创建对应的唯一性索引
- 主键约束既可以在字段级定义,可以在表级定义
* 举例:
- drop table student;
- create table student(
- sid number(3) primary key,
- name varchar2(20)
- );
- drop table student;
- create table student(
- sid number(3) primary key,
- name varchar2(20),
- constraint student_sid_pk primary key(sid)
- );
* 联合主键:
- 由多个字段组合而成的主键也称联合主键
- 联合主键中每一个字段都不能为空
- 联合主键字段组合的值不能出现重复
- 联合主键只能定义为表级约束
* 举例:
- create table student(
- sid number(3),
- name varchar2(20),
- constraint student_sid_name_pk primary key(sid, name) -> (联合主键)
- );
##########[ 外键约束(foreign key) ]##########
* 外键约束特点:
- 外键用于确保相关的两个字段之间的参照关系,以实现参照完整性约束
- 外键约束通常构建于来自不同表的两个字段之间;
- 子表外键列的值必须在主表参照列值的范围内,或者为空
- 外键参照的必须是主表的主键或者唯一键
- 主表主键/唯一键被子表参照时,主表相应记录不允许被删除
* 举例:
- create table empinfo(
- eid number(3) primary key,
- ename varchar2(20),
- job varchar2(20),
- birth date
- );
- create table salinfo(
- eid number(3),
- basic_sal number(8, 2),
- job_allowance number(8, 2),
- travelling_allowance number(8, 2),
- personal_income_tax number(8, 2),
- constraint salinfo_eid_fk foreign key(eid) references empinfo(eid)
- );
- create table salinfo(
- eid number(3) references empinfo(eid), -> 可以放在字段级
- ...
- );
- insert into empinfo values(10, 'SMITH', 'CLERK', sysdate);
- insert into empinfo values(20, 'ALLEN', 'SALESMAN', sysdate);
- insert into empinfo values(30, 'WARD', 'MANAGER', sysdate);
- insert into empinfo values(40, 'JONES', 'ANALYST', sysdate);
- insert into empinfo values(50, 'MARTIN', 'PRESIDENT', sysdate);
- insert into salinfo values(10, 2750, 200, 300, 350); -> (Y)
- insert into salinfo values(70, 2750, 200, 300, 350); -> (N)
- create table salinfo(
- eid number(3) primary key, -> 注意:即是主键也是外键
- basic_sal number(8, 2),
- job_allowance number(8, 2),
- travelling_allowance number(8, 2),
- personal_income_tax number(8, 2),
- constraint salinfo_eid_fk foreign key(eid) references empinfo(eid)
- );
- create table salinfo(
- eid number(3) primary key references empinfo(eid), -> 注意:即是主键也是外键
- ...
- );
##########[ 检查约束(check) ]##########
* 检查约束特点:
- 定义每一行(的指定字段)都必须满足的条件
- 以条件表达式的形式给出数据需要符合的条件
- 条件表达式中不允许出现如下内容:
- currval, nextval, level, rownum 等伪列
- sysdate, uid, user, userenv 等函数
- 对其它字段的引用
- 只能在字段级定义
* 举例:
- create table test(
- name varchar2(20),
- age number(3) check(age >=0 and age <= 120)
- );
- insert into test values('AAA', 20); -> (Y)
- insert into test values('BBB', 170); -> (N)
- drop table test;
- create table test(
- name varchar2(20) check(length(name) >= 6 and length(name) <= 20), ->也可以 name varchar2(20) check(name is not null),
- age number(3) check(age >=0 and age <= 120)
- );
- insert into test values('AAA', 20); -> (N)
- insert into test values('BBB', 170); -> (N)
- insert into test values('CCCCCCC', 50); -> (Y)
##########[ 约束小结 ]##########
* 上述5种约束分为三类:
* 域完整性约束:
- not null
- check
* 实体完整性约束
- unique
- primary key
* 参照完整性约束
- foreign key
##########[ 查看约束 ]##########
* 查询用户字典视图 user_constrains
- 可得到用户的所有约束
* 查询用户字典视图 user_cons_columns
- 可获知约束建立在哪些字段上
##########[ 建表后添加约束 ]##########
* 基本语法:
- alter table table_name
- add [constraint constraint_name] constraint_type (column);
* 举例:
- create table student(
- sid number(10),
- name varchar(20)
- );
- alter table student
- add constraint student_sid_pk primary key(sid);
* 特例:
- alter table student
- modify(name not null);
##########[ 删除约束 ]##########
* 基本语法
- alter table table_name
- drop constraint constraint_name;
* 举例
- create table student(
- sid number(10),
- name varchar2(20),
- constraint student_sid_pk primary key(sid)
- );
- alter table student drop constraint student_sid_pk;
* 删除主键约束的另一种方式(只有主键才可以这样删,因为主键只有一个):
- alter table table_name drop primary key;
* 举例
- alter table student drop primary key;
##########[ 删除级连约束 ]##########
* 在删除约束时,如果还存在与该当前约束相关联的其它约束,则删除操作会失败,此时可使用 cascade 子句将其它关联约束一并删除
- alter table table_name
- drop constraint constraint_name [cascade];
* 举例
- create table empinfo(
- eid number(3) constraints empinfo_eid_pk primary key,
- ename varchar2(20)
- );
- create table salinfo(
- eid number(3) primary key references empinfo(eid)
- );
- alter table empinfo
- drop constraints empinfo_eid_pk cascade
* 在删除表中字段时,如果该字段处于多字段联合约束条件(联合主键,联合唯一键,存在参照当前字段的外键)中,则删除会失败,此时可
* 使用 cascade constraints 子句将与该字段相关的约束一并删除
* 语法:
- alter table table_name
- drop (column[, column]...) cascade constraints;
* 举例:
- create table stuinfo(
- sid number(3),
- idcard varchar2(18),
- name varchar2(20),
- constraint stuinfo_sid_idcard_pk primary key(sid, idcard)
- );
- alter table stuinfo drop(sid) cascade constraints;
##########[ 禁用约束 ]##########
* 在 alter table 语句中, 还可使用 disable constraint 子句禁用已有约束
* 也可使用 cascade 选项将相关联的约束也一并禁用
* 语法:
- alter table table_name
- disable constraint constraint_name [cascade];
* 举例:
- create table student(
- sid number(10),
- name varchar2(20),
- constraint student_sid_pk primary key(sid)
- );
- alter table student
- disable constraint student_sid_pk;
##########[ 启用约束 ]##########
* 在 alter table 语句中, 可以使用 enable constraint 子句启用先前被禁用的约束
* 语法:
- alter table table_name
- enable constraint constraint_name;
* 举例:
- drop table student;
- create table student(
- sid number(10),
- name varchar2(20),
- constraint student_sid_pk primary key(sid)
- );
- alter table student
- disable constraint student_sid_pk;
- alter table student
- enable constraint student_sid_pk;
* 说明:
- 和关闭约束操作的情形有所不同,此时无法再使用 cascade 选项一并启用相关联的其它约束
##########[ 视图 ]##########
* 什么是视图 ( View ) ?
- 视图由一个或多个表(或视图)中提取数据而成
- 视图是一种虚拟表
- 视图一经创建,可以当作表来使用
* 使用视图的好处
- 简化复杂数据查询
- 提高运行效率 -> 编译后的 SQL 语句
- 屏蔽数据库表结构,实现数据逻辑独立性
- 限制数据库访问
- 在相同数据上提供不同的视图,便于数据共享
* 简单视图和复杂视图
- 特征 简单视图 复杂视图
- 基表数目 一个 一个或多个
- 使用函数 无 有
- 使用分组 无 有
- 支持 MDL 操作 支持 不一定
##########[ 创建/删除视图 ]##########
* 创建视图
- 通过在 create view 语句中嵌入子查询的方式创建视图
* 语法:
- create [or replace] view [schema.]view [(alias[, aliasx]...)]
- as subquery
* 例:
- create or replace view myview1(编号, 姓名, 职位, 工资)
- as select empno, ename, job, sal from emp where deptno = 20;
* 查询视图
- select * from myview1;
* 查看视图结构
- desc myview1;
* 删除视罗
- drop view myview1;
##########[ 强制创建视图 ]##########
* 可使用 force 选项强制创建视图
* 语法:
- create [or replace] [force | noforce] view [schema.]view [(alias[, aliasx]...)]
- as subquery;
* 例:
- create or replace force view myview2
- as select empno, ename, jobm sal from emp2 where deptno = 20;
##########[ 更新视图 ]##########
* 在可更新视图上进行 DML 操作,可以修改基表中数据
- 可更新视图的定义中不能使用分组函数, group by 子句, distinct 关键字, rownum 伪列, 字段的定义不能为表达式..
- 由两个以上基表中导出的视图不可更新
- 基表中非空的列在视图定义中未包括,则不可在视图上进行 insert 操作...
* 在视图上进行 DML 操作,语法与在表上操作相同
- insert
- update
- delete
##########[ 创建只读视图 ]##########
* 在创建社图时,可使用 with read only 选项将之设置为只读
* 语法格式:
- create [ or replace ][force | noforce] view [schema.] view [(alias[, aliasx]...)]
- as subquery
- [with read only]
* 例:
- create or replace force view myview2
- as select empno, ename, job, sal from emp2 where deptno = 20
- with read only;
##########[ 临时视图 ]##########
* 嵌入到 SQL 语句中的子查询是临时视图
* 临时视图不是数据库对象, 其定义不会长久保存在数据库中,本次运行后即被清除
* 例:
- create table myemp(编号, 姓名, 年薪)
- as select empno, ename, sal*12 from emp;
- select rownum, a.* from (select * from emp order by sal) a
- where rownum <= 5;
##########[ 索引 ]##########
* 什么是索引 ( index ) ?
- 一种用于提升查询效率的数据库对象
- 通过快速定位数据的方法, 减少磁盘 I/O 操作;
- 索引信息与表独立存放;
- Oracle 数据库自动使用和维护索引
* 索引分类
- 唯一性索引
- 非唯一性索引
* 创建索引的两种方式
- 自动创建:在定义主键或唯一键约束时系统自动在相应的字段上创建唯一性索引
- 手动创建:用户可以在其它列上创建非唯一的索引,以加速查询
##########[ 创建/删除索引 ]##########
* 可使用 create index 语句手动创建索引
* 语法:
- create index [schema.]index
- on table(column[, column]);
* 举例:
- create index myindex on emp(ename);
* 删除索引
- 使用 drop index 语句删除索引
- 操作者须是索引的所有者, 或拥有 drop 该 index 的权限
- 删除表时相关的索引(和约束将被自动删除), 但视图和序列将保留
* 语法:
- drop index myindex;
##########[ 创建索引的原则 ]##########
* 下述情况可以创建索引
- 字段取值分布范围很广
- 字段中包含大量空值
- 字段经常出现在 where 子句或连接条件中
- 表经常被访问, 数据量很大, 且通常每次访问的数据量小于记录总量的2%-4%
* 下列情况不适合创建索引
- 表很小
- 字段不经常出现在 where 子句中
- 每次访问的数据量大于记录总数据的2%-4%
- 表经常更新
- 被索引的字段作为表达式的一部分被引用
##########[ 查看索引 ]##########
* 查询用户字典视图 user_indexes
- 可得到用户的所有索引
* 查询用户字典视图 user_ind_columns
- 可获知索引建立在哪些字段上
##########[ 基于函数的索引 ]##########
* 基于表达式的索引被统称为基于函数的索引--索引表达式由表中的字段, 常量, SQL 函数和自定义函数构建而成
* 创建函数索引
- create index [schema.]index
- on table(function(column));
* 例:
- create index myindex
- on emp(lower(ename));
* 使用函数索引
- select * from emp
- where lower(ename) = 'king';
##########[ 序列 ]##########
* 什么是序列( Sequence )?
- 系统自动生成的,不重复的整数据值,
- 序列是一种数据库对象,可以被多个用户共享
- 贡型用途是做为主键值,它对于每一行必须是唯一的
- 序列可以代替应用程序编号
- 可以对序列值进行缓冲存储,以提高访问效率
##########[ 创建序列 ]##########
* 使用 create sequence 语句创建序列
- create sequence [schema.]sequence
- [increment by n] -> 增长值(缺省为1)
- [start with n] -> 开始值(缺省为1)
- [{maxvalue n | nomaxvalue}] -> 最大值(缺省为无限,约为10的27次方)
- [{minvalue n | nominvalue}] -> 最小值(缺省为无限,约为10的-27次方)
- [{cycle | nocycle}] -> 是否循环(缺省为不循环)
- [{cache n | nocache}] -> 是否进行缓冲存储(缺省为缓冲存储20),缓存有可能丢失,不会出错,但不连续
- [{order | noorder}]; -> 是否保证顺序(缺省为noorder,如果有多个请求同一个序列)
* 例:
- create sequence iseq
- increment by 1
- start with 1
- nomaxvalue nocycle;
- create sequence student_sequence;
- create table student(
- sid number(11) primary key,
- name varchar2(20)
- );
- insert into student values(student_sequence.nextval, 'AAA');
- insert into student values(student_sequence.nextval, 'BBB');
- insert into student values(student_sequence.nextval, 'CCC');
- select * from student;
- select student_sequence.currval from dual;
- select student_sequence.nextval from dual;
* 查询数据字典视图 user_sequences 可获得用户序信息
##########[ 使用序列 ]##########
* nextval/currval 伪列
- nextval 伪列用于从指定的序数值中取出下一个值
- currval 伪列引用的是指定序列的"当前值"
* 语法格式
- select mysequence.currval from dual;
- select mysequence.nextval from dual;
- insert into test value(mysequence.nextval, 'Tom');
* 说明:
- 使用缓存( cache n )可提高访问效率
- 序列在下列情况下可能出现不连续的情况:
- 回滚
- 系统异常
- 多个表同时使用同一个序列
- 使用 nocache 和 noorder 设置会隆低运行效率
##########[ 修改序列 ]##########
* 语法格式
- alter sequence [schema.]sequence
- [increment by n]
- [{maxvalue n | nomaxvalue}]
- [{minvalue n | nominvalue}]
- [{cycle | nocycle}]
- [{cache n | nocache}]
- [{order | noorder}];
* 注意事项
- 操作者必须是序列的所有者,或者拥有 alter 该序列的权限
- 只有未来再生成的序列数受影响
- 序列的初始值不可更改
- 更改中会进行一些难,比如新的 maxvalue 如果小于当前的序列值就会报错
##########[ 删除序列 ]##########
* 删除序列
- 使用 drop sequence 语句删除序列
- 操作者必须是序列的所有者,或者拥有 drop 该 sequence 的权限
* 例
- drop sequence student_sequence;
##########[ 同义词 ]##########
* 同义词相当于对象的别名, 使用同义词可以:
- 方便访问其它用户的对象
- 缩短对象名字的长度
* 创建同义词
- create [public] synonym synonym_name
- from object;
* 例:
- create synonym gt1 for emp;
- create public synonym gt2 for scott.emp;
* 使用同义词
- select * from gt1;
* 删除同义词
- drop synonym gt1;
##########[ 收集 ]##########
* 一次插入大量数据
DECLARE
i INT;
BEGIN
i := 0;
WHILE(i < 10000)
LOOP
i := i + 1;
INSERT INTO temp VALUES(i, '姓名' || i);
END LOOP;
COMMIT;
END;
**********************************************************************
##########[ SCOTT.EMP 表 ]##########
CREATE TABLE EMP(
EMPNO NUMBER(4) NOT NULL,
ENAME VARCHAR2(10),
JOB VARCHAR2(9),
MGR NUMBER(4),
HIREDATE DATE,
SAL NUMBER(7,2),
COMM NUMBER(7,2),
DEPTNO NUMBER(2)
);
INSERT INTO EMP VALUES(7369, 'SMITH', 'CLERK', 7902, '17-12月-80', 800, null, 20);
INSERT INTO EMP VALUES(7499, 'ALLEN', 'SALESMAN', 7698, '20-2月-81', 1600, 300, 30);
INSERT INTO EMP VALUES(7521, 'WARD', 'SALESMAN', 7698, '22-2月-81', 1250, 500, 30);
INSERT INTO EMP VALUES(7566, 'JONES', 'MANAGER', 7839, '02-4月-81', 2975, null, 20);
INSERT INTO EMP VALUES(7654, 'MARTIN', 'SALESMAN', 7698, '28-9月-81', 1250, 1400, 30);
INSERT INTO EMP VALUES(7698, 'BLAKE', 'MANAGER', 7839, '01-5月-81', 2850, null, 30);
INSERT INTO EMP VALUES(7782, 'CLARK', 'MANAGER', 7839, '09-6月-81', 2450, null, 10);
INSERT INTO EMP VALUES(7788, 'SCOTT', 'ANALYST', 7566, '19-4月-87', 3000, null, 20);
INSERT INTO EMP VALUES(7839, 'KING', 'PRESIDENT', null, '17-11月-81', 5000, null, 10);
INSERT INTO EMP VALUES(7844, 'TURNER', 'SALESMAN', 7698, '08-9月-81', 1500, 0, 30);
INSERT INTO EMP VALUES(7876, 'ADAMS', 'CLERK', 7788, '23-5月-87', 1100, null, 20);
INSERT INTO EMP VALUES(7900, 'JAMES', 'CLERK', 7698, '03-12月-81', 950, null, 30);
INSERT INTO EMP VALUES(7902, 'FORD', 'ANALYST', 7566, '03-12月-81', 3000, null, 20);
INSERT INTO EMP VALUES(7934, 'MILLER', 'CLERK', 7782, '23-1月-82', 1300, null, 10);
##########[ SCOTT.DEPT 表 ]##########
CREATE TABLE DEPT(
DEPTNO NUMBER(2) NOT NULL,
DNAME VARCHAR2(14),
LOC VARCHAR2(13)
);
INSERT INTO DEPT VALUES(10, 'ACCOUNTING', 'NEW YORK');
INSERT INTO DEPT VALUES(20, 'RESEARCH', 'DALLAS');
INSERT INTO DEPT VALUES(30, 'SALES', 'CHICAGO');
INSERT INTO DEPT VALUES(40, 'OPERATIONS', 'BOSTON');
##########[ SCOTT.SALGRADE 表 ]##########
CREATE TABLE SALGRADE(
GRADE NUMBER,
LOSAL NUMBER,
HISAL NUMBER
);
INSERT INTO SALGRADE VALUES(1, 700, 1200);
INSERT INTO SALGRADE VALUES(2, 1201, 1400);
INSERT INTO SALGRADE VALUES(3, 1401, 2000);
INSERT INTO SALGRADE VALUES(4, 2001, 3000);
INSERT INTO SALGRADE VALUES(5, 3001, 9999);