绑定完请刷新页面
取消
刷新

分享好友

×
取消 复制
SQL语言(汇总)
2023-05-29 17:40:16

简介

基本知识

SQL语言是一种非过程语言;
SQL语句接受集合作为输入,返回集合作为输出;
SOL的集合特性允许将一条SQL语句的结果作为另一条SQL语句的输入;
SQL不要求用户指定对数据的存放方法,用户无需了解存取路径及物理地址,存取的路径由DBMS优化来完成;
查找可以是集合,插入、删除更新也可以是元组;
同一语法结构有两种使用方法,用户在终端命令提示符下输入SQL命令时数据库服务器立即执行的交互式应答使用,和把SQL命令嵌入到应用程序中执行的预编译SQL。

通过SQL语言可以完成以下操作

1建立数据库表格,并设置表格可以使用的空间;
2改变数据库系统的环境设置;
3针对某个数据库或表格授予用户存取权限;
4对数据库表格建立索引值;
5修改数据库表格结构(新建、删除、修改表格字段);
6对数据库进行数据的新建、修改、删除、查询。

SQL语言分类

1数据查询语言-DQL-select 语句
2数据操作语言-DML-insert(插入数据) update(更新数据) delete(删除数据) 语句
3事务控制语言-TCL-commit(提交对数据库的更改) rollback(取消对数据库的更改) savepoint(设置保存点)
4数据定义语言-DDL-create table(创建表) alter table(修改表结构) drop table(删除表)
5数据控制语言-DCL-grant(授予用户或者角色权限) revoke(收回用户或者角色权限)

SQL语言编写规则

1关键字不区分大小写
2字符值区分大小写

用户模式

1模式是一个数据库对象的合集
2模式为一个数据库用户所拥有,并且具有和该用户相同的名称,如system模式scott模式
3在一个模式内部不能直接访问其他模式的数据库对象,即使在具有访问权限的情况下,也需要指定模式名称才可以访问其他模式的数据库对象
4模式对象是用户创建的逻辑结构,用以储存或引用数据
5模式拥有模式对象,模式对象被模式所拥有

scott模式示例(还有很多其他模式)
emp:
empno|NUMBER
ename|VARCHAR2
job|VARCHAR2
mgr|NUMBER
hiredate|DATE
sal|NUMBER
comm|number
salgrade:
grade|NUMBER
losal|NUMBER
hisal|NUMBER
dept:
empno|NUMBER
dname|VARCHAR2
loc|VARCHAR2
bonus:
ename|VARCHAR2
job|VARCHAR2
sal|NUMBER
comm|NUMBER

SQL>connect scott/tiger
已连接
SQL>select table_name from user_tables;--查询数据库的所有表名

SQL>connect system/1qaz2wsx
已连接
SQL>select table_name from dba_tables where owner='SCOTT';--在system模式下查询数据库的所有表名

一、检索数据

本文代码基于PL/SQL Developer1开发工具与Oracle进行交互(此外还有TOAD和oracle自带工具SQL*Plus

基本语法格式
select{[distinct|all]columns|*}--用于选择数据表、视图中的列【4】
[into table_name]--用于将原表中的结构和数据插入新表中
from{tables|views|other select}--用于指定数据来源,包括表、视图和其他select语句【1】
[where conditions]--用于对检索的数据进行筛选【2】
[group by columns]--用于对检索结果进行分组显示【3】
[having conditions]--用于从使用group by子句分组后的查询结果中筛选数据行【5】
[order by columns]--用来对结果进行排序【6】

以上语句的执行顺序:【4】【1】【2】【3】【5】【6

1简单查询

(QL/SQL-scott模式下)

1.1检索所有列

select * from emp;--检索一个表的所有列
select * from emp,dept;--检索多个表的所有列,检索结果呈现在同一个窗口,且和表名的输入顺序有关

注:select子句中可跟具体字段(列名)、常量、*、函数
    常量-可用于使查询结果明晰
    select '姓名:',name from student;--查询结果如 姓名:张张
    select '张简简' from student;--suanzuo

1.2检索指定的列

(1)基础

select column1column2 from table_name;--从单个表中查询多个制定的列
select column1column2 from table_name1,table_name2;--从多个表中查询多个特定的列
select column2column1 from table_name1,table_name2;--语句中不要求列名和表名顺序对应


(2)伪列

(2.1)ROWID

oracle数据库中有的行标识符ROWID
Oracle数据库中使用隐藏列,实际上并不是定义在表中
所以被称为伪列,长度为18个字符
包含该行数据在Oracle数据库中的物理地址,使用select语句可以查询到
select rowid from table_name;
--查询伪列
--与索引相关

(2.2)ROWNUM

非真实存在于表中
与查询结果相关
为每条记录赋序号
查询结果是一行一行出现的,查询一行赋一个号

select rownum,s.name
from student s
where rownum=1;
--可运行
select rownum,s.name
from student s
where rownum=2;
--不可运行
--因为行无法出现,无法跳过1赋值2
select rownum,s.name
from student s
where rownum<3;
--可运行,显示前两条记录
select rownum,s.name
from student s
where rownum>3;
--不可运行
--行无法出现

解决办法(用子查询):
select *
from select rownum r,s.name,s.age
      from student s
where r>3;

ROWNUM通常用于分页

--分页
--每一页有10行,分别查询页和第二页内容
--注意用公式的形式(如10*(1-1)+1 and 10*1)
select * from 
(select rownum r,s.name,s.age from student s)
where r between 10*(1-1)+1 and 10*1;
select * from 
(select rownum r,s.name,s.age from student s)
where r between 10*(2-1)+1 and 10*2;


1.3查询日期列

日期列指数据类型为DATA的列,默认显示格式为DD-MON-RR
------
1)以简体中文显示日期结果
alter session set nls_date_language='SIMPLIFIED CHINESE';--报错‘ora-12705:无法访问NLS数据文件,或者指定的环境’
--原因是多次重复安装数据库--解决办法暂无,建议一开始一次性安装好数据库--原来是SIMPLIFIED拼写错误(可恶)
select * from V$NLS_PARAMETERS--可查看系统参数,如NLS_LANGUAGE  |  SIMPLIFIED CHINESE)
select ename,hiredate from emp;--即使步错误解决,仍无法显示‘17-12月-80’格式的结果
------
2)以美国英语显示日期结果
alter session set nls_date_langeuage='AMERICAN';--但是这样的修改不会有ora-12705,可以修改
select ename,hiredate from emp;--仍然无法得到'17-DEC-80'格式的查询结果
-----
3)以特定格式显示日期结果
alter session set nls_date_format='YYYY''年''MM''月''DD''日''';--显示‘a-01821日期格式无法识别’报错
select ename,hiredate from emp;--即使成功修改后,在PL/SQL中也无法显示自定义日期格式

alter session set nls_date_format='YY-DD-MM';--可运行
select ename,hiredate from emp;--无法显示自定义日期格式

alter session set nls_date_format='YY';--也可运行
select ename,hiredate from emp;--无法显示自定义日期格式
----
4TO_CHAR函数自定义日期(看函数部分)

1.4带有表达式的select语句

select sal*(1+.1),sal from emp;--查询结果是两列sal*(1+0.1),sal
select语句中可以使用算术运算符+-*/和括号,不仅可以执行单独的数学运算,还可以执行单独的日期运算以及与列名关联的运算

1.5别名

1)列别名
select empno as 员工编号,ename as '员工名称'job 职务 from emp;--报错-原因'员工名称'外有引号
select empno as 员工编号,ename yuangongmingcheng from emp;--可以不需要as,别名不能被引号选中,别名可以是中文、字母
2)表别名-可快捷选取列名(养成习惯)-另建student数据表
select   from student s;
select s.______[出现各列名] from student s;--选中需要的列名
select s.birthday,tel from student s;--不必须用s.tel

1.6显示不重复记录

select distinct job from emp;--减少冗余
select distinct XO,gender from student s;--另建student数据表,对组合列去重,以每行每单位内容全重复的才算重复

1.7处理null值

null表示未知量,不是空格也不是,当插入数据时,如果没有为特定列提供数据,并且该列没有默认值,则结果为null
select ename,sal,comm,sal+comm from emp;
--sal+comm会出现值为‘值+null=null’的错误
select ename,sal,comm,sal+nvl(comm,) from emp;
--nvl(comm,0)如果comm存在数值则返回数值,否则为0
####
含有null的条件查询
select * from student s where s.major like'%会计%' and (s.home not like '%济宁%' or s.home is null);
--查询学会计的家乡不是济宁的同学
####
nvl2(参数1,参数2,参数3)
--参数1不为空时,返回参数2,否则返回参数3

### 查询xx为空或者错误的XX 
select s.name,d.dormno
from student s
left join dorm d
on s.dormid=d.id
where d.id is null;
-- 用 is null 非=''或者=null


2条件查询

2.1比较查询

语法select col1,col2... from tbname where 条件要求;

大于    >
大于等于    >=
小于    <
小于等于    <=
不等于    <>  或者 =

特殊
A {operator} any B 表示元素A与B中任何元素进行operator运算符的比较,只要有一个比较值为TRUE则返回数据行
例:select empno,ename,sal from emp where sal = any(840,1300,1155);
A {operator} all B 表示元素A与B中所有元素进行operator运算符的比较,全部比较值都为TRUE才返回数据行
例:select empno,ename,sal from emp where sal <> all(840,1300,1155);

2.2模糊查询(like关键字)

select * from student s where name like '张张%';--可得张张、张张张等人的信息,%可匹配0个及任意长度字符串

select * from student s where name like '张_';--可得张张、张海等名字为两个长度且姓张的人名,‘_’仅仅且必须匹配一个字符

select * from student s where s.bulidid not like '%楼%';--like关键字无法查询到空白记录null值
select * from student s where not s.bulidid like '%楼%';--‘非’操作,查询结果和上面一样

select * from student s where not s.bulidid like '小红楼';--则无结果,应当用‘=’号

转义字符(不是oracle自带的,需要自己定义)
select * from dept_temp where dname like 'IT\_%'escape'\';--自定义‘\’为转义符,例子中‘_’已经不是通配符了

2.3 in关键字查询

select * from student s where s.xo [not] in ('A','AB');
--查询血型[不为A和AB]为A或AB的同学的所有信息
in 后面要跟一个集合

2.4多条件查询(and,or,not--and优先级高于or)

考虑 与或非、交并补
select * 
from student s 
where s.name not like '孙%' and s.name not like '王%';
--查询不姓孙也不姓王的学生
select * 
from student s 
where not (s.name  like '孙%' or s.name  like '王%');--查询不姓孙也不姓王的学生

2.5 between函数

[not]between and 
select * from student s where s.age>=22 and s.age<=24;
等同
select * from student s where s.age between 22 and 24;

2.6对查询结果排序(order by总是放在select语句的后面)

select s.groupno,s.name,s.age from student s order by s.groupno,s.age desc;
--检索组号、姓名、年级并按组号升序排序(默认ASC)再按年级降序(DESC)

select ename,sal from emp order by (3+sal)*8;
--检索依照的条件可以是特定列或表达式

注意了解以下两种用法但不建议使用(不直观):
select empno,ename,sal*12 AnnualSalary from emp order by 3 desc;
--用列名‘3’指代行名,‘Annual Salary’取别名时两个单词间不能有空格
select ename from emp order by sal;
--用非选择列表列进行排序

ASCII码:计算机中每一个字符都有一个数字与之对应
         10 \n 换行符  65 A 97 a
         排序时先按字符中个字符的ASCII码比较,若相同再比较第二个字符的ASCII码 

3分组查询

3.1单列分组

(1)基本用法

select deptno,job from emp;
select deptno,job from emp group by deptno,job;
select ename,deptno,job from emp group by deptno,job;--报错
--对于含group by子句的select语句中仅允许出现统计函数、常量、group by子句中已经出现过的字段列
select ename,deptno,job from emp group by ename,deptno,job;

select avg(sal) from emp group by job;--group by 中的列可以不出现在select列表中

(2)常用的统计函数

聚合函数:
AVG|返回一个数字列或者计算列的平均值
COUNT|返回查询结果中的记录数(注意不统计null值--count(1)可以用来计数
MAX|返回一个数字列或是计算列的大值
MIN|返回一个数字列或是计算列的小值
SUM|返回一个数字列或者计算列的总合
select sum(sal),sum(distinct sal),sum(all sal)
from emp;
--都可以加 distinct 或 all(默认为all)


select job,avg(sal),sum(sal),max(sal),min(sal),count(job) 
from emp 
group by job;
--分组的意义在于对分组后的内容进行处理
--查询各类job的平均工资、总工资、高工资、低工资、人数
JOB AVG(SAL) SUM(SAL) MAX(SAL) MIN(SAL) COUNT(JOB)
CLERK   1037.5    4150    1300      800     4
SALESMAN 1400     5600    1600     1250     4
PRESIDENT 5000    5000    5000     5000     1
MANAGER 2758.33   8275    2975     2450     3
ANALYST 3000      6000    3000     3000     2

####
补充:
wm_concat
select wm_concat(s.name)
from student s;
--用逗号将所有的字符串连接在一起
variance统计方差
stddev标准方差

(3)对于 含group by子句的select语句中仅允许出现统计函数、常量、group by子句中已经出现过的字段列 的理解

select job,avg(sal) from emp;--error:不是单组分组函数
select job,avg(sal) from emp group by job;
条语句select子句中的列名称job告诉Oracle系统显示每行数据的职位,在emp表中有很多条数据
avg(sal)告诉Oracle显示emp表中所有数据行的平均工资,只能产生一个平均工资
两者矛盾,因此报错

3.2多列分组

select deptno,job,avg(sal),max(sal) from emp group by deptno,job;
--与单列分组的区别在于多列分组是把多个列中相同的组合列作为分组的标准
--查询同一部门中的同类工作的平均工资和高工资

DEPTNO  JOB AVG(SAL) MAX(SAL)
20  CLERK      950  1100
30  SALESMAN  1400  1600
20  MANAGER   2975  2975
30  CLERK      950   950
10  PRESIDENT 5000  5000
30  MANAGER   2850  2850
10  CLERK     1300  1300
10  MANAGER   2450  2450
20  ANALYST   3000  3000

3.3分组后排序

select deptno,job,avg(sal),max(sal) from emp group by deptno,job  order by deptno desc;

3.4限制分组结果

having子句对分组结果做进一步筛选
如果不使用group by子句having子句和where子句一样都具有定义搜索条件的作用
having子句可以包括聚合函数COUNT SUM AVG where子句不能包含聚合函数

select子句中的处理顺序
首先由from子句找到数据表where子句则接收from子句输出的结果having子句接收来自group bywherefrom子句的输出

select deptno as 部门编号,avg(sal) from emp group by deptno having avg(sal)>2000;
--先通过分组计算得到每个部门的平均工资,然后通过having过滤得到平均工资大于2000的记录信息
--聚合函数的条件必须放在having之后

select deptno as 部门编号 from emp  where sal>2000;--此处的where并不能用having替代

3.5 ROLLUP 和 CUBE 操作符 (仅作了解)

1)使用 ROLLUP 操作符执行数据统计
(直接用group by只能生成的简单的数据统计结果,用ROLLUP生成数据统计、横向小计、总计统计)
select deptno as 部门编号,job as 岗位,avg(sal) as 平均工资 from emp group by rollup(deptno,job); 
--可得到各部门全部岗位的平均工资

部门编号 岗位 平均工资
10  CLERK   1300
10  MANAGER 2450
10  PRESIDENT 5000
10      2916.66666666667--得到部门10的全部岗位的平均工资
20  CLERK   950
20  ANALYST 3000
20  MANAGER 2975
20      2175
30  CLERK   950
30  MANAGER 2850
30  SALESMAN 1400
30      1566.66666666667
        2073.21428571429
----
2)使用 CUBE 操作符执行数据统计
select deptno 部门编号,job 岗位,avg(sal) 平均工资 from emp group by cube(deptno,job);

部门编号  岗位  平均工资
                 2073.21428571429--全部部门的全体员工的平均工资
           CLERK 1037.5--所有岗位为CLERK的员工的平均工资
           ANALYST 3000
           MANAGER 2758.33333333333
           SALESMAN  1400
           PRESIDENT 5000
10                2916.66666666667--所有部门为10的员工的平均工资
10         CLERK 1300
10         MANAGER 2450
10         PRESIDENT 5000
20                  2175
20         CLERK 950
20         ANALYST 3000
20         MANAGER 2975
30                  1566.66666666667
30         CLERK 950
30         MANAGER 2850
30         SALESMAN  1400

思考一:select deptno 部门编号,job 岗位,avg(sal) 平均工资 from emp group by cube(job,deptno);

部门编号 岗位 平均工资
        2073.21428571429--全部部门的全体员工的平均工资
10      2916.66666666667--所有部门为10的员工的平均工资
20      2175
30      1566.66666666667
    CLERK   1037.5--所有岗位为CLERK的员工的平均工资
10  CLERK   1300
20  CLERK   950
30  CLERK   950
    ANALYST 3000
20  ANALYST 3000
    MANAGER 2758.33333333333
10  MANAGER 2450
20  MANAGER 2975
30  MANAGER 2850
    SALESMAN    1400
30  SALESMAN    1400
    PRESIDENT   5000
10  PRESIDENT   5000

思考二:select deptno 部门编号,job 岗位,mgr 上级,avg(sal) 平均工资 from emp group by cube(job,deptno,mgr);
--出现多个复合组合的结果,复杂度提升,个人认为不建议使用

部门编号 岗位 上级  平均工资
            5000
            2073.21428571429
        7566    3000--上级是7566的员工的平均工资
        7698    1310
        7782    1300
        7788    1100
        7839    2758.33333333333
        7902    800
10          5000
10          2916.66666666667
10      7782    1300
10      7839    2450
20          2175
20      7566    3000
20      7788    1100
20      7839    2975
20      7902    800
30          1566.66666666667
30      7698    1310
30      7839    2850
    CLERK       1037.5
    CLERK   7698    950
    CLERK   7782    1300
    CLERK   7788    1100
    CLERK   7902    800
10  CLERK       1300
10  CLERK   7782    1300
20  CLERK       950
20  CLERK   7788    1100
20  CLERK   7902    800
30  CLERK       950
30  CLERK   7698    950
    ANALYST     3000
    ANALYST 7566    3000
20  ANALYST     3000
20  ANALYST 7566    3000
    MANAGER     2758.33333333333
    MANAGER 7839    2758.33333333333
10  MANAGER     2450
10  MANAGER 7839    2450
20  MANAGER     2975
20  MANAGER 7839    2975
30  MANAGER     2850
30  MANAGER 7839    2850
    SALESMAN        1400
    SALESMAN    7698    1400
30  SALESMAN        1400
30  SALESMAN    7698    1400
    PRESIDENT       5000
    PRESIDENT       5000
10  PRESIDENT       5000
10  PRESIDENT       5000
----
3)使用 GROUPING 函数确定统计结果是否用到了特定列
select deptno 部门编号,job 岗位,mgr 上级,avg(sal) 平均工资,grouping(deptno),grouping(job),grouping(mgr)
from emp group by cube(job,deptno,mgr);

部门编号 岗位 上级  平均工资 GROUPING(DEPTNO) GROUPING(JOB) GROUPING(MGR)
            5000    1   1   
            2073.21428571429    1   1   1
        7566    3000    1   1   
        7698    1310    1   1   
        7782    1300    1   1   
        7788    1100    1   1   
        7839    2758.33333333333    1   1   
        7902    800 1   1   
10          5000       1   
10          2916.66666666667       1   1
10      7782    1300       1   
10      7839    2450       1   
20          2175       1   1
20      7566    3000       1   
20      7788    1100       1   
20      7839    2975       1   
20      7902    800    1   
30          1566.66666666667       1   1
30      7698    1310       1   
30      7839    2850       1   
    CLERK       1037.5  1      1
    CLERK   7698    950 1      
    CLERK   7782    1300    1      
    CLERK   7788    1100    1      
    CLERK   7902    800 1      
10  CLERK       1300          1
10  CLERK   7782    1300          
20  CLERK       950       1
20  CLERK   7788    1100          
20  CLERK   7902    800       
30  CLERK       950       1
30  CLERK   7698    950       
    ANALYST     3000    1      1
    ANALYST 7566    3000    1      
20  ANALYST     3000          1
20  ANALYST 7566    3000          
    MANAGER     2758.33333333333    1      1
    MANAGER 7839    2758.33333333333    1      
10  MANAGER     2450          1
10  MANAGER 7839    2450          
20  MANAGER     2975          1
20  MANAGER 7839    2975          
30  MANAGER     2850          1
30  MANAGER 7839    2850          
    SALESMAN        1400    1      1
    SALESMAN    7698    1400    1      
30  SALESMAN        1400          1
30  SALESMAN    7698    1400          
    PRESIDENT       5000    1      
    PRESIDENT       5000    1      1
10  PRESIDENT       5000          
10  PRESIDENT       5000          1
--此查询语句可能存在无意义的情况,本处只用做grouping示例
----
4)在 RULLUP 操作符中使用复合列
复合列被看作一个逻辑单元的列组合,可以略过RULLUP的某些统计结果
例如:group by rollup(a,b,c)的统计结果等同于group by(a,b,c) group by(a,b) group by a group by()的并集
将(b,c)作为复合列,group by(a,(b,c))的结果等同于group by(a,b,c)group by agroup by()的并集

select deptno as 部门编号,job as 岗位,avg(sal) as 平均工资 from emp group by rollup(deptno,job); 
部门编号 岗位 平均工资
10  CLERK   1300
10  MANAGER 2450
10  PRESIDENT 5000
10      2916.66666666667
20  CLERK   950
20  ANALYST 3000
20  MANAGER 2975
20      2175
30  CLERK   950
30  MANAGER 2850
30  SALESMAN 1400
30      1566.66666666667
        2073.21428571429

select deptno as 部门编号,job as 岗位,avg(sal) as 平均工资 from emp group by rollup((deptno,job)); 

部门编号 岗位 平均工资
10  CLERK   1300
10  MANAGER 2450
10  PRESIDENT 5000
20  CLERK   950
20  ANALYST 3000
20  MANAGER 2975
30  CLERK   950
30  MANAGER 2850
30  SALESMAN 1400
        2073.21428571429
----
5)在 CUBE 操作符中使用复合列
例如:group by cube(a,b,c)的统计结果等同于group by(a,b,c) group by(a,b) group by(a,c)group by(b,c)group by agroup by bgroup by c group by()的并集
将(a,b)作为复合列,group by((a,b),c)的结果等同于group by(a,b,c)group by(a,b)group by cgroup by()的并集

3.6 GROUPING SETS 操作符(生成多种分组结果)

select deptno,job,avg(sal)
from emp
group by grouping sets(deptno,job);
--得到依部门和工资两个平均工资


4多表关联查询

4.1表的别名

①在多表关联查询时,如果多个表之间存在同名的列,则必须用表名限定列的引用
 dept.deptno,emp.deptno
②为使语句简洁,使用表别名,表别名在from子句中定义如 emp e
③表别名一经定义,在整个查询语句中就只能用表别名,而不能用表名 emp.ename × e.ename 
④表别名只在所定义的查询语句中有效


4.2内连接(直连-只显示关联到的结果,会遗失部分数据)

####
select d.dormno, s.name
from dorm d
[inner]join student s--默认是inner内查询,不用写
on d.id=s.dormid;
--用相同的ID来进行表之间连接

####
select b.buildname,d.dormno,s.name
  from building b
  join dorm d
    on b.id = d.buildid
  join student s
    on d.id = s.dormid;
--三个及以上连接

####
select d.dormno, s.name
  from dorm d
  join student s
    on d.id = s.dormid
 where s.gender = ;
 --条件语句放在后面
 
####
内连接的另一种写法(了解即可,千万别用)
select e.ename,d.dname,e.sal
 from emp e,dept d--省去了join on 语句
 where sal>=3000;--忘记写where子句会导致笛卡尔积任意关联,会导致非常严重的数据库崩溃
 --笛卡尔积:两个表做任意关联,无关联条件,导致数据暴增

4.3外连接(可以返回不相关的数据行,不必须有条件语句)

(1)左连接(以左边的为主表,显示所有行的结果,以右边的为从表,只显示关联的结果)

select e.ename,d.dname,e.comm
from dept d
left join emp e
on e.deptno=d.deptn;--此处应该在建表时用id而不用no

####
select s.name,d.dormno 
from student s, dorm d 
where s.dormid=d.id(+);
--左连接另种写法,仅作了解,千万别用,会造成笛卡尔积数据库崩溃或数据丢失
####
▲如果左连接的从表添加where条件,则左连接失效
例:查询所有人的姓名,如果其他宿舍在2楼,显示宿舍号
select s.name,d.dormno
from student s
left join dorm d
on d.id=s.dormid
where d.floor=2;--此处where应改为and,把选择条件变成关联条件

(2)右连接

right用法和左连接一样

(3)全连接(特殊情况才用,一般不用,显示左右全部数据,如果关联则在同一行)

full同上

4.4自然连接(几乎不用)

自然连接指在检索多个表时
oracle会将个表中的列和第二个表中具有相同名称的列进行自动连接
语法: natural join
select empno,ename,job,dname
from emp 
natural join dept
where sal>2000;
--由于自然连接要求表之间必须有相同名称的列,这样容易在出现不可预知的错,故几乎不用


4.5自连接(一表两用)

####
select em2.ename 上层管理者,em1.ename 下属员工
from emp em1
join emp em2
on em1.mgr=em2.empno--关键在于找到对应关系
order by em1.mgr;

####
如果左连接后使用自连接,则自连接会失效
例:
select d.dormno,s.name,s1.name
from student s
left join dorm d
on d.id=s.dormid
left join student s1
on d.headno=s1.stuno;
--仅作语法示例

4.6交叉连接(几乎不用,会造成笛卡尔积)

语法: cross join
select count(*) --计算查询结果的行数
from dept
cross join emp;
--执行结果是一个笛卡尔积

等同于

select count(*)
from dept,emp;
--执行结果是一个笛卡尔积


5子查询

又称嵌套查询

在执行数据操作时
某个操作要依赖另一个select语句的查询结果
可以select语句嵌入该语句中

注意:
①子查询子句必须用括号括起来
②子查询不能包括order by
③子查询允许多层(不超过255行)嵌套
④子查询比多表关联查询更灵活、功能更强大、更容易理解,但效率更低


5.1单行子查询

指子查询语句的返回结果只有一行
当在where子句中引用单行子查询时可以用单行比较运算符= > < >= <= <>

①关联子查询在select语句(查询结果中)
select s.name,s.gender,s.groupno,
       (select avg(t.age)from student t)--此处的平均年龄只作为常量,不是聚合函数
from student s;
--查询每个人的姓名、年龄和班级平均年龄

②关联子查询在条件语句中
select empno, ename, sal--外查询
  from emp
 where sal > (select min(sal) from emp)--括号内是内查询
   and sal < (select max(sal) from emp);
--查询emp表中不是高或低工资的员工编号、姓名、工资

5.2多行子查询

指子查询语句的返回结果不止一行
当在where子句中引用多行子查询时必须用多行比较符in any all

(1.1)in运算符

在多行子查询中使用in运算符时
外查询会尝试与子查询结果中任何一个结果进行匹配
只要有一个匹配成功则外查询会返回当前的检索记录
select empno,ename,job
from emp
where deptno in
(select deptno from dept where dname<>'SALES');
--查询emp表中不是销售部门的员工信息

(1.2)exists运算符

exists存在(前面可以加not

--查询有预备党员的小组
select s.groupno
  from student s
 where s.groupno in 
       select t.groupno
       from student t
       where t.political = '预备党员');
select distinct s.groupno
  from student s
 where exists (select t.groupno
          from student t
         where t.political = '预备党员'
           and s.groupno = t.groupno);
--查询没有预备党员的小组
select distinct s.groupno
  from student s
 where not exists (select t.groupno
          from student t
         where t.political = '预备党员'
           and s.groupno = t.groupno);
           
 工作中常用 exists代替 in(速度更快)
 in关联子查询先子查询全部
 再主查询(速度慢,但容易想)
 exists:关联子查询先主查询一条一条查询
 再子查询(子查询不需要查询全部,速度更快)
①将原 SQL中 in改为 exists
②在子查询中添加条件
 (原子查询的结果=原主查询中 in的前面一致


(2)any运算符

any运算符必须与单行操作符结合使用
并且返回行只要匹配子查询的任何一个结果即可
select deptno,ename,sal
from emp
where 
sal>any (select sal from emp where deptno=30)
and deptno<>30;--and与sal语句是并列的
--查询emp表中工资大于30号部门的任意一个员工工资的其他部门的员工信息
--实质上查询emp表中工资大于30号部门的低的一个员工工资的其他部门的员工信息

(3)all运算符

all运算符必须与单行操作符结合使用
并且返回行必须匹配子查询的所有结果
select deptno,ename,sal
from emp
where 
sal>all (select sal from emp where deptno=30);
----查询emp表中工资大于30号部门的所有员工工资的其他部门的员工信息
--与any相比较

5.3多列子查询

select *
from student s 
where (s.age,s.gender)=(select t.age,t.gender from student t where name='张简简');
--查询年龄和性别都和张简简相同的人
--注意s.age,s.gender和t.age,t.gender前后顺序要一致


5.4关联子查询

在单行或多行子查询中内查询和外查询是分开执行的
外查询仅仅使用内查询的终结果

在一些特殊需求的子查询中内查询和外查询相互关联
被称为关联子查询

①关联子查询在select语句(查询结果中)
select s.name,s.gender,s.groupno,
       (select avg(t.age)from student t where t.groupno=s.groupno)
from student s;
--使用了两个表别名
--不需要使用分组函数
--例 select avg(t.age) from student t where t.groupno*=1
    即可查询1组的平均年龄

②关联子查询在条件语句中
select s.name,s.age
from student s
where s.age>(select avg(t.age) from student t where t.groupno=s.groupno);
--查询比小组平均年龄大的人

5.5子查询难点用法

--查询A型血人数比B型血人数多的宿舍
select ssaxx.dormno
from (select d.dormno,count(1) ssaxxrs 
      from student s 
      join dorm d 
      on s.dormid=d.id 
      where s.xo='A' 
      group by d.dormno) ssaxx--把A血型的寝室和人数看作一个表
join (select d.dormno,count(1) ssbxxrs 
      from student s 
      join dorm d 
      on s.dormid=d.id 
      where s.xo='B' 
      group by d.dormno) ssbxx--把B血型的寝室和人数看作一个表
on ssaxx.dormno=ssbxx.dormno
where ssaxx.ssaxxrs>ssbxx.ssbxxrs;
--当问题不清晰的时候拆解成多个表来解决问题即可

6 开窗函数

也称分析函数
窗,就是范围
over子句所限定的范围内进行查询
速度优于子查询


6.1 partition by

select s.name,s.groupno,s.age,
	   max(s.age) over(partition by s.groupno) age1
from student s;
--查询所有同学姓名、组号年龄和内大年龄
--partition by 类似于 group by具有分组的作用
--【max(s.age) over(partition by s.groupno) age1】是一个整体
  使用多个聚合函数时每个要单独加over语句
--由于受开窗范围的影响别名(此处为age1)要放在 order by后

6.2 order by

select s.name,s.groupno,s.age,max(s.age)
	   over(partition by s.groupno order by s.age)
from student s;
--查询所有同学姓名、组号年龄和窗口内大年龄
--order by
  不仅仅具有排序的作用
  只有 order by 没有 partition by 则仅有排序功能 
  会使窗口发生变化
  窗口变化为从 partition by选定的窗口的行数据开始
  到与被查询主体 order by后的列名(此处为s.age)相同值的所有数据行为止
  (不明白就运行代码试试)

6.3 排序类开窗函数 row_number()、 rank()、dense_rank() ▲

在窗口范围内对 order by 后指定的数据进行排序

select s.name,s.groupno,s.age,
	   row_number() over(partition by s.groupno order by s.age)
from student s;
--相同年龄也分先后顺序
  如:排序 1  2  3  4  5
     年龄 18 19 19 19 20
select s.name,s.groupno,s.age,
	   rank() over(partition by s.groupno order by s.age)
from student s;
--并列第二然后第五
  如:排序 1  2  2  2  5
     年龄 18 19 19 19 20
select s.name,s.groupno,s.age,
	   dense_rank() over(partition by s.groupno order by s.age)
from student s;
--并列第二然后第三
  如:排序 1  2  2  2  3
     年龄 18 19 19 19 20

6.4 偏移类开窗函数 lag() lead()

select s.name,s.groupno,s.age,
       lag(s.age) over(partition by s.groupno order by s.age)
from student s;
--lad(参数1,参数2,参数3)
  参数1(列名)所处位置的数据往上偏移参数2个位置
  如果偏移后数据为空则用参数3的数据填充
--lead(参数1,参数2,参数3)
  往下偏移

6.5 了解部分

(1)first_value() last_value()

--不可和聚合函数同用
select s.name,s.groupno,s.age,
       first_value(s.age) over(partition by s.groupno order by s.age),
       last_value(s.name) over(partition by s.groupno order by s.age)
from student s;    
--注意要写逗号
--first_value(col_name)返回该窗口中某列的个值
--last_value(col_name)返回该窗口中某列的后一个值


(2)影响开窗范围的参数(range between 参数1 and 参数2)(可以有聚合函数,必须有order by)

range between 参数1 and 参数2
在原来的窗口范围内再进行选定

select q.realname,q.groupno,q.age,
       max(q.age) over(partition by q.groupno order by q.agerange between 参数1 and 参数2) 
from qqinfo q;

参数可以替换为以下:
unbounded preceding 组内首行
current row 当前行
unbounded following 组内末行
1 preceding 组内当前行前面1
1 following 组内当前行后面1
range 值比较--不了解
rows 行比较--不了解

7 其他

7.1 查询中的集合操作

两个集合间   
1)并 
    union (自带去重效果)
          (去重必带排序)
          oracle中去重和排序都非常慢
    union all (不去除重复内容)
              (执行速度更快)
例:
  select s.name from student s
  union
  select e.name from emp e
此外要注意多列同时运算的情况:
  对应列如s.age和e.age的属性和类型要一致
  select s.names.age from student s
  union
  select e.name,e.age from emp e
2)交( intersect 
3)差  minus 

7.2 case when

查询结果根据类别不同,查询方式随之不同
select s.name--逗号不能少
       case--开始
       when s.gender=1 then '男生'
       when s.gender= then '女生'--也可以只有一个 when then语句 
       else '其他'
       end--结束
from student s;

需要注意的是 case when 是顺序执行的
如果前面的条件包含了后面的条件
则后面的条件
如:
  select s.name,
         case
         when s.score>60 then '及格'
         when s.score>80 then ''
         else '不及格'
         end
  from student s;
  --则60分以上的都是及格,即使是100也是及格而不是

 case when 中的条件是确定值(即用等号=)时
    可等价于decode如
    select s.name,--逗号不能少
       decode(s.gendere,1,'男生',,'女生','其他')
    from student s;

7.3 行列相互转换

(1)行转列【常面】

将同一列内容分成多列
 group by
 case when
 聚合函数

例(查询班内全部人数,男生数量,女生数量):
  select count(1),
         count(case when s.gender=1 then '是' end) nans,
         count(case when s.gender= then '是' end) nvs
  from student s;
例(查询各组全部人数,男生数量,女生数量):
  select s.groupno
         count(1),
         count(case when s.gender=1 then '是' end) nans,
         count(case when s.gender= then '是' end) nvs
  from student s
  group by s.groupno;


(2)列转行【常面】

将不同列的内容汇总到同一列
 union[all](并-操作)

select name,'男' gender from stul where nans=1
union
select name,'女' from stu1 where nvs=1;




二、数据类型

1数字

整型(整数型)int/integer
浮点型(小数)float
oracle中常用NUMBER(包括以上两类)定义数据的数字类型

####
定义数据类型 number102)指定义一个长度为10精度为2的数字类型
键入 1234567890 报错
键入 1234  1234.00
键入 .123456788890 .12
--思考:如果把该类型转换成字符串,那么会不会存在看不见的空格?like关键字能使用吗?(目前不知道怎么转换-可以用to_char转换)

####
to_number把字符串变成数字
注意:
select *
from student s 
where from s.gender=1;--隐式类型转换
等同于
select *
from student s 
where from to_number(s.gender)=1;
--等号两边类型不一致的时,会将左边转换成右边类型,从而报错ORA-01722

1.1四则运算(加减乘除)

select * from dual;--dual表用于进行试验性操作,得一行一列的结果
select 1/3 from dual;--得3.333333333....

1.2取余(mod函数)

select mod(10,3) from dual;--得1

1.3截取(trunc函数,round函数-四舍五入-常用)

select trunc(1.2345) from dual;--得1
select trunc(1.2345,3)from dual;--得1.234
select trunc(125341.2345,-3)from dual;--得120000
 
select round(1.2345) from dual;--得1
select round(1.2345,3)from dual;--得1.235 
select round(125341.2345,-3)from dual;--得130000
--把小数换成分数一样可以运行

特别注意:
|随机返回1-10的整数
select trunc(dbms_random.value(1,11)) from dual;
select round(dbms_random.value(1,10)) from dual;--但是此处1和10的几率小于其他数

1.4值(abs函数)

select abs(-1) from dual;1

1.5乘方(power函数)

select power(3,4) from dual;--3的4次方

1.6平方根(sqrt函数)

select sqrt(4) from dual;--得2(注意和数学运算有所区别)

select power(4,1/2) from dual;--得2(也可)

1.7向上取整(ceil函数)

select ceil(1.2) from dual;--得2

1.8向下取整(floor函数)

select floor(1.2) from dual;--得1

1.9伪随机数(dbms_random.value函数-在oracle中很少用)

select dbms_random.value() from dual;
--得到值在[0,1)之间,没有括号也可以
select dbms_random.value(1,5) from dual;
--得到在[1,5)之间

1.10函数组合用法

例:随机得到1-10的整数
select trunc(dbms_random.value(1,11)) from dual;
select round(dbms_random.value(1,10))from dual;

1.11其他函数(不常用)

exp(n)返回e的n次幂
sin(n)返回n的正弦值n为弧度
cos(n)返回n的余弦值n为弧度
log(n1n2)返回以n1为底n2的对数
sign(n)n为负则返回-1,为正返回1,为返回


2字符串

char()固定长度字符串, varchar()可变长度字符串
当用通配符‘%’检索时
'6,7,8' char(10) 实际上8后面还存在空格 '%,8' 查询不出来
'6,7,8' varchar(10) 此处8后面就不存在空格 '%,8' 因此可以查询出来--你以为是小问题,其实是大问题,不能不求甚解

select '8'+5 from dual;--字符串类型的数字和数字类型的数字可以进行运算

2.1字符串连接(显示更有意义的信息)

连接字符串时,如果在字符串中加入数值,那么可以直接指定数字值;
如果在字符串中加入字符值或者日起值,那么必须用单引号引住
1)用||连接字符串
select ename|| ' ''s job '||job from emp;--注意 ''两个单引号等同于一个单引号字符
select 1||2||3||4||5 from dual;--也可以连接数字变成字符串

2 用函数CONCAT连接字符(只了解即可)
select concat(concat(ename,'''s salary is'),sal)from emp;

|
select * from test1 where ','||cs||',' like'%,8,%';
--可查找列中仅数字8但不要28,88等,如找到‘1,3,8’,‘4,566,7,8’,‘8,95’,‘7,8,88,9’

2.2字符串长度

select s.name,length(s.name) from student s;

2.3截取字符串

select 'zhangzhang',substr('zhangzhang',6,2) from dual;--从第六位开始截取2个字符得'zh'
select 'zhangzhang',substr('zhangzhang',6) from dual;--从第六位开始截取剩余的全部字符得'zhang'
select 'zhangzhang',substr('zhangzhang',-3) from dual;--从倒数第三位开始截取剩余的全部字符得'ang'

2.4替换字符串

select 
replace('zhangjianjian','jianjian','hhh')
from dual;
--得zhanghhh
--若第三个参数为空则替换为空

2.5查询字符串的位置

语法:instr(s1,s2[,i][,j])
     s2在s1中从第i个字符第j次出现的位置i,j默认是1
select 
instr('zhangjianjian','an',5,2)
from dual;
--返回12
select 
instr('zhangjianjian','an',1,2)
from dual;    
--返回8

####
select 
instr('zhangjianjian','an')
from dual;--查询个‘an’的位置

select 
instr('zhangjianjian','an',4)
from dual;--查询从第四位开始往后的个‘an’的位置,返回8

select 
instr('zhangjianjian','an',3)
from dual;--注意:返回3

select 
instr('zhangjianjian','an',-1)
from dual;
--得12
--当第三个参数为负数时,搜索将从右向左进行,但是返回位置还是从左向右计算的

2.6其他函数

1)大小写转换
select upper('zhangJIANJINA')
from dual;
select lower('zhangJIANJINA')
from dual;


2)去除空格
select trim('    zhangjianjian    ')
from dual;
--去左边
select ltrim('    zhangjianjian    ')
from dual;
--去两边
select rtrim('    zhangjianjian    ')
from dual;
--去两边


3)填充
select lpad('jian',10,'a')
from dual;
--左填充,使字符串长度达到10,不足的用第三个参数补齐,没有第三个参数则用空格补齐
--rpad右填充
--如果字符大于二个参数要求则从左到右截取第二个参数要求的长度



####
4)返回字符的ASCII值、返回ASCII值的字符串
select ascii('\n'),ascii('A'),ascii('a')
from dual;
--得
ASCII('\N') ASCII('A')  ASCII('A')
92          65          97
--换行键是 10
--92是 \

select chr(92),chr(65),chr(97)
from dual;
--得
CHR(92) CHR(65) CHR(97)
\       A        a


5)字符串每个单词首字母大写(INITCAP)(用空格、标点符号、控制字符来区分单词)
select initcap('zhang jian jian')
from dual;

3日期

(date,timestamp)

3.1日期转字符串

select to_char(sysdate,'yyyy/mm/dd hh[24]:mi:ss q day')
from dual;
--分别对应年、月、日、时(如果是hh24则是24小时制,否则默认12小时制)、分、秒、季度、星期
--顺序可以调整
--sysdate是关键字,表示当前服务器的时间(非网络时间)
--中间的符号和空格可以用其他符号替换,但是目前不清楚怎么用汉字或者字母替换
--此外注意如果to_char('mm')只能知道是哪个月,不能知道是哪年哪月

3.2字符串转日期

select to_date('0101','mmdd') 
from dual;
--不带年份则默认为当年
--可依照日期转字符串反向思考
####
注意:
--如果条件添加为时间等于时间,应将时间转换成字符串
select * 
from student s
where to_char(s.birthday,'yyyymmdd')='20220101';
--查询2022年1月1日出生的人
 
--如果把字符串变成时间会导致不
select * 
from student s
where to_date('20220101','yyyymmdd')=s.birthday;
--因为日期实际上有很多位,包括时分秒等,所以无法相等

3.3日期的加减(日期格式之间不能相加)

select sysdate+.5,sysdate-1 
from dual;
--加半天,减一天
--两个时间只能想减,不能相加,得天数

3.4日期截取

1trunc函数(得到个时刻)
select trunc(sysdate)
from dual;
--得到当天凌晨的时间
--截取后仍然是date格式
select turnc(sysdate,'mm')
from dual;
--yyyy截取到当年个时刻
--mm截取到当月第个一时刻
--dd截取到当日个时刻
--day截取到当周个时刻
--(Oracle按照美国的习惯,每周的天为周日,如果得到周一则需要后+1,trunc(sysdate,'day')+1)
--其他类推

3.5当月后一天

select last_day(sysdate) 
from dual;
--返回当月的后一天的同一时刻,如1.31,2.28等(注意不是准点时刻)
####
--如果要上个月的后一天,建议先查找上个月,然后再查找后一天
select last_day(add_months(sysdate,-1))
from dual;

3.6月份相加减

select add_months(sysdate,1),add_months(sysdate,-2)
from dual;

3.7其他函数

1)两个时间相差的月数
select months_between(add_months(sysdate,5),sysdate)
from dual;
--前一个减去后一个时间相差的月份
2)从某时刻开始算的下一个周几
select next_day(sysdate,1)
from dual;
--1代表星期天
--注意:如果今天是周三,那下一个周四是明天

####
3)时区
new_time(d1,t1,t2)
--d1是日期类型
--返回t1时区的d1时间在t2时区的时间

三、DML

DML数据库操作语言
注意:多台电脑一起操作要及时提交或回滚
     不能挂起
     否则其他人无法操作
     PL/SQL Developer界面上面有绿色(提交)和红色(回滚)的类箭头符号
有人未提交或回滚导致无法操作的处理:
     PL/SQL Developer界面
     -工具-回话-点击下面窗口-锁定
     -点击上方窗口中的数据行找到下方窗口有数据的行
     -右键-关掉
     即可

select s.*,rowid 
from student s;
-- 可以在PL/SQL Developer中直接修改表数据

select * 
from V$NLS_PARAMETERS;
-- 查询表的部分数据类型的形式


1 插入数据

insert语句
注意:
①为数字列增加数据时,可以直接提供数字值或者用单引号引住
②为字符列或日期列增加数据时必须用单引号引住
③增加数据列时,数据必须满足约束条件并且必须为主键列和NOT NULL列提供数据
④增加数据时,数据必须与列的个数和顺序保持一致

1.1 直接插入数据

insert into 
table_name(column_name1,column_name2···)
values(express1,express2···)
--如果不指定列名则需要为每一列都提供数据且顺序必须与表列顺序完全一致(不推荐)

###知识例
insert into
emp(empno,ename,job,hiredatesal)
values(1234,'MARY','CLERK',to_date('1999-01-01','YYYY-MM-DD'),default);
--日期值的处理
--指定 DEFAULT时,如果存在默认值则使用默认值,否则自动使用NULL

1.2 子查询插入数据

insert into
table_name(column_name1,column_name2,column_3···)
selectSubquery--任何合法的select语句
--可用于批量插入数据

###仅例
insert into
jobs_temp
select * from jobs where jobs.max_salary>10000;


2 修改数据

2.1直接修改

update table_name
set cloumn_name1=express1,cloumn_name2=express2···--express也可以是select语句
[where condition]
--只有符合条件的记录才会被修改
--如果没有where子句则修改全部记录
--修改数据为空 where col=''(不是 is null)

###知识例
update cs
set job='aaaa',mgr=1234,hiredate=to_date('19990101','yyyymmdd'),deptno=default
where empno=9999;
--日期处理
--default应用(如果存在默认值则使用默认值修改数据,否则使用NULL)


2.2 子查询更新

--把emp表中工资小于3000的员工工资调整为管理者的平均水平
update emp
set sal=(select avg(sal)
         from emp 
         where job='MANAGER')
where sal<2000; 


3 删除数据

3.1 delete

delete from 
table_name
where condition;
--无where子句则删除表的全部数据
--可以用ROLLBACK回滚


3.2 truncate 清空表(格式化)

truncate table table_name;
--删除表的全部内容
--修改了表结构 属于DDL语句
--无法回滚
--REUSE STORAGE删除记录仍保存占用的空间
--DROP STORAGE删除记录立刻回收空间
--大型数据表的全部数据删除应该用TRUNCATE
--用DELETE会导致回滚段磁盘耗光,ORACLE数据库挂起

3.3 delete和truncate区别【重要】

delete 删除过程慢,容易恢复(更安全),DML,不影响高水位线
truncate 删除过程快,很难恢复,DDL,高水位线归零

高水位线:表中历史插入数据量的大高度

delete 删除后的数据恢复【了解】
    闪回: alter table able_name enable row movement;--重置行
          flashback table table_name to timestamp to timestamp('20220220 10:10:10','yyyymmdd hh24:mi:ss')


4 MERGE【记录】

结合insertupdate
如果目标表有数据则更新数据为源表的数据
没有数据则将源表中对应数据插入目标表

语法:
merge into tbDst(目标表)
using tbSrc(源表)/select子句
on ________  (源表和目标表关联关系)
when matched then --如果匹配到
  update set tbDst.col=tbSrc.col --则更新
when not matched then--如果匹配不到
  insert (tbDst.cols....) values (tbSrc.cols)--则更新(此处不必是表中的全部列)


四、DDL

数据定义语言:定义、修改或删除数据库对象

数据库对象:表,索引,约束,同义词,数据链,表空间,作业,序列,视图,物化视图,函数,过程,包,触发器

本部分的操作在PL/SQL Developer中都可 右键表名-编辑 进行操作

1 表

1.1 创建表

(1)直接创建

【语法】
create table
new_table_name(
col_name1 type1,
col_name2 type2,
···
col_namen typen,
);


####
create table gamerole(
id     varchar2(32),
name   varchar2(50),
lev    number,
zhiye  varchar2(10),
gold   number
);

注意:列名不可以以数字或下划线开头

(2)子查询创建

【语法】
create table
new_table_name
as select子句 [where 1=]
--有 where 1=0则查询无果,只备份表结构

1.2 修改表

PL/SQL Developer 中右键表名-编辑-即可修改
右下角可看对应SQL语句 


(1)修改表名

alter table 原表名 
rename to 新表名;

(2)添加/修改表注释

comment on 
table 表名 is '注释';

(3)修改列名

alter table tbName 
rename column 原列名 to 新列名;

(4)添加列

alter table tbNmae 
add 列名 数据类型;

(5)删除列

alter table tbName 
drop column 列名;

(6)修改列类型(要求该列数据为空)

alter table tbName 
modify 列名 修改后的类型;
--如果该列数据不为空,则可能无法修改

(7)添加/修改列注释

comment on 
column 表名.列名 is '注释';
--注意是点,不是逗号

1.3 删除表

drop table tbName;
--难以恢复,使用时应当注意


2 约束

给数据添加限制条件
constraint


2.1 主键约束

使得主键列数据 不可重复,不可为空
一个表只能有一个主键约束

alter table tbName 
add constraint 主键名 
primary key (主键列);
--此处主键名是自定义的一个名称
--此处主键列指需要定义成主键列的一列或多列
--联合主键(即多列)(基本不用):性即保证多列不是完全一致
--建表直接添加主键约束 在列属性后加上 primary key即可

###仅例
alter table daily
add constraint pk_daily_dayno--主键名示例
primary key (dayno);

2.2 约束

使得约束列数据 不可重复,可以为空
一个表可以有多个约束

alter table tbName 
add constraint 约束名 
unique (col_name);

2.3 检查约束(基本不用)

alter table tbName 
add constraint 约束名 
check (限制条件);
--可以添加任意约束条件

####
alter table GAMEROLE 
add constraint ck_game_lev 
check (lev between  and 30);

2.4 非空约束

alter table tbName 
modify 列名 [not] null;
--加 not 则不可为空

####仅例
alter table daily
add constraint check_name
check (length(things)>5);
--条件可以直接使用函数

2.5 默认值

alter table tbName 
modify 列名 default 默认值;
--具体用处参考 用 DEFAULT插入数据
####
alter table GAMEROLE 
modify gold default ;

2.6 外键(强烈不推荐写)

alter table tbName 
add constraint 约束名 
foreign key (外键列) 
references 主表 (主键) 
[on delete cascade];
--添加 on delete cascade 
  删除主表数据同时将子表依赖于该主表数据的子数据删掉(不建议写)
--不添加 on delete cascade 
  会导致 ERROR:ORA-02292违反完整约束条件
  无法删除有外键依赖的数据

3 索引

相当于书的目录
一个表比作一本书,一条记录比作一页,rowid相当于页码

当从表中查找记录时,先从索引搜索该关键词,找到对应的rowid,然后根据rowid进行查询


3.1 b_tree 索引

即普通的索引[normal]
适用于 该列基数比较大 可取的值特别多 的情况
不记录空值
如果对索引列进行函数运算,索引失效

create index 索引名 
on 表名 (列名...);

####
create index idx_stu_name 
on STUDENT (name);
create index idx_stu_name 
on STUDENT (name,age);--复合索引

####不记录空值-
select * from student 
where name is null;
--这条sql不会走索引

####函数运算,索引失效-
select * from student 
where substr(name,1,1) = '张';
--这条sql不会走索引

####索引样子-
假设在name列建立索引,那么索引样子如下
name1   AAAVbFAAEAAAA/eAAA
name2   AAAVbFAAEAAAA/eAAB
name3   AAAVbFAAEAAAA/eAAC
name4   AAAVbFAAEAAAA/eAAD
name5   AAAVbFAAEAAAA/eAAE
name6   AAAVbFAAEAAAA/eAAF
name7   AAAVbFAAEAAAA/eAAG
name8   AAAVbFAAEAAAA/eAAH


3.2 索引

创建主键或约束时
自动创建同名的索引
索引的值是的


3.3 位图索引

适用于 该列基数比较小 可取的值比较少 重复值多 的情况
记录空值
create bitmap index 索引名 
on 表名 (列名...);

####空值可走索引-
create bitmap index IDX_STU_NAME 
on STUDENT (gender);
select * from student 
where name is null--可以走索引

3.4 函数索引

create  index 索引名 
on 表名 (函数操作);

####
create index IDX_STU_NAME 
on STUDENT (SUBSTR(NAME,1,1));
select * from student 
where substr(name,1,1) = '张';--走索引

3.5 是否走索引的判断

PL/SQL中按F5打开解释执行窗口
可以通过查看是否有 index
判断sql语句是否走索引

注意:需要有where子句使用索引条件才能走索引
###理解例
假如:emp表中ename为索引列
     select empno from emp;
     --不走索引
     select ename from emp 
     where empno='7521';
     --走索引

4 视图

(view)

【语法】
create or 
replace view 视图名
as select 子句;
--没有视图则创建 有就替代
--节省空间(实际上是虚拟表 不保存数据 不占用空间)
--实时性(视图数据随源表数据变化而变化)
--保护数据(一般不能修改数据)
--清晰明了(节省代码量)
--查询速度慢(查询视图就相当于查询视图中的sql语句))
用途:简化表连接

###理解例
create or replace 
view v_stu
as select s.groupno,count(1) rs 
   from student s 
   group by s.groupno;


5 物化视图 【记录】

(materialized view)常用于业务系统

--物化视图是保存数据的,查询速度和表一样
--数据不是实时的,要定期更新
--用途:常用于业务系统

物化视图数据更新
1)自动更新,设置一个时间点【了解】
2)手动更新
    BEGIN
       dbms_mview.refresh(list             => '视图名',
                      method               => 'fast', -- 增量刷新
                      refresh_after_errors => TRUE);
    END;


6 序列

sequence

--用途:产生自增序列号(流水号)的对象

【语法】
create sequence 序列名
minvalue 小值
maxvalue 大值
start with 下一个值
increment by 自增量;

###知识例
create sequence xlm
minvalue 1
maxvalue 9999
start with 20
increment by 15;
--建序列
select xlm.nextval from dual;
--下一列
--每一次用netval,当前值就会+15
select xlm.currval from dual;
--当前列

###展示例
insert into 
stu1(name,birthday,age) 
values ('sss',sysdate,seq_stu.nextval);

7 同义词

Synonyms

--用途:给对象取别名
	   例;如给表取表别名
	      用表别名修改内容
	      则源表也被修改

【语法】
create or replace 
synonym 同义词名 
for 用户名.原对象名;


###展示例
create or replace 
synonym stu 
for scoTT.studeNT;

8 表空间【重要】

tablespace

--既是物理结构又是逻辑结构

【语法】
CREATE TABLESPACE 表空间名称 
DATAFILE 数据文件路径(.DBF文件路径 
SIZE 表空间的初始值 
AUTOEXTEND ON 
NEXT 自动扩展大小 
MAXSIZE UNLIMITED|大存储大小;
--创建表空间
--‘|’表示‘或’
--UNLIMITED表示没有上限

【语法】
create table EMP
(
col1 tapy1,
    ...
) 
tablespace tbs_202202
--建表选择表空间 tbs_202202(此处可更改)
  如果不选,放入默认表空间users

【语法】
create temporary tablespace
--创建临时表空间
  用途:存放临时数据(如 排序数据、临时表的数据)
--在创建表空间语法中添加关键字 temporary 即可

【语法】【了解】
select * 
from DBA_FREE_SPACE; 

###展示例
CREATE TABLESPACE tbs_202202
DATAFILE 'd:/app/scl/oradata/orcl/tbs_202202_01.dbf',
         'd:/app/scl/oradata/orcl/tbs_202202_02.dbf'
SIZE 4000M
AUTOEXTEND ON 
NEXT 100M
MAXSIZE UNLIMITED;


9 数据链【禁用】

database link

【语法】
create database link 数据链名
connect to 用户名 identified by 密码
using 'ip/实例名';
--实例名指数据库名 如:orcl
--此处‘/’是字符,非‘或’

create database link db242
connect to scott identified by scott
using '192.168.1.242/orcl';

select * from emp@db242 e join dept d on e.deptno=d.deptno;*

10 用户

user

create user 用户名
       identified by '密码'
--创建用户


11 删除对象

drop 对象关键字 对象名称;

###展示例
drop table 表名称;
drop view 视图名称;
等等类似;


五、TCL

1 事务

事务:完成一项工作的所有步骤的和
oracle数据库中的事务
    只要是还未执行提交或回滚
    就可以看做一个事务(该事务未结束)

事务控制语言:控制事务提交或回滚
--commit(提交对数据库的更改) rollback(取消对数据库的更改) savepoint(设置保存点)

1.1 特征

(1)原子性

事务是一个整体的工作单元
要么全部执行 要么全部取消
某一步执行失败 则全部回滚

(2)一致性

当前事务在进行数据修改时
其他事务只能查看修改之前的状态
等到当前事务执行结束(提交后)
数据的修改才能被看到

(3)隔离性

当前事务在进行数据修改时
其他事务只能查看修改之前的状态
等到当前事务执行结束(提交后)
数据的修改才能被看到

(4)持久性

事务提交后
所做的修改就会保存
直到下一次事务来改变它


1.2 隔离级别

1 Serializable (串行化)
     可避免脏读、不可重复读、幻读的发生

2 Repeatable read (可重复读)
     可避免脏读、不可重复读的发生

3 Read committed (读已提交)
     可避免脏读的发生(oracle默认

4 Read uncommitted (读未提交)
     低级别,任何情况都无法保证


1.3 隔离级别不同导致的问题

(1)脏读

在一个事务处理过程里读取了另一个未提交的事务中的数据

(2)不可重复读

例如:
    事务T1在读取某一数据
    而事务T2立马修改了这个数据并且提交事务给数据库
    事务T1再次读取该数据就得到了不同的结果
    发生不可重复读
    
解决办法:oracle中可以通过forupdate解决
        select * 
        from emp 
        for update;--锁定【基本没人用】

(3)虚读(幻读)

--幻读是事务非独立执行时发生的一种现象

例如:
    事务T1对一个表中所有的行的某个数据项做了从1”修改为“2”的操作
    这时事务T2又对这个表中插入了一行数据项
    而这个数据项的数值还是为“1”并且提交给数据库
    而操作事务T1的用户如果再查看刚刚修改的数据
    会发现还有一行没有修改,其实这行是从事务T2中添加的
    就好像产生幻觉一样 这就是发生了幻读

--解决办法:锁整个表


2 TCL语句

直接输入运行即可

commit;
--提交

rollback;
--回滚


六、DCL

权限控制语言-grant(授予用户或者角色权限) revoke(收回用户或者角色权限)

1 角色权限

(1)赋予

【语法】
grant 角色权限关键字
to 用户名;

--connect:拥有创建会话的权限
--resource:使用资源的权限(可以创建数据库对象)
--dba:管理员权限(几乎所有权限)

###展示例
grant connect
to scott;

(2)收回

【语法】
revoke 角色权限关键字
from 用户名;

2 赋予对象权限【重要】

(1)赋予

【语法】
grant 操作
on 对象名
to 用户名;
--操作指 select insert update delete ···( all代指所有权限)
--可以一次赋予多个权限(用逗号隔开)
--如果角色权限为dba则已有几乎全部的对象权限

###展示例
grant select, insert 
on STUDENT 
to zhangsan;

(2)收回

【语法】
revoke 操作  
on 对象名 
from 用户名;


###展示例
revoke debug 
on STUDENT 
from ZHANGSAN;


3 系统权限

一些比普通账号高的特殊权限

grant drop user 
to ZHANGSAN;
--赋予删除账号的权限

revoke UNLIMITED TABLESPACE 
from ZHANGSAN;
--收回表空间任意扩展的权限

七、其他

1 数据字典

字典:字及对字的解释
数据字典:数据及对数据的解释

(1)系统的数据字典

--主要是数据库对象及对该对象的解释
--是视图 非实际表

user_tables--当前用户下所有表【重要】
dab_tables--数据库管理员管理的表
all_tables--该用户可以看到的所有表
user_tab_columns--当前用户下所有列【重要】

###展示例
select * 
from user_tables t 
where t.OWNER='ZHANGSAN';
--当前账号下所有表

select * 
from dba_tables;

select *
from all_tables t 
where t.OWNER='ZHANGSAN';
--是该用户可以看到的所有表

select * 
from user_tab_columns t 
where t.TABLE_NAME='EMP';

select * 
from user_views;

select * 
from user_indexes;

select * 
from user_tablespaces;

select * 
from user_synonyms;



(2)用户的数据字典(码值表)

是用户自建的一个表
一般有三列
type字典类别key实际值value对应含义


2 sqlplus

打开命令行窗口输入以下命令

sqlplus scott/scott;
--登录本机的scott账号

sqlplus / as sysdba;
--登录本机的sys账号

sqlplus scott/scott@192.168.1.241/orcl;
--  登录远程数据库
-- ip+实例名

sqlplus scott/scott@241;
-- 登录远程也可以直接跟tns名
-- tns指oracle自带的Net Mangement中添加的 服务命名

sqlplus -S scott/scott@241;
--静默登录,不显示前面的一些信息

进入后直接在 SQL> 后输入sql语句(一定要有分号)或命令即可

desc emp;
--打印emp的列的信息;
exit;
--退出sqlplus;

登录dba账号后可以执行下列操作
shutdown immediate;
--关闭数据库
startup;
--关闭数据库

3 范式

(1)范式 1NF

列不可再分

表中如果有一对多关系,要添加中间表

反例:student的home列


2.第二范式 2NF

要求表中的列必须和表有关系,列必须依赖主键

反例:在student添加一列天气


3.第三范式 3NF

要求表中列必须直接依赖主键,而不是其他列

反例:在student表添加一列dormno,因为dormno直接依赖dormid

有时候为了加快查询速度,违反第三范式(增加冗余)也是一种方式


补充信息

1 拟ID数据

insert into building(id) values(sys_guid());
--sys_guid()被成为全球值,每运行一次数据库就会发生变化,可以用来作为主键ID

2 导入dmp数据库数据

工具-导入表-右下角选择-文件-导入-日志
日志:出现只有DBA才能导入DBA错误
登陆sys-sys-sysdba
在SQL界面输入grant dba to scott
在登陆sccot
重新导入即可

##


分享好友

分享这个小栈给你的朋友们,一起进步吧。

数据库开发
创建时间:2020-06-17 14:33:07
数据库开发是数据库管理系统(DBMS)和数据库应用软件设计研发的总称,主要是数据运维、参与数据库生产环境的问题优化和解决等方面的事宜
展开
订阅须知

• 所有用户可根据关注领域订阅专区或所有专区

• 付费订阅:虚拟交易,一经交易不退款;若特殊情况,可3日内客服咨询

• 专区发布评论属默认订阅所评论专区(除付费小栈外)

技术专家

查看更多
  • 小雨滴
    专家
戳我,来吐槽~