这里将oracle的多表查询的sql用法。
基础的语法参考另一篇oracle数据库的操作--基础sql:https://blog.csdn.net/S_L__/article/details/105030191
select * from employees e,departments d;
select e.*,d.*
from employees e
join departments d on e.department_id=d.department_id;
select e.*,d.*
from employees e,departments d
where e.department_id=d.department_id;
select e.*,d.*
from employees e
left join departments d on e.department_id=d.department_id;
--oracle自己的左外连接:等号的右边末位添加(+)
select e.*,d.*
from employees e,departments d
where e.department_id=d.department_id(+);
select e.*,d.*
from employees e
right join departments d on e.department_id=d.department_id;
--oracle自己的右外连接:等号的左边添加(+)
select e.*,d.*
from employees e,departments d
where e.department_id(+)=d.department_id;
select e.*,d.*
from employees e
full join departments d on e.department_id=d.department_id;
即:2个表没有关系,字段范围处理
select e.salary,j.*
from employees e,job_grades j
where e.salary between j.lowest_sal and j.highest_sal
select e.salary,j.*
from employees e
join job_grades j
on e.salary between j.lowest_sal and j.highest_sal;
本质就是同一张表,同时拥有主键,外键
employees,主键employee_id,外键manager_id
员工姓名 员工工资 上级姓名 上级工资
select e.first_name||e.last_name,e.salary,m.first_name||m.last_name,m.salary
from employees e,employees m
where e.manager_id=m.employee_id
自连接适用场景(菜单树):
菜单树
系统管理
员工管理
基础数据管理
商品管理
商品类型管理
CROSS JOIN——它在两个表格中创建了一个笛卡尔积,就象是在Oracle8i中没写WHERE时一样
select e.*,d.*
from employees e
cross join departments d;
即:不能使用*,2个表的字段有相同
自动把2个表相同的列名做等值连接
NATURAL JOIN——它通过从WHERE子句中自动连接标准来改善SQL的稳定性
select e.first_name||e.last_name,d.department_name
from employees e
natural join departments d;
select e.first_name||e.last_name,d.department_name
from employees e,departments d
where e.department_id=d.department_id
and e.manager_id=d.manager_id;
它可以通过名字来具体指定连接
(填写那个字段,就是那个字段进行等值连接)
写字段的时候不能写别名,直接写字段名称
select e.first_name||e.last_name,d.department_name
from employees e
join departments d using(department_id,manager_id);
--①单行单列子查询:只包含一个字段的查询,返回的查询结果也只包含一行数据
--查询工资大于平均工资的员工
1.平均工资
select avg(salary) from employees;--4400
2.大于平均工资
select *
from employees
where salary>
(
select avg(salary) from employees
)
②多行单列子查询:只包含了一个字段,但返回的查询结果可能多行或者零行
--分组,只要平均工资
select avg(salary)
from employees
group by department_id
语法: ROWNUM为oracle自带的,用来截取数据(前面多少条,或者后面多少条) ,相当于maysql的limit num.
注意:rownum关键字直接使用,只能使用<=,不支持>用法,但是使用别名可以用>符号,在分页的使用需要用
SELECT [column_list], ROWNUM
FROM (SELECT [column_list]
FROM table
ORDER BY Top-N_column)
WHERE ROWNUM <= N;
--查询工资最高的3名员工
select a.*,rownum r2
from
(
select e.*,rownum r1
from employees e
order by e.salary desc
)a
where rownum<=3
两种方式:第一种为oracle标准的分页查询方法,因为所查询的条数更低,效率更高。
第一种分页sql:
select b.*,rownum r3
from
(select a.*,rownum r2
from
(
select e.*,rownum r1
from employees e
order by e.salary desc
)a
where rownum<=6 --把一个查询条件推到第2层
)b
where r2>3
第二种分页sql:
select b.*,rownum r3
from
(select a.*,rownum r2
from
(
select e.*,rownum r1
from employees e
order by e.salary desc
)a
)b
where r2>3 and r2<=6
第一种:表,字段,内容全部复制
备份employees表到employees_bck
create table employees_bck
as
select * from employees;
第二种:只复制表结构,不要数据
创建employees_bck2表,复制employees表结构
create table employees_bck2
as
select * from employees
where 1=2 ;
第三种:只复制部分字段
使用employees表中的某几列创建employees_test表(id,fullname,hire_date,salary)。
create table employees_test
(id,fullname,hire_date,salary)
as
select employee_id,first_name||last_name,hire_date,salary
from employees;
1,插入一行数据,可以空值(和mysql一样)
insert into employees_bck2(employee_id,first_name,last_name)
values(1,'军','军');
2,插入时使用函数(hire_date-sysdate)
insert into employees_bck2(employee_id,hire_date)
values(20,sysdate);
3.insert+select (oracle特殊场景写法)
insert into employees_bck2
select * from employees;
注意:这样写法要求字段名完全一直,否则按照下面的写法
insert into employees_bck2
(employee_id,first_name,last_name,hire_date,salary)
select employee_id,first_name,last_name,hire_date,salary
from employees;
1,简单的修改语句,在线运行系统注意先备份数据在修改
update employees_bck2
set first_name='张',last_name='二娃'
where employee_id>10000
2,修改10006号员工的6000工资和10002号员工4000相同--注意,在mysql中的对同一张表的更新问题。
oracle写法:
update employees_bck2
set salary=(select salary from employees_bck2 where employee_id=10002)
where employee_id=10006
mysql写法:
update employees
set salary =
(
select salary from
(
select * from employees
) as e
where e.employee_id = 10002
)
where employee_id = 10006;
1.简单的删除语句 (和mysql一样)
delete from employees_bck2
where employee_id<100
--场景:在线系统又更新了一些数据 ,备份表更新已有的数据,插入新的数据
Merge语句(oracle9i后新增):
MERGE INTO table_name table_alias
USING (table|view|sub_query) alias
ON (join condition)
WHEN MATCHED THEN
UPDATE SET
col1 = col_val1,
col2 = col2_val
WHEN NOT MATCHED THEN
INSERT (column_list)
VALUES (column_values);
使用案例:
merge into employees_bck2 e2
using employees e
on (e.employee_id=e2.employee_id)
when matched then
update set
e2.first_name=e.first_name,
e2.last_name=e.last_name
when not matched then
insert(e2.first_name,e2.last_name)
values(e.first_name,e.last_name)
(存在于DML和DDL)
1、开始于第一个执行的语句
2、结束于:
用户执行COMMIT 或 ROLLBACK
单个的DDL or DCL 语句
用户连接异常错误,或者用户断开连接
系统崩溃
1、当下列情况发生时事务自动隐式提交:
执行一个 DDL 语句
从 SQL*Plus正常退出(EXIT 或者 QUIt)
2、当从SQL*PLUS中强行退出或连接异常中断时,事务自动回滚
在SQLPLus中有一个与事务相关的环境变量-autocommit,如果这个参数被启用,在SQLPLus中所有修改将在执行时自动提交,启动的方法是在SQLplus环境下执行set autocommit on命令。
--默认状态下oracle的事务自动提交是关闭的
SQL> show autocommit;
autocommit OFF
--下面的语句就是开启事务自动提交
SQL> set autocommit on
SQL> show autocommit;
autocommit IMMEDIATE
场景:大量导入数据需要回滚的时候,可以回滚到指定事务点
--保存事务点(内存),不能手动点击提交或者回滚
sp1 没有数据:如果回到sp1点,sp2和sp3事务点就生效
select * from test t
savepoint sp1;
sp2 有11条数据
insert into test
select employee_id,first_name
from employees;
savepoint sp2;
sp3 删除了11条数据
delete from test
savepoint sp3;
--回滚指定事务点
rollback to sp1;
--悲观锁
第一人:必须把事务提交或者回滚:释放锁
select * from table id=100 for update对这一行记录加锁,如果事务没有提交,其他就只能只读访问,不能修改
update from table where id=100
第二人
select * from table id=100
update from table where id=100--不能执行
--乐观锁:数据库表里面添加了一个字段version
第一人
select *,version=10 from emp where id=11
先判断当前的版本是否是10,是
update ...where id=11 and version=10
update成功,version=11
第二人
select *,version=10 from emp where id=11
update ...where id=11 and version=10
提交的时候发现数据库version==11,
否version=11抛出异常version以及被其他人修改了
语法:
ALTER TABLE table
ADD (column datatype [DEFAULT expr]
[, column datatype]...);
案例:
alter table test
add (sex number(1))
语法:
ALTER TABLE table
MODIFY (column datatype [DEFAULT expr]
[, column datatype]...);
不一定会成功,如:把一个字符串变成number,先把字符串的字段设置为null
案例:
alter table test
modify (sex char(1))
语法:
ALTER TABLE table
DROP column (columns);
案例:
alter table test
drop column sex--只能删除一列
drop 删除列 不可回滚
从每行中删除掉字段占据的长度和数据,释放在数据块中占用的空间。删除大表中的字段将需要比较长的时间.
truncate 删除表 ,不可回滚
使用: TRUNCATE TABLE table_name
delete :(DML语句)以选择删除表中的一部分 可回滚
--Oracle 支持下面五类完整性约束:
1、NOT NULL 非空
2、UNIQUE Key 唯一键
3、PRIMARY KEY 主键(非空且唯一)
4、FOREIGN KEY 外键
5、CHECK 检查
案例:
create table t_user
(
id int primary key,--列级建立约束
name varchar2(20) not null unique,
password varchar2(20),
age number(3) check(age>0 and age<150)
);
双主键约束,只能创建表的时候控制,如下:
create table t_user_role
(
u_id int,
r_id int,
constraint sys_c_ur_pk primary key(u_id,r_id),--双主键,表级
--双外键
constraint sys_c_ur_fk1 foreign key (u_id) references t_user(id),
constraint sys_c_ur_fk2 foreign key (r_id) references t_role(id)
);