[数据库汇总]-- sql 的基本知识

Oracle


Person p1 = new Person("程程",18,"我买了一个礼物");
Person p2 = new Person("希希",19,"媳妇儿,生活费没了");
**字符流:
文件:person.txt
程程-18-我买了一个礼物
希希-19-媳妇儿,生活费没了
张三-asd-18
存在的问题:
没有数据类型支持:
安全:
单用户操作:没有多用户支持
没有数据备份/恢复机制
。。。


数据库


是一个软件:存储数据
**物理上文件存储
**逻辑上是以表存储(Table)
表:行|列|表结构

关系型数据库
Oracle Oracle(收费)
Mysql Mysql AB
SQL Server微软

NoSQL数据库
mongodb 文档型数据库

内存型数据库
Redis
安装Oracle:
OracleXE 10g(快捷版)
安装:开发软件安装英文目录
①http:端口:8080
1521
②:查看window服务:
运行---services.msc--
OracleServiceXE Oracle服务器的核心服务
OracleXETNSListener监听1521端口号客户端连接
Oracle服务器
Oracle客户端
**命令:sqlplus sql
isqlplus:
访问:http://127.0.0.1:8080/apex
 http://localhost:8080/apex
**查看表结构  
desc 表名
sqlplus
运行--sqlplus--用户名+密码
**win+R
退出:exit
sqldeveloper---oracle官方
plsql developer
-----------------------


数据库相关概念


表 Table数据库存储的单位
行 row数据库表中的一条数据
列 column(字段),数据在该列代表意义
主键 primary key唯一标识表中的一条数据
外键 foreign key 关联不同表的数据

SQL 命令: Structured Query Language结构化查询语言
SQLPLUS 命令:oracle提供扩展sqlplus: desc 表名


简单查询:
from 指定查询数据来源的表
select 指定查询的列(只有写select后的信息才会显示)
书写:select 列名,列名... from 表名;
1.查询部分列
*select 部分列名 from 表名
--查询员工工号,名字,工资
select employee_id,first_name,salaryfrom employees;
2.查询所有列
--查询员工的全部信息
select employee_id,first_name,salary....(所有列)   from employees;
select  *  from employees;
**开发优先选择第一种
3.运算:+  -   *   /    
--查询员工工号,名字,年薪
select employee_id,first_name,salary*12   from employees;
**每条数据的salary都要做运算
4.给查询的列起别名
列名 [as] 别名(as可以省略)
--查询工号,名字,年薪(显示列名:工号,名字,年薪)
select employee_id as 工号,first_name as 名字,salary*12 as 年薪  from employees;
--年薪  --》 年   薪
select employee_id as 工号,first_name as 名字,salary*12 as 年  薪  from employees;
**当别名中包含空格或者特殊符号时:
列名 as "别名"
5.字符串拼接:字符串数据   'str'
列 || 列
--查询员工的工号,姓名,工资
select employee_id 工号,first_name || '.' || last_name 姓名,salary 月薪 from employees;
6.数据去重 distinct
书写:select distinct 列名... from 表名
--查询所有的经理工号
select manager_id from employees;(会有重复数据)
select distinct manager_id from employees;
**distinct去除重复数据
distinct后所有列全部相同才算重复数据
排序:
order by 排序列名 asc|desc
asc:升序
desc:降序
**默认不写asc|desc为升序
**作用于关键字之前的列名
结构:
select  ...  from ... order by 列  asc|desc
---查询员工工号,工资,入职日期,按照工资降序排序
select  employee_id,salary,hire_date  from employees order by salary desc;
---查询员工号,工资,入职日期,按照工资降序, 按照工号升序
select employee_id,salary,hire_date from employees 
order by salary desc,employee_id asc;
条件查询:
where 条件表达式
结构:
select ... from ... where 条件 order by 列 desc|asc;
1.等值查询
--查询工号,工资,名字,工资等于10000;
select employee_id,salary,first_name from employees where salary = 10000; 
2.不等值查询
> >=  < <=   !=<>(不等号)
--查询员工号,名字,工资,条件:工资大于10000;
select employee_id,first_name,salary from employees where salary>10000;
3.多条件查询 and   or  
--查询员工号,名字,工资 条件:工资为6000~10000之间
select employee_id,first_name,salary from employees where salary>6000  and  salary <10000;
4. null值处理:
--查询员工工号,工资,提成比率(佣金比率)条件:提成为空
**查询没有提成的员工信息
select employee_id,salary,commission_pct from employees where commission_pct = null;(×)
select employee_id,salary,commission_pct from employees where 
commission_pct is null;
5.模糊查询
like
% 0~n占位符
_ 1个占位符
--查询员工名字已K开头的员工信息
select * from employees where first_name like 'K%';
--查询员工名字长度为4的员工信息
select * from employees where first_name like '____';

--思考:查询员工的工号,名字,佣金比率:按照佣金比率降序排序?
select employee_id,first_name,commission_pct from employees
order by commission_pct desc;
**排序时,默认将null作为最大值
select employee_id,first_name,commission_pct from employees
order by commission_pct desc nulls last;
补充:nulls last 将条件值为null的数据放在最后;
6. 区间查询
between min值 and max值
---查询员工号,名字,工资 条件:工资为8000~10000之间(包含8000,10000)
select employee_id,first_name,salary from employees
where salary >=8000 and salary <=10000;

select employee_id,first_name,salary from employees
where salary between 8000 and 10000;
**查询结果包含条件边界
7.枚举值查询
in (值1,值2,值3)
--查询员工号,名字,部门id 条件:部门id为70,90,100
select employee_id,first_name,department_id from employees 
where department_id = 70 or department_id = 90 or department_id = 100;

select employee_id,first_name,department_id from employees 
where department_id in (70,90,100);

case-when
作用:对查询数据进行条件判断,根据不同的条件产生不同结果值
case 
when 条件  then  值
when 条件2 then 值2
when 条件3 then 值3
end
**生成一列值


--查询员工工号,名字,工资,级别;
级别:
salary>=10000 A
8000<=salary<10000B
6000<=salary<8000C
salary<6000 D

select employee_id,first_name,salary, 
case
when salary>=10000 then 'A'
when salary<10000 and salary>=8000 then 'B'
when salary<8000 and salary >=6000 then 'C'
else 'D'
end 级别
from employees;



补充:
SQLPLUS:
**命令没有分号结束
**通常可缩写
desc(describe)表名 查询表的结构
cl(clear) screen清屏
host 主机命令 host cls 清屏
(@)start 文件路径 执行硬盘上文件中的sql|sqlplus命令

修改密码:
cmd执行:
sqlplus /nolog
conn system as sysdba【回车】
【回车】
alter user system identified by 新密码;
=====================================================
SQL:操作数据库数据
select 列名,.,.. from 表名 where 条件 order by 列名 asc|desc


关键字:
sysdate 当前系统时间
--查询当前系统时间
select sysdate from;
**oracle中要求查询语句必须完整
dual 表   虚表
select * from dual;
**一行一列
作用:维护sql语句完整性
--查询当前系统时间
select sysdate from dual;

函数:
单行函数
**一条数据产生一条结果
字符串相关
length(str):获得字符串的字符长度
--‘abcdef’字符串的字符长度
select  length('abcdef')  from  dual;
--查询员工的工号,名字,名字长度
select  employee_id,first_name,length(first_name) from employees;
lengthb(str):获得字符串的字节长度
--'abcdef' 在oracle中的字节长度
select lengthb('abcdef') from dual;
--'呵呵'在oracle中的字节长度
select lengthb('呵呵') from dual;--6字节长度(UTF-8)
substr(str):对字符串进行截取
**oracle中下标是从1开始
**java中下标是从0开始
substr(str,n):
--对字符串'helloworld' 从n位开始截取
select substr('helloworld',4) from dual;
substr(str,start,end)
--对字符串'helloworld'从4开始截取2位;
select substr('helloworld',4,2) from dual;
concat(str1,str2):连接字符串等效于 || 
--将hello 和 world拼接成一个字符串
select  concat('hello','world') from dual;
--查询员工工号,姓名
select employee_id,concat(first_name,last_name) from employees;

数字相关
mod(num,n):用num对n取模相当于java % 
--数字123对4取模
select mod(123,4) from dual;
--查询员工工号为偶数的员工信息
select * from employees where mod(employee_id,2)=0;
round(num,le):对num取约数,保留le个小数位(四舍五入)
--对12.345取约数,保留2位
select round(12.345,2) from dual;
trunc(num,le):对num截取,保留le位小数(直接截取)
--对12.345截取,保留2位
select trunc(12.345,2) from dual;


日期相关
add_months(date,n):在date的日期之上增加n个月(结果是日期)
--下个月的今天是什么日期
select add_months(sysdate,1) from dual;
--思考:今年1月31日的下个月的日期????
思路:sysdate--今年1月31---add_months
months_between(date1,date2):获得两个日期之间的月数(数字类型,结果会有小数)
**date1是大月份   date2 是小月份
--查询员工的工号,入职日期,入职月份
select  employee_id,hire_date,months_between(sysdate,hire_date)  from employees;
next_day(date,'星期的格式'):从date开始,获得下一个星期几的日期
--从今天开始,下一个星期二
select next_day(sysdate,'星期二') from dual;
--从今天开始,下一个星期一
select next_day(sysdate,'星期一') from dual;
last_day(date):获得date日期的本月的最后一天
--获得sysdate的last_day
select last_day(sysdate) from dual;
trunc(date,'日期格式'):对date日期进行截取。
日期格式:
年 yyyy
月 mm
日 dd
时 hhhh24(24制)
分 mi
秒 ss
星期 day
--对当前系统时间截取到月份
select trunc(sysdate,'mm') from dual;
**对sysdate截取到月份:保留月份,其余时间归零
--获得今年1月1日
select trunc(sysdate,'yyyy') from dual;
--获得今年1月31日
select last_day(trunc(sysdate,'yyyy')) from dual;
--获得今年1月31日下个月的日期
select add_months(last_day(trunc(sysdate,'yyyy')),1) from dual;

类型转换
字符串----日期
to_date(strdate,'日期格式'):将strdate字符串按照给定的日期格式转换成日期
--将字符串‘1997-9-9’转换成日期
select to_date('1997-9-9','yyyy-mm-dd') from dual;
**'9-9月-1997'不规范
日期---字符串
to_char(date,'日期格式'):将date日期按照指定的日期格式转换成字符串
--查看当前系统时间的详细信息:年月日时分秒
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual;
作用:
1.将日期全部格式化成字符串显示
2.获得日期的部分信息()
--查看1997年入职的员工信息
select * from employees where to_char(hire_date,'yyyy') = '1997';

--查询员工工号,名字,年收入(工资+提成)*12
select employee_id 工号,first_name 名字,(salary+salary*commission_pct)*12 年收入 from employees;---×
**当计算中含有null值,结果也为null
处理null的
nvl(值1,值2):当值1不为null,结果为值1,否则结果为值2
相当于java中的:值1!=null?值1:值2
--nvl(commission_pct,0);
修改:
select employee_id 工号,first_name 名字, (salary+salary*nvl(commission_pct,0))*12 年收入 from employees;

组函数


**组函数处理中忽略null值
一组数据产生一条结果

avg(列) 统计一组中列的平均值
sum(列) 统计一组数据中列的总和
max(列) ....最大值
min(列) ....最小值
--查询员工的平均工资:将全部数据作为一组
select avg(salary) 平均工资 from employees;
--查询员工的平均工资,最大工资,最小工资,总工资
select  avg(salary),max(salary),min(salary),sum(salary) from employees;

count(列):统计分组后数据的个数
--查询员工的个数
select count(employee_id) from employees;
select count(*) from employees;
--查询员工中有提成的员工个数
select count(commission_pct) from employees;
select count(*) from employees where commission_pct is not null;

--统计各个部门的员工个数
手工:
工号 名字部门id
100 chengcheng80
101 xixi90
102 shijian100
103 fujie80
104 wanglexiao100
1.确定分组依据 department_id
2.分组
100 chengcheng80|
103 fujie80|

101 xixi90|

102 shijian100|
104 wanglexiao100|
3.统计每组中员工的个数
分组:
**对满足where条件数据进行分组
group by 分组依据列
书写:select ... from ... where ... group by 分组依据 order by ...
1.确定分组依据
group by department_id
2.执行分组
3.组函数
select  department_id,count(employee_id)  from employees group by department_id;
--查询各个部门中的最高工资:
1.确定分组依据
group by department_id;
2.分组
3.组函数
select  department_id,max(salary) from employees group by department_id;

--查询70.80.100三个部门各个部门的员工人数
select  department_id,count(employee_id) from employees where department_id in (70,80,100) group by department_id;
**对满足where条件的数据进行分组
**先where过滤----group by分组
--思路:先分组--对分组后的数据过滤
select department_id,count(employee_id) from employees group by department_id having department_id in(70,80,100);

--求各个部门中员工人数大于5的部门的最高工资
select  department_id,max(salary)  from employees where count(employee_id)>5 group by department_id;--×
**1.where条件先与group by执行
2.分组之前的数据不能执行组函数
--对分组之后的数据进行条件判断
having:
对分组之后的数据进行过滤
select department_id,max(salary),count(employee_id)   from employees group by department_id having count(employee_id)>5;


having和where条件对比:
1.where在分组之前执行条件过滤
2.having是对分组之后的数据进行过滤
3.where和having都能满足需求:优先选择where

SQL:执行顺序:
书写:
select ... from 表名 where 条件 group by 分组依据 having 分组后条件 order by 列 asc|desc
执行:
from  确定数据来源的表
where 对数据(分组之前的数据) 进行条件过滤
group by 对满足where条件的数据进行分组
having 对分组后的数据进行过滤

select |最后执行
order by|



--补充:
select  employee_id,department_id,count(*),max(salary)  from employees group by department_id;
**数据一旦分组,最终查看的数据只能组函数或者分组依据列
只能select查看到组特性数据
规则:
分组:select 后面只能出现组函数,或者group by 后面的列名
=========================================================================
伪列:
不存在任何表中的列,
可以查询到
rowid:
是当前数据在硬盘(数据库)上的唯一标识;
rownum:
是对查询结果的标号,
**当数据满足查询条件,之后才会对数据添加rownum标号
--1.对查询到的数据赋值rownum标号
--2.只有当数据真正满足查询条件,才会将该rownum生效随着该数据放入查询结果中
--查询employees表中前10个员工的工号,名字,工资
select
employee_id,first_name,salary
from employees where rownum<=10;
--思考:
查询employees表中第11~20个员工工号,名字,工资
select
employee_id,first_name,salary
from employees where rownum >=11 and rownum <=20


【难点+重点】子查询
**对于查询需求中,无法通过一次查询获得结果
1.子查询的结果是 1行1列(单个值):将子查询结果作为条件判断
--查询工资为最高工资的员工信息
select * from employees where salary = max(salary);×
**where条件是在分组之前执行的
①查询最高工资
select max(salary) from employees;--最高工资  24000
②根据最高工资查询对应的员工信息
select * from employees where salary = 最高工资|24000;
③合并
select * from employees where salary = (select max(salary) from employees);
--查询工资大于平均工资的员工信息
①。查询平均工资
select avg(salary) from employees;
②.查询员工信息,条件salary>平均工资
select * from employees where salary>(平均工资)
③合并
select * from employees where salary>(select avg(salary) from employees);
2.子查询的结果是 n行1列(多个值):将子查询的结果参与in运算
--查询和姓‘King’在同一部门的员工信息
①查询 姓 'King'所在的部门
select department_id from employees where last_name = 'King';
②查询员工信息,条件:部门id是不是80,90中的一个
select * from employees where department_id in (80,90);
③合并
select * from employees where department_id in (select department_id from employees where last_name = 'King');
3.子查询的结果是 n行n列(一个表)
--查询工资最高的前10名员工信息
select * from employees
where rownum <=10
order by salary desc;--×
**where条件在order by之前执行
①先对原表数据排序
select * from employees order by salary desc;--临时表
②获得前10个员工信息
select * from (?) where rownum <=10;
③合并
select *
from (select * from employees order by salary desc)
where rownum <=10;
--应用:
分页查询:
--按照工资排序,查询工资处于第11名~第20名的员工信息(第二页/10)
1.排序
select * from employees order by salary desc;

**
select * from (select * from employees order by salary desc) 
where rownum between 11 and 20;--×
2.对排序后的表增加一列
select employee_id,first_name,salary,email,rownum rn
from (select * from employees order by salary desc);
3.对增加一列后的数据,判断rn列
select employee_id,first_name,salary,email,rn
from 
(select employee_id,first_name,salary,email,rownum rn
from (select * from employees order by salary desc))
where rn between 11 and 20;


****--查询员工的信息,具有本部门最高工资的员工信息(相关子查询)
select *
from employees as e
where salary =(select max(salary) from employees where department_id = e.department_id);
**1.在查询主查询中每条数据时,需要判断salary=本部门的最高工资
select * from employees where salary = 本部门最高工资
 2.用子查询查询本部门的最高工资
select max(salary) from employees where department_id = 主查询的部门id
非相关子查询:
先执行子查询,在执行主查询
相关子查询
子查询执行时,需要用到主查询中的某个值
主查询先执行,在查询每条数据时,进而去执行子查询




集合运算符:将查询结果做合并
union 对查询结果求并集
union all 对查询结果求全并集
minus 用第一次查询结果对第二次查询结果做差集
intersect 对两次查询结果做交集

--查询60,70部门的员工信息:员工工号,工资,部门id
select employee_id,salary,department_id
from employees 
where department_id in (60,70);
103 900060
104 600060
105 480060
106 480060
107 420060
204 1000070
--查询70,90部门的员工信息:工号,工资,部门Id
select employee_id,salary,department_id
from employees
where department_id in (70,90);
204 1000070
100 2400090
101 1700090
102 1700090

1.union
*将两次查询结果合并,并且保留相同的数据(相同数据只保留一个)
select employee_id,salary,department_id from employees where department_id in (60,70)

union

select employee_id,salary,department_id from employees where department_id in (70,90);
2.union all
*将两次查询结果和合并,保留全部的重复数据
select employee_id,salary,department_id from employees where department_id in (60,70)

union all

select employee_id,salary,department_id from employees where department_id in (70,90);

3.minus
*对查询结果作差集:去除第一次查询结果中在第二次查询结果存在的数据
select employee_id,salary,department_id from employees where department_id in (60,70)

minus

select employee_id,salary,department_id from employees where department_id in (70,90);
4.intersect 
*对两次查询结果求交集:保留重复数据(重复数据只保留一个)
select employee_id,salary,department_id from employees where department_id in (60,70)
intersect 
select employee_id,salary,department_id from employees where department_id in (70,90);
=================================================================

【重点】
表连接:
将2张甚至多张表连接成一张表,再查询
规则:表1 连接符 表2 on 连接条件
--查询员工工号,工资,部门名称
**查询的内容来源于两张表
employees:employee_id,salary
departments:department_name
内连接
书写:
table1 [inner] join table2 on 连接条件
规则:
连接两张表中都存在的数据:满足连接条件
employees departments
100 zhangsan10 10 IT
102 lisi20 20 销售
103 wangwu30 30 前台
104 zhaoliu40 40 财务部
105 chengcheng50 安保

连接:employees e inner join departments d on e.department_id = d.department_id
100 zhangsan10 ` 10 IT
102 lisi20 20 销售
103 wangwu30 30 前台
104 zhaoliu40 40 财务部

EG:
select
e.employee_id,e.salary,d.department_name
from 
employees e inner join departments d on e.department_id = d.department_id;
外连接
左外连
书写:table1 left [outer] join table2 on 连接条件
规则:连接两张表都存在的数据+左表中存在右表中不存在的数据
连接:
employees e left join departments d on e.department_id = d.department_id
100 zhangsan10 10 IT
102 lisi20 20 销售
103 wangwu30 30 前台
104 zhaoliu40 40 财务部
105 chengcheng


eg:
select
e.employee_id,e.salary,d.department_name
from 
employees e left join departments d on e.department_id = d.department_id;
**以左表为主:
右外连
书写:
table1 right [outer] join table2 on 连接条件
规则:连接两张表都存在的数据+右表中存在但左表不存在的数据
100 zhangsan10 10 IT
102 lisi20 20 销售
103 wangwu30 30 前台
104 zhaoliu40 40 财务部
50 安保
**
table1 right join table2 on 条件
table2 left join table1 on 条件


多表连接
select
from 
table1 left join table2 on 连接条件1
left join table3 on 连接条件2
left join table4 on 连接条件3
...




自连接:
--查询员工工号,工资,经理id,经理名字
select
e1.employee_id,e1.salary,e2.employee_id,e2.first_name
from 
employees e1 left join employees e2 on e1.manager_id = e2.employee_id;
========================================================
SQL分类: database
DQL data query language数据查询语言
select[重点]
DDL data define language 数据定义语言
create|alter|drop
DCL data control language数据控制语言
grant|revoke[不涉及]
DML data manipulate language 数据操纵语言
insert|update|delete[重点]
TCL Transaction control language事务控制语言
commit|rollback[重点]

建表【重点】
create table 表名(
列名 数据类型 [约束] [约束],
列2 数据类型 [约束],
... --最后一列不要加逗号
);


数据类型:
字符串
varchar2(n):
该列的数据类型为字符串,最高(字节)长度为n
char(n):
该列的数据类型为字符串,存储的字符串最高长度为n,
name char(5)
'abcde' √ length(name) = 5
'abc' √length(name) = 5
**不够5的用空格补充

数字
number(n):数字类型,数字长度为n的整数
age number(3):
123 √
123.5 ?
number(n,m):数字类型,数字的长度为n,其中小数位为m
balance number(10,2)
123.456789 -- 123.46 √
日期
date 时间|日期(精确到秒)
'7-7月-1997' --- ×


clob: 大文本数据
blob:大二进制数据
约束:
unique 唯一约束 用户身份证
not null 非空约束 注册昵称,用户密码,邮箱...
primary key 主键约束 (唯一标识表中的一条数据)
特点:
唯一+非空
foreign key 外键约束
eg:
employees表中的department_id列就是(departments)外键
**外键指向主表的主键

语法:
references 主表(主键)
check 检查约束
check(约束表达式)
sex varchar2(5)check(sex in ('男','女'))
phoneNum varchar2(11) check(length(phoneNum) = 11)
email varchar2(30)check(email like '%@%');




存储学生信息 t_student
学号 主键
姓名 非空
性别 只能选择'男' '女'
邮箱 必须包含@
class_id 外键(班级表中主键)

SQL:
create table t_student(
stu_id number(10) primary key,
stu_name varchar2(40) not null,
stu_sex varchar2(5) check(stu_sex in ('男','女')),
stu_email varchar2(50) check(stu_email like '%@%'),
class_id number(10) references t_class(class_id)
);

存储班级信息 t_class
class_id 主键
class_name 班级名称
SQL:
create table t_class(
class_id number(10) primary key,
class_name varchar2(30) not null
);
**按照先主表后子表的顺序创建


测试数据
1.增加
insert into 表名(列名,列名,...) values(值1,值2,)
...表名后的列,必须和values后的值保持一致
①添加班级
insert into t_class(class_id,class_name) values(10035,'java35班');
②添加学生 10035059chengcheng '男'[email protected] 10035
insert into t_student values(10035059,'chengcheng','男','[email protected]',10035);


2.修改数据
语法:
update 表名 set 列名= 新值,列名= 新值,.. where 条件
--修改chengchegn---程程,[email protected]@qq.com
update t_student set stu_name = '程程',stu_email='[email protected]' where stu_id = 10035059;

3.删除
语法:
delete from 表名 where 条件

--删除程程的信息:删除stu_id = 10035059
delete from t_student where stu_id = 10035059;


=========================================================================
回顾:
建表:
create table 表名(
列名 数据类型 [约束] [约束2],
列 数据类型  [约束],
...
);
删除:
drop table 表名
DML语句:
insert:
插入全部列:insert into 表([所有列]) values(值1...);
**表后的列和values后的值必须一一对应
插入部分列:insert into 表(指定部分列) values(值...);
update:
update 表名 set 列= 新值,列=新值.. where 条件
**更新表中全部数据
update 表名 set 列 = 新值;
delete:
delete from  表名  where 条件;
**删除表中全部数据

说明:删除表中全部数据
delete from 表:
逐条删除
truncate table 表名;
一次性将表中数据截断
结论:
删除全部数据:truncate 比delete 效率高


序列:
序号生成器
语法:create sequence 序列名;
使用:序列名.nextval
**当前序号值会被取走;
eg:
创建seq_class的序列
create sequence seq_class;
create sequence seq_class1 start with 100000;--创建seq_class1序列,起始值为100000
注意:
序列不属于任何表;
删除序列:
drop sequence 序列名




视图:View
是一个虚拟表:
语法:
create view 视图名 as select语句;--本质上就是给查询语句起了别名

eg:
--查询员工工号,工资,部门名称,部门所在地
select
e.employee_id,e.salary,d.department_name,l.street_address
from 
employees e left join departments d on e.department_id = d.department_id
left join locations l on d.location_id = l.location_id;
①。创建视图:
create view v_emp as 
select
e.employee_id,e.salary,d.department_name,l.street_address
from 
employees e left join departments d on e.department_id = d.department_id
left join locations l on d.location_id = l.location_id;
②对视图进行查询
select * from v_emp;
删除视图:
drop view 视图名;

作用:
简化查询语句sql
没有优化查询效率的作用:
视图是逻辑概念,不会产生任何表占用空间

索引:
作用:提高数据的查询速率;
创建索引:
create index 索引名 on 表(字段);
eg:
create index 索引名 on t_product(description)
**根据description列为条件查询时,查询效率比较高
索引使用:
oracle自动使用;
注意:
可以优化查询效率
索引并不是创建越多越好 (索引会单独占用数据库内存空间,数据在修改时,需要更新索引)
删除索引
drop index 索引名;



事务【重点+难点】

--1.oracle客户端执行sql:
insert into t_class values(37,'java37班');
另外的客户端查询不到数据
--2.转账:wangyx  ---  >houhui  50000
t_acccount(c_id,username,password,balance)

100001 wangyx 123 100000
100002 houhui 321 1
①:update t_account set balance = balance - 50000 where c_id = 100001;--wangyx扣50000
②:update t_account set balance = balance +50000 where c_id = 100002;--给houhui+50000

概念:
数据库的最小执行单元:一个事务是由1条或者n条sql(DML)组成,要求多条sql要么全部执行成功,要么只要有一条执行失败,则全部失效.
**事务的大小由实际业务决定
原理:
oracle会为每一个连接的客户端,分配一小段内存空间(rollback segment 回滚段).
每个客户端sql的执行结果,会缓存在该内存中.当事务结束时(commit),将回滚段中的数据一次性同步至数据库(DB server),或者事务失败时(rollback),将回滚段中的数据销毁;
开始:任意一条DML语句

事务边界:
事务开始:
任意一条DML语句事务的开始

事务结束:

成功:
显示提交:commit;
隐式提交:任意一个DDL语句,自带commit;
失败
显示回滚:rollback;
隐式回滚:数据宕机 断电;
事务特性:ACID2
A 原子性(Atomic):事务中的sql不可分割;
C 一致性: 事务执行前后,数据库中数据保持一致
转账:事务执行前数据库中wangyx和houhui金额总和必须都是1000001
I 隔离性(Isolation):不同的客户端之前事务互不干扰,事务与事务之前互不干扰
D 持久性:事务结束之后,对数据库的影响是永久性的

思考:
insert 
update
delete
commit
insert
create table 。。。
delete
rollback
??有几个事务?


数据库事务隔离级别:(标准数据库)
read-uncommitted读未提交: ---oracle不支持
现象:能够读到其他客户端的回滚段中的数据;
A客户端
--添加一个账户
insert into t_account values(100003,'jiangzz','22222',1000);
B客户端
select * from t_account where c_id = 100003;--查到了jiangzz的账户信息

问题:
该现象也被称为 ----脏读

read-committed读提交 ---oracle默认的事务隔离级别
解决问题:
解决了脏读问题;
现象:
A客户端不能读到其他客户端回滚段中的数据.


A客户端
--查询100001  wangyx账户的信息
select * from t_account where c_id = 1000001;--1000000

B客户端
--取钱1000000
update t_account set balance = balance -1000000 where c_id = 1000001;
commit;
A客户端
--查询账户余额 100001
select * from t_account where c_id = 1000001;--0
问题:
需求背景:操作的某条数据,不希望在事务(业务)结束之前被修改

repeatable-read 重复读-- oracle不支持
解决问题:
解决读提交问题:
Oracle提供了解决方案:
A: select * from t_account where c_id = 1000001 for update;--对数据加行级锁
现象:
A:--统计账户总人数
select count(*) from t_account;---100

B:--卡户
insert into t_account values(100004,'陈艳南','123',10);
commit;

A:--统计人数
select count(*) from t_account;---101;

问题需求:
当客户端查询(操作)某张表的数据时,比希望其他客户端对该表进行任何操作

Serializable:序列化读--oracle支持表级锁
解决问题:
客户端访问数据库的表,变成序列化访问;(一个客户端一个客户端)


总结:
从read-uncommitted----> serializable 事务隔离级别提高;
数据安全性越高
数据库访问效率越低
===================================================
补充:
外键相关约束:当删除主表中被副表引用外键的数据时,是无法删除的
主表:
create table tab1(
  t_id number(5) primary key,
  name varchar2(13)
);
从表:
create table tab2(
  b_id number(5) primary key,
  user_id number(5) references tab1(t_id),
  b_name varchar2(15)
);
insert into tab1 values(1,'zpc');
insert into tab2 values(1,1,'lzr');
delete from tab1 where t_id=1          =======》ORA-02292: 违反完整约束条件 (HR.SYS_C004410) - 已找到子记录

可以在添加外键约束时添加约束:
on delete cascade  删除父表中的数据时,级联删除子表相关联的数据
on delete set null 删除父表中的数据时,将子表相关联的数据置为null


班级
100 java班
学生
001 wangyx13900412354 [email protected]
=====================================================================
回顾:
事务:
1.数据库会为每一个客户端分配一小段内存空间(回滚段),客户端sql的执行结果,会先缓存在回滚段中,只有事务结束(commit),会将回滚段中的数据一次性同步至数据库;事务失败(rollback;),将回滚段中的数据销毁.
事务隔离级别:
read-uncommitted读未提交 --oracle不支持
脏读
read-committed读提交 --oracle支持,默认
不可重复读
repeatable-read重复读 ---oracle不支持
** oracle提供解决方案:
select * from ....  for update;--行级锁
幻影读


serializable --oracle支持
**客户端对表的访问,变成序列化访问s

** set transaction isolation level 隔离级别


数据库设计范式:
第一范式:属性不可再分割:
--用户表
id 用户名密码 爱好
001 程程123 唱歌,跳舞,网购
002 解及 123 唱歌,看书,跳舞
003 于谦321 抽烟,喝酒,烫头
--问题:删除所有的 唱歌 爱好.
**需要将所有包含"唱歌"爱好的数据全部查询,字符串拆分,更新
解决方案:
将可分割的属性,单独作为一张表

创建一个爱好表
id 爱好名字
1 唱歌
2 跳舞
3       网购
4 看书
5 抽烟
--用户表
id 用户名密码
001 程程123
002 罗平123
--用户爱好关系表(u_id指向用户表id;aihao_id指向爱好表id)
u_id aihao_id
001 1
001 2
001 3
create t_user_aihao(
u_id number(10) references t_user(id),
aihao_id number(10) references t_aihao(id)
);

第二范式:属性不可部分依赖主属性(主键)
--员工表
id 名字部门id 部门名称
001 程程10 IT
002 丁伟20 Sales
30 客户部

*主键:将id和部门id作为联合主键
primary key(id,部门id);
--问题:添加一个部门?
添加 部门id部门名称
**只有部门id,没有员工id,不能组成联合主键
解决方案:
将部分依赖拆分成一个表
--员工表
id 名字dep_id
001 程程10
002 丁伟20
--部门表
部门id 部门名称
10 IT
20 Sales
30 客服部
**外键建在多的一方;
第三范式:属性不能传递依赖主属性

--学生成绩表(主键id)
id 名字科目id 科目成绩
001 时间100 Corejava90
002 王乐200 Oracle60
300 lucene
--问题:
添加一个科目?
科目信息:科目id 科目名称
300 lucene
**添加的数据没有id
解决方案:
将间接依赖属性单独作为一张表
--学生表
id 名字
001 时间
002 王乐
--课程表
科目id 科目
100 CoreJava
200 Oracle
--学生成绩表
u_id course_id成绩
001 10090
002 20060
--建表sql:
create table t_student(
id number(10)primary key,
stu_name varchar2(30)
);
create table t_course(
c_id number(10)primary key,
c_name varchar2(50)

);
create table t_stu_score(
u_id number(10) references t_student(id),
course_id number(10) references t_course(c_id),
scores number(6,2)
);
============================================================================


 

你可能感兴趣的:(数据库混合,SQL)