1、SQL语言基础
SQL是Structured Query Language(结构化查询语言)的简称,是用户与数据库交流所需要的标准语言。
1.1 SQL语言简介
1.1.1 SQL语言特点
1)综合统一
2)集合性
3)统一性
4)高度非过程化
5)语言简单
6)以同一种语言结构提供两种使用方式(交互式应答使用、预编译SQL进行执行)
7)是所有关系数据库的公共语言。
1.1.2 SQL语言分类
1)数据定义(DDL):create、drop、alter
2)数据操纵(DML):select、insert、update、delete
3)数据控制(DCL):grant、revoke
1.1.3 SQL语言编写规则
1)SQL关键字不区分大小写
2)对象名和列名不区分大小写
3)字符值区分大小写
4)在SQL*Plus环境编写SQL语言时,如果SQL语言较短,则可以将语言放在一行上显示;
如果SQL语言很长,为了便于用户阅读,则可以将语言分开显示(并且Oracle会在除第一行外的每一行前面自动加上行号),当SQL输入完毕,要以分号作为结束符。
2、用户模式
某个用户所创建的数据库对象就都属于该用户模式。
2.1 模式与模式对象
模式是一个数据库对象的集合。模式为一个数据库对象所有,并且具有与该用户相同的名称。如SCOTT模式。
在一个模式内部不可以直接访问其他模式的数据库对象,即使具有访问权限情况下也需要指定模式名称才可以访问其他模式的数据库对象。
模式对象是由用户创建的逻辑结构,用于存储或者引用数据。如表、索引等。
模式与模式对象之间是拥有和被拥有的关系,即模式拥有模式对象,而模式对象被模式拥有。
示例:SCOTT模式下所拥有的模式对象
#通过检索user_tables表来显示SCOTT模式所拥有的4个数据表
connect scott
select table_name from user_tables
#在system模式下,通过检索dba_tables表来显示SCOTT模式所拥有的4个数据表
connect system
select table_name from bda_tables where owner='SCOTT'
3、检索数据
检索数据可以通过select语句来实现。该语句基本语法如下:
select {[distinct|all] columns|*}
[into table_name]
from {tables|views|other select}
[where conditions]
[group by columns]
[having conditions]
[order by columns]
select子句:用于选择数据表、视图中的列。
into子句:用于将原表的结构和数插到新表中。
from子句:用于指定数据来源,包括表、视图和其他select语句。
where子句:用于对检索的数据进行筛选。
group by子句:用于对检索的结果进行分组显示。
having子句:用于从使用group by子句分组后的查询结果中筛选数据行。
order by子句:用于对结果集进行排序(包含升序和降序)。
3.1 简单查询
只包含select子句和from子句的查询就是简单查询。
1)检索所有的列
select * from dept;
2)检索指定的列
在Oracle数据库中,有一个标识行中唯一特性的行标识符,该行标识符的名称为ROWID,是隐藏列,也成为伪列,长度为18为字符,包含该行数据在Oracle数据库中的物理地址。
select job,ename,empno from emp;
select rowid,job,ename from emp;
3)查询日期列
日期列的默认显示格式为DD-MON-RR
以简体中文显示日期结果
alter session set nls_date_language='SIMPLIFIED CHINESE';
select ename,hiredate from emp;
以美国英语显示日期结果
alter session set nls_date_language='AMERICAN';
select ename,hiredate from emp;
以特定格式显示日期结果
alter session set nls_date_format='YYYY"年"MM"月"DD"日"';
select ename,hiredate from emp;
使用TO_CHAR函数定制日期显示函数,将日期转变为特定格式的字符串。
4)带有表达式的SELECT子句
select sal*(1+0.1) from emp;
5)为列指定别名
为了方便查看检索结果,为列指定别名。
为列起别名,AS关键字为可选项,用户可以在列名称的后面直接指定列别名。
select empno as "员工编号",ename as "员工姓名",job as "职务" from emp;
select empno "员工编号",ename "员工姓名",job "职务" from emp;
6)显示不重复记录
select distinct job from emp;
7)处理NULL值
使用函数NVL处理空值。
select ename,sal,comm,sal+nvl(comm,0) job from emp;
当使用nvl(comm,0)处理空值时,如果comm存在数值,则函数返回原有数值;如果comm不存在数值,则函数返回0.
8)连接字符串
使用“||”操作符连接字符串
select ename,||""||'s job is '||job from emp;
使用函数CONCAT连接字符串
select concat(concat(ename,'''s job is '),job) from emp;
3.2 筛选查询
语法格式
select columns_list
from table_name
where conditional_expression
1)比较筛选
比较筛选的操作主要有以下6种情况:
A=B、A<>B、A>B、A<B、A>=B、A<=B
select empno,ename,sal
from emp
where sal>1500;
两种特殊的“比较筛选”操作:
A{operator}ANY(B):表示A与B中的任何一个元素进行operator运算符的比较,只要有一个比较值为true,就返回数据行。
A{operator}ALL(B):表示A与B中的所有一个元素进行operator运算符的比较,只要所有元素比较值为true,才返回数据行。
select empno,ename,sal
from emp
where sal<>all(1500,950,800);
2)使用特殊关键字筛选
like关键字:需要使用通配符在字符串内查找指定的模式。
%通配符代表0个或者多个字符。
_通配符代表一个且只能是一个字符。
select empno,ename,job
from emp
where ename like 'S%'; #S开头的任意字符串
要查询字符串中含有“%”或“_”时,可以使用转义关键字(\)实现查询。
in关键字:表示查询指定的值在某一目标值中。not in表示查询指定的值不在某一目标值中。
select empno,ename,job
from emp
where job in ('PRESIDENT','MANAGER','ANALUST');
BETWEEN关键字:需要返回某一个数据值是否位于两个给定的值之间。通常使用BETWEEN...AND和NOT...BETWEEN...AND来指定范围条件。
select empno,ename,sal
from emp
where sal between 2000 and 3000;
IS NULL关键字:
空值
select ename,mgr
from emp
where mgr is null;
3)逻辑筛选
在WHERE子句中使用逻辑运算符AND、OR和NOT进行数据筛选的操作。
AND逻辑运算符:逻辑与
OR逻辑运算符:逻辑或
NOT逻辑运算符:逻辑非
3.3 分组查询
select columns_list
from table_name
[where conditional_expression]
group by columns_list
1)使用GROUP BY子句进行单列分组
单列分组是基于列生成分组统计结果。当基于分组列的每个不同值生成一个统计结果。
GROUP BY子句经常和聚集函数一起使用,可以实现对查询结果中每一组数据进行分类统计。
AVG:平均值
COUNT:计数
MAX:最大值
MIN:最小值
SUM:求和
select job,avg(sal),sum(sal),max(sal),count(job)
from emp
group by job
在使用GROUP BY子句时候应该注意:
在SELECT子句后面只可以有两种表达式:统计函数和进行分组的列名。
SELECT子句中的列名必须是进行分组的列,除此之外其他全部是错误的,但是GROUP BY子句
后面的列名可以不出现在SELECT子句中。
默认情况,按照GROUP BY子句指定的分组列升序排列,如需重新排序可使用ORDER BY子句指定新的排序顺序。
select avg(sal)
from emp
group by job
2)使用GROUP BY子句进行多列分组
多列分组是指基于两个或两个以上的列生成分组统计结果。
select deptno,job,avg(sal),max(sal)
from emp
group by deptno,job;
3)使用ORDER BY子句改变分组排序结果
使用GROUP BY子句执行分组统计时候,会自动基于分组列进行升序排列。
为了改变分组列的排序结果,需要使用ORDER BY子句指定新的排序顺序。
select deptno,sum(sal)
from emp
group by deptno
order by sum(sal) desc;
4)用HAVING子句限制分组结果
HAVING子句通常与GROUP BY子句一起使用,在完成对分组结果统计后,使用HAVING子句对分组的结果做进一步的筛选。
如果不使用GROUP BY子句,HAVING子句和WHERE子句的功能一样。
HAVING子句和WHERE子句相似之处都可以定义搜索条件,不同之处在于HAVING子句可以包含聚集函数,WHERE子句不可以。
select deptno as 部门编号,avg(sal) as 平均工资
from emp
group by deptno
having avg(sal) >2000;
5)在GROUP BY 子句中使用ROLLUP和CUBE操作符
当直接使用GROUP BY子句进行多列分组时,只能生成简单的数据统计结果。为了生成数据统计、横向小计和总计统计,可以在GROUP BY子句中使用ROLLUP操作符。
select deptno as 部门编号,job as 岗位,avg(sal) as 平均工资
from emp
group by rollup(deptno,job);
为了生成数据统计、横向小计、纵向小计和总计统计,可以使用CUBE操作符。
select deptno as 部门编号,job as 岗位,avg(sal) as 平均工资
from emp
group by cube(deptno,job);
为确定统计结果是否用到特定列,可使用GROUPING函数,如果函数返回0表示统计结果使用了该列;如果返回1表示统计结果未使用到该列。
select deptno,job,sum(sal),grouping(deptno),grouping(job)
from emp
group by rollup(deptno,job);
6)使用GROUPING SETS操作符
GROUPING SETS操作符可以合并多个分组统计结果,简化多个分组操作。
select deptno,job,avg(sal)
from emp
group by grouping sets(deptno,job);
3.4 排序查询
select columns_list
from table_name
[where conditional_expression]
[group by columns_list]
order by {order_by_expression [ASC|DESC]}
1)单列排序
select deptno,empno,ename from emp order by deptno,empno;
2)多列排序
首先按照第一列进行排序,当第一列存在相同数据时,再以第二列进行排序,以此类推。
select ename,depno from emp order by deptno,sal desc;
3.5 多表关联查询
1)表别名
表别名一经定义,在整个查询语句中就只能使用表的别名而不能使用表名。
2)内连接
内连接就是使用JOIN指定用于连接的两个表,使用ON指定连接表的连接条件。若进一步限定查询范围,则可以直接在后面添加WHERE子句。
内连接返回的查询结果中只包含符合查询条件和连接条件的行。
select columns_list
from table_name1 [inner] JOIN table_name2
ON join_condition
3)外连接
外连接扩展了内连接的结果集,除了返回所有的匹配行之外,还返回一部分或者全部不匹配的行。三种外连接种类:
左外连接:不仅包含满足连接条件的数据行,还包含左表中不满足连接条件的行。LEFT [OUTER] JOIN
右外连接:不仅包含满足连接条件的数据行,还包含右表中不满足连接条件的行。RIGHT [OUTER] JOIN
完全外连接:执行一个完整的左外连接和右外连接查询,合并、去重。FULL [OUTER] JOIN
4)自然连接
自然连接是指在检索多个表时,将第一个表中的列与第二个表中具有相同名称的列进行自动连接,不需要明确指定进行连接的列。NATURAL JOIN关键字。
5)自连接
在同一张表之间的连接查询。
6)交叉连接
实际上不需要任何连接条件的连接。结果是一个笛卡尔积。
select colums_list
from table_name1 cross join table_name2;
4、ORACLE常用系统函数
4.1字符类函数
1)ASCII(c)函数和CHR(i)函数
ASCII(c):用于返回一个字符c的ASCII码。
CHR(i):用于返回ASCII码值对应的字符。
dual是Oracle系统内部提供的一个用于实现临时数据计算的特殊表。它只有一个列DUMMY,类型为VARCHAR2(1).
select ascii('Z') Z,ascii('H') H,ascii('D') D,ascii(' ') space
from dual;
select chr(90),chr(72),chr(68),32 S
from dual;
2)CONCAT(s1,s2)函数
将字符串s2连接到字符串s1的后面。
select concat('Hello ','World!') information from dual
3)INITCAP(s)函数
把字符串s的每个单词的第一个字母大写,其他字母小写。
select initcap('oh my god!') information from dual
4)INSTR(s1,s2[,i][,j])函数
字符串s2在字符串s1中第j次出现时的位置,搜索从字符串s1的第i个字符开始。
没有发现要找的字符,返回0。
i为负数,搜索从右向左进行,但是函数返回位置还是按照从左到右计算。
select instr('oracle 11g','1',3,2) abc from dual
5)LENGTH(s)函数
返回字符串s的长度
6)LOWER(s)函数和UPPER(s)函数
LOWER(s)函数和UPPER(s)函数分别用于返回字符串s的小写形式和大写形式。
7)LTRIM(s1,s2)函数、RTRIM(s1,s2)函数和TRIM(s1,s2)函数
LTRIM(s1,s2)函数:删除字符串s1左边的字符串s2
RTRIM(s1,s2)函数:删除字符串s1右面边的字符串s2
TRIM(s1,s2)函数:删除字符串s1左右两端的字符串s2
如果不指定字符串s2表示去除相应方位的空格。
7)REPLACE(s1,s2[,s3])函数
用s3字符串替换出现在s1字符串中的所有s2字符串,并返回替换后的新字符串。s3默认值是空字符串。
8)SUBSTR(s,i[,j])函数
从字符串s的第i个位置开始截取长度为j的子字符串。如果省略j,则直接截取到尾部。
4.2数字类函数
ABS(n):绝对值。
CEIL(n):返回大于或等于数据n的最小整数。
FLORR(n):返回小于或等于数据n的最大整数。
SIN(n):正弦,n为弧度。
COS(n):余弦,n为弧度。
EXP(n):e的n次幂。
SORT(n):返回n的平方根,n为弧度。
LOG(n1,n2):返回以n1为底n2的对数。
MOD(n1,n2):返回n1除以n2的余数。
POWER(n1,n2):返回n1的n2次方。
ROUND(n1,n2):返回舍入小数点右边n2位的n1的值,n2的默认值为0.若n2为负数就舍入小数点左边的位。
SIGN(n):若n为负数,返回-1;若n为正数,返回1。若n为0,返回0.
TRUN(n1,n2):返回结尾到n2位小数的n1值,n2默认为0.n2为默认值,会将n1截尾成整数,若n2为负数就截尾在小数点左边相应的位上。
4.3日期和时间函数
SYSDATE()函数:返回当前系统时间。
ADD_MONTHS(d,i):返回日期d加上i月之后的结果。
4.4转换类函数
TO_CHAR(x[,format]):实现将表达式转换为字符串,format表示字符串格式。
TO_DATE(s[,format[lan]]):实现将字符串s转换为date类型,format表示字符串格式,lan表示所使用的语言。
TO_NUMBER(s[,format[lan]]):返回字符串s代表的数字,返回值按照format格式进行显示,format表示字符串格式,lan表示所使用的语言。
select sysdate as 默认格式日期,to_char(sysdate,'YYYY-MM-DD') as 转换后日期
from dual
4.5聚合类函数
AVG():平均值
COUNT():计数
MAX():最大值
MIN():最小值
SUM():求和
VARIANCE():统计方差
STDDEV():标准偏差
5、子查询的用法
子查询是在SQL语句内的另外一条select语句。
select empno,ename,job from emp
where deptno=(select deptno from dept
where dname='RESEARCH');
子查询规则:
1)必须用括号‘()’括起来。
2)子查询中不能包含ORDER BY子句。
3)子程序允许嵌套多层,但是不能超过255层。
5.1单行子查询
单行子查询是指返回一行数据的子查询语句。在WHERE子句中引用单行子查询时,可以使用单行比较运算符(=、>、<、>=、<=和<>)。
select empno,ename,sal from emp
where sal>(select min(sal) from emp)
and sal<(select max(sal) from emp)
5.2多行子查询
多行子查询是指返回多行数据的子查询语句。在WHERE子句中引用多行子查询时,必须使用多行比较运算符(IN、ANY、ALL)。
1)使用IN运算符
当子多行子查询中使用IN运算符时,外查询会尝试与子查询结果中的任何一个结果进行匹配,只要有一个匹配成功,则外查询返回当前检索的记录。
select empno,ename,job
from emp
where deptno in
(select deptno from dept where dname<>'SALES');
2)使用ANY运算符
ANY运算符必须与单行操作符结合使用,并且返回行只要匹配子查询的任何一个结果即可。
select deptno,ename,sal from emp
where sal>any(select sal from emp where depno=10) and deptno<>10;
3)使用ALL运算符
ALL运算符必须与单行操作符结合使用,并且返回行必须匹配子查询的所有子查询结果。
select deptno,ename,sal from emp
where sal>all(select sal from emp where depno=30);
5.3关联子查询
单行子查询和多行子查询中,内查询和外查询是分开执行的,也就是说内查询与外查询的的执行是没有关系的,外查询仅仅是使用内查询的最终结果。
一些特殊的需求,内查询的执行需要借助于外查询,而外查询的执行又离不开内查询的执行,这时,内查询和外查询是相互关联的,这种子查询就被称为关联子查询。
--在emp表中,使用‘关联子查询’检索工资大于同职位平均工资的员工信息
select empno,ename,sal
from emp f
where sal>(select avg(sal) from job=f.job)
order by job;
关联子查询不仅可以作为SELECT语句的子查询,也可以作为INSERT、UPDATE或DELETE语句的关联子查询。
6、操作数据库
6.1插入数据(INSERT语句)
INSERT语句注意事项:
当为数据列增加数据,可以直接提供数字值,或者用单引号引住。
当为字符列或日期列增加数据,必须用单引号引住。
当增加数据时,数据必须满足约束规则,并且必须为主键列和NOT NULL列提供数据。
当增加数据时,数据必须与列的个数和顺序保持一致。
1)单条插入数据
INSERT INTO table_name[(column_name1[,column_name1]...)]
VALUES(express1[,express2]...)
使用列列表增加数据
既可以是数据表的全部列,也可以是不分列,但是注意不为空的列必须列出来。
insert into dept(deptno,dname,loc)
values(88,'design','beijing');
不使用列列表增加数据
必须根据表中定义的列顺序,为所有的列提供数据。
'''
desc jobs;--查询表结构和列的定义顺序。
insert into jobs
values('PRO','程序员',5000,10000);
'''
使用特定格式插入日期值
在增加日期数据时,可以使用TO_DATE函数实现日期的转换。
insert into emp(empno.ename,job,hiredate)
values(1356,'MARY','CLERK',to_date('1983-10-20','YYYY-MM-DD'));
使用DEFAULT提供数据
默认值,如果不存在默认值,自动生成NULL
insert into dept
values(60,'MARKET',DEFAULT);
2)批量插入数据
INSERT INTO table_name[(column_name1[,column_name1]...)] selectSubquery
INSERT INTO job_temps
select * from jobs
where jobs.max_salary>10000
6.2更新数据(UPDATE语句)
更新数据时,更新的列数可以由用户自己指定,列与列之间用逗号分隔更新的条数可以通过WHERE子句来加以限制。
UPDATE table_name
SET{column_name1=express1[,column_name2=express2...]
|(column_name1[,column_name2...])=(selectSubquery)}
[WHERE condition]
更新数据注意事项:
当更新数字列时,可以直接提供数字值,或者用单引号引住。
当更新字符列或日期列时,必须用单引号引住。
当更新数据时,数据要满足约束条件。
当更新数据时,数据必须与列的数据类型匹配。
1)更新单列数据
update emp
set sal=2460
where ename='SCOTT'
2)更新多列数据
update emp
set sal=sal*1.2,sal1=sal1*1.2
where job='SALESMAN'
3)更新日期列数据
update emp
set hiredate=TO_DATE('1984/01/01','YYYY/MM/DD')
where empno=7788
4)使用DEFAULT选项更新数据
update emp
set job=DEFAULT
where ename='SCOTT'
5)使用子查询更新数据
update emp
set sal=(select avg(sal)
from emp where job='MANAGER')
where sal<2000;
6.3删除数据(DELETE语句和TRUNCATE语句)
1)DELETE语句
可以删除数据库中的所有记录和指定范围的记录。如果删除指定范围的记录,要通过WHERE子句进行限制。
DELETE FROM table_name
[WHERE condition]
delete from jobs
where job_id='PRO';
如果不指定WHERE子句,那么会删除表的所有数据。
delete from emp;
2)TRUNCATE语句
TRUNCATE语句删除表中所有记录。比DELETE语句删除表中所有数据快很多。因为TRUNCATE语句删除数据不会产生数据回滚记录。所以TRUNCATE语句的操作也无法使用ROLLBACK语句撤销。
truncate table jobs_temp;
需要说明,在TRUNCATE语句中还可以使用REUSE STORAGE关键字或DROP STORAGE关键字,前者表示删除记录后仍然保存记录所占用的空间,后者表示删除记录后立即回收记录占用的空间。默认情况下TRUNCATE语句使用DROP STORAGE关键字。