MySQL常用语句

发布时间 2023-11-09 14:56:40作者: 溺水的小金鱼

--------------数据库分类 --------------

主流数据库:
微软sql server 2008 R2,access
瑞典mysql
美国oracle 10g 11g 12c
小型数据库 access
中型数据库mysql,sql sever
大型数据库 负载级别sysbase<oracle<db2 安全性高 昂贵


客户端:
a)、安装数据库客户端软件
b)、配置本地服务(即tnsnames.ora文件),用于远程连接数据库,需要的配置信息有:(必须掌握)
数据库服务器的IP(或主机名)
全局数据库名称(也即sid)
监听端口(默认是1521)
登陆数据库还需要用户名和密码

数据库对象:表、视图、索引、用户、角色、表空间、存储过程、包......


一:创建Oracle数据库对象(DDL:Data Definition Language)
ddl:数据库定义语句
create
alter
drop
truncate
1、表的创建、修改与删除
表是存储用户数据的基本结果。建立一个表结构的基本任务是对组成表的字段进行定义,指出该表由哪些字段组成,字段值的数据类型及对字段的约束。

******************表的创建***********************

创建表结构的格式:
create table 表名(
列名1 数据类型 ,
列名2 数据类型 ,
列名3 数据类型 ,
列名4 数据类型 ,
列名5 数据类型 ,
...
列名N 数据类型
);

create table 表名(
列名1 数据类型 [primary key],
列名2 数据类型 [unique],
列名3 数据类型 [not null | null],
列名4 数据类型 check(条件),
列名5 数据类型 [references 表名(列名)]
...
列名N 数据类型 [default 默认值] [各种约束]
);

列名命名规则:字母、数字、下划线(_)组成,不要以数字开头

数据类型:在Oracle中有很多数据类型,我们需要掌握三种:字符串、数字、日期
数字:number 可以表示整数,也可以表示小数 number(5,2) 一个数为5位数的有效数,2位小数 -999.99~999.99 numbe(5) -99999~99999
日期:date
字符串:char、varchar2,在Oracle中,字符串用单引号引起来,用双引号引起来是别名
char是定长,如char(12),存储内容的最大长度是12个字节,若实际存储内容只有6个字节,该列仍然占用12个字节 char(10) '小明'
varchar2是可变长,如varchar2(12),存储内容的最大长度是12个字节,若实际存储内容只有6个字节,该列仍然占用6个字节

字节:字节是由二进制代码组成,二进制代码就是0和1组成,8个二进制位组成1个字节,即1B = 8b
字符:是由字节经过特定的编码方式组成,编码就相当于一个翻译官,不同的翻译官所掌握的语言也不一样,UTF-8是掌握了8国语言的翻译官,即UTF-8是国际通用字符集数据库服务器可以使用不同的翻译官(即使用不同的字符集)若数据库使用GBK或GB2312做为翻译官,那么1个中文字符占2个字节若数据库使用UTF-8做为翻译官,那么1个中文字符占3个字节建议最保守的做法是:1个中文字符占3个字节对于英文字符来说,一个字符占用1个字节。

主键(primary key):相当于身份证号码,是唯一的,通过身份证号码只能找到一个人,即通过主键列只能找到一行数据,在创建表时,通常要有主键列,主键属于表对象,所以主键有一个名字,若没给主键指定名字,oracle会自动分配一个唯一的名字,在一个表中只能有一个主键对象

约束:就是限制
唯一约束(unique):值不能重复,但是可以为null。属于表对象(跟列一样),必须要有名字,若没有指定名字,则Oracle随即分配一个唯一的名字
非空约束(not null):值不能为空,一个列默认是可以为空
主键(primary key):相当于身份证号码,包含非空约束和唯一约束,也是属于表对象,在设计一张表示,需要有主键列
检查约束(check):检查值是否满足某个条件,属于表对象,必须要有名字
外键(references):也属于表对象,必须要有名字
默认值(default):当没有给列指定值的时候,则取默认值;在创建表时,若没有给列指定默认值,那么该列的默认值是空(即null)

复制代码
创建一个简单的表
create table t_student(
id number,
name varchar2(50),
sex char(12),
birthday date
);


create table student_tmp(
id number,
name varchar2(50),
sex char(12),
birthday date
);
复制代码

以下两个表有约束关系:

create table t_class(
classid number primary key, ---- 主键
classname varchar2(100)
);

--sysdate:获取系统当前时间,格式是:年月日时分秒
create table t_user(
t_id number primary key, ---- 主键
t_sex varchar2(20) check(t_sex = '男' or t_sex = '女'), ----- 检查
t_name varchar2(50) unique, --- 唯一
t_cardid varchar2(20) not null, --- 非空
t_birthday date default sysdate, ---- 默认值
classid number references t_class(classid) ----- 外键
);

复制代码
商品售货系统设计案例
现有一个商品的数据、记录客户及其购物情况,由下三张表组成
商品goods(商品号goodsid,商品名goodsname,单价untiprice,商品类别category,供应商provider)
客户customer(客户号customerid,姓名name,住址address,电邮email,性别sex,身份证cardid)
购买purchase(客户号customerid,商品号goodsid,购买数量nums)
1、建表,每个表的主外键,客户的姓名不能为空值;单价必须大于0,购买数量必须在1到30之间;电邮不能重复;客户的性别必须是男或女,默认是男;
CREATE TABLE goods(
goodsid VARCHAR(32) primary key COMMENT'商品号',
goodsname VARCHAR(50) comment'商品名',
untiprise DECIMAL(8,1) check(untiprise>0) comment'单价',
category varchar(32)comment'商品类别',
procider carchar(32)comment'供应商'  
)
create table customer(
customerid VARCHAR(32) primary key comment'客户号',
name varchar(32) not null comment '姓名',
address varchar(32)comment'家庭住址',
email char(20) unique comment'邮箱',
sex char(2) default('男')check (sex in('男','女'))comment'性别',
cardid varchar(32)comment'身份证'
)ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='客户表';
create TABLE purchase(
customerid varchar(32) references customer(customerid) comment'客户号',
goodsid varchar(32) references goods(goodsid) comment'商品号',
nums int(12) check(nums between 1 and 30) comment'购买数量'
)
复制代码

 

*****************表的修改***************

-------- 查看表结构 --------
在 command window(命令窗口)下输入:
desc 表名;

--------修改表:增加列 --------
alter table 表名
add(字段名1 数据类型 [not null | null],字段名2 数据类型 [not null | null]);

如果要新增多个列,则要用逗号将各列定义分开。

例:向t_student表中增加一个性别和住址字段

alter table t_student
add(score number,addr varchar2(50));

alter table t_student
add classid number references t_class(classid);

--------修改列:修改数据类型、约束等等--------
alter table 表名
modify(列名 数据类型 [default 默认值] [not null | null]);

如果要修改多个列,则要用逗号将各列定义分开。

例:修改t_student的name字段类型为varchar2(50),且默认值为"张大大"。


alter table t_student
modify name varchar2(50) default '张大大' not null;


--------删除列--------
alter table 表名
drop column 列名;


例:
alter table t_student
drop column score;

alter table t_student
drop column addr;


*****************表的删除******************************
删除表结构:drop table 表名
例:删除student_tmp2表
drop table student_tmp2;

*************************************

emp 员工信息表,包含字段:empno 雇员编号(工号), ename 员工姓名, job 工种,mgr 员工上级的编号, hiredate 入职日期,
sal 薪水, comm 奖金, deptno 部门号

dept 部门表,包含的字段: dname 部门名称, loc工作地址

二、Oracle数据库数据操作(DML:data manipulation language)
/*dml:数据库操作语句,常见的增、删、改、查(最重要)

1、查询 --- 注意:后面的查询案例,如无特殊说明,均以系统中存在的emp和dept两个表为例
/*查询的总语句
select 列1,列2,列3...列N 或 *
from 表名/(表达式) -- 数据池
[where 过滤条件]
[group by 分组内容]
[having 组内条件]
[order by 排序方式]
*/

********************1.1 无条件查询(全表查询)********************
语法:
select 列1,列2,列3...列N 或 *
from 表名;

--查询指定列
select empno,ename,job,mgr,hiredate,sal,comm,deptno
from emp;

--查询查询所有列,用*表示所有列
select * from emp;


********************1.2 条件查询********************
select 列1,列2,列3...列N 或 *
from 表名
[where 过滤条件]

按照指定的条件进行过滤,如“单值比较运算符”:>、<、=、!=或<>、<=、>=,两边的数据类型要保持一致

例:查询20号部门中全体员工的姓名、工资、和工种的有关信息。
select ename,job,sal from emp
where deptno = 20;

思考以下sql,两边的数据类型是否一致?
select * from emp where sal = '八百';

练习:查找出奖金超过其工资的雇员的姓名、工资、奖金和工种的信息。
select ename,sal,comm,job from emp where comm>sal;

----distinct:对于指定的字段所选择的重复行,只返回一行。
例:查找出20号部门中有多少种不同的工种。
select distinct job from emp
where deptno = 20

/*没有使用distinct关键字的结果
select job from emp
where deptno = 20
*/

---多条件过滤之逻辑运算符:and、or
例:查找出全部经理 和 第10号部门秘书的有关信息
select job,ename,sal,deptno from emp
where job='MANAGER' or (job='CLERK' and deptno=10);

练习:
查找出不是30号部门中的所有经理的所有信息。
select * from emp where job='manager' and deptno!=30;

----多值比较运算符:(not)between 值1 and 值2, in, not in
例:查找出工资在2000到3000之间的职工姓名、工种和工资
select ename,job,sal from emp
where sal between 2000 and 3000;

练习:查找出工资在2500到3500之外的职工姓名、工种和工资
select ename,job,sal from emp where sal<=2500 or sal>=3000
select ename,job,sal from emp where sal not between 2500 and 3000

例:查询出全部秘书、分析员或推销员的姓名、工种、工资和所在部门号
select ename,job,sal,deptno from emp
where job IN('CLERK','ANALYST','SALESMAN');

练习:查询出工资分别是1500,2500,3000的分析员或推销员的姓名、工种、工资和所在部门号
select ename,job,sal,deptno from emp where sal in(1500,2500,3000) and job in('ANALYST','SALESMAN');

-----模糊查询: like
%表示匹配任意长度的字符串
%test%:表示匹配中间字符串为test的任意长度的字符串

_表示仅能匹配一个字符
o_a:表示匹配长度为3,以字母o开头,且以字母a结尾的字符串,中间一个字符为任意字符。

例:查询出名字以"MA"开头的全部职工的姓名、工种、工资和部门号
select ename,job,sal,deptno from emp
where ename like 'MA%';


例:查询出名字以"SCO"开头的,长度为5位的全部职工的姓名、工种、工资和部门号

select ename,job,sal,deptno from emp
where ename like 'SCO__';

练习:
1、查找出所有工种以'MANAG'开头的职工姓名、工种和工资
select ename,job,sal from emp where job like'MANAG%'

2、查找出所有姓名以'ALLE'开头,且长度为5的职工姓名、工种和工资
select ename,job,sal from emp where ename like'ALLE_';

-----is null 或 is not null
例:查找出emp表中经理号(MGR)为空的职工的有关信息
select * from emp where MGR is null;


如果某字段为空,则要使用比较运算符"IS NULL"(非空使用"IS NOT NULL"),不能用"=NULL"或"!=NULL"表示。

练习:查找出没有奖金的员工的姓名、工种、工资和部门号
select ename,job,sal,deptno from emp where sal is null;

**************************1.3 排序显示查询结果********************
通常情况下,查询结果是以按数据在数据库表中存储的顺序显示的。若要使查询结果按某种特定顺序显示,就要使用“ORDER BY”子句。
格式:
ORDER BY 字段名 ASC/DESC;
字段名,指出查询出来的结果按该字段排序;选项ASC表示按升序排序,DESC表示按降序排序;默认是按升序排序。
ORDER BY子句可以对查询结果按一个字段或多个字段进行排序。按多个字段排序时,先按前面的字段排序,当字段相同时,再按下一个字段排序,以此类推。

例:计算每个销售人员的年度总报酬,并按总报酬由高到低顺序显示

select ename,job,sal,comm,12*(sal+comm) sumprice from emp
where job='SALESMAN'
order by 12*(sal+comm) DESC;

---sumprice是12*(sal+comm)表达式的一个别名,该别名在标题中使用。别名不影响列的真名,它不能在查询语句的其他任何地方使用。


练习:
1、查找出工资高于1000元的职工的姓名、工种、工资和部门号,并按部门号由小到大排序显示
select ename,job,sal,deptno from emp where sal>1000 order by deptno asc;

2、查找出奖金超过本人基本工资3%的职工的姓名,工资,奖金,奖金与工资的比例,并按其比例由高到低显示
select ename,sal ,comm,comm/sal 比例 from emp where comm>0.03*sal order by 比例 desc;

3、按工种升序,而同工种按工资降序排列显示全部职工的姓名,工种,工资。
select ename,job,sal from emp order by job asc , sal desc

---------------------------******************插入******************----------------------------

2、向数据库中插入数据
/*新增数据
insert into 表名(列1,列2...列N) values(值1,值2...值N);
commit | rollback;

在Oracle字符串用单引号引起来
*/
insert into t_class values (1, '测试就业班');
commit;

insert into t_class values (2, '测试周末班');
rollback;

--多条dml语句组成一个事物
insert into t_class values (3, '安全测试班');
insert into t_class values (4, 'JAVA开发班');
commit;


insert into t_user values (1, '男', '张大大','001',sysdate, 1);
insert into t_user values (2, '男', '张大大','001',sysdate, 1);
commit;

--思考以下sql是否有问题?
insert into t_user values (1, '男', '张大大','001',sysdate, 9);
commit;

******************修改******************
3、修改数据库的数据
update 表名
set 列1 = 值1,列2 = 值2...列N = 值N
[where过滤条件];

例:将职工ALLEN提升为经理,工资增至$8000,奖金增加40%
update emp
set job = 'MANAGER',sal = 8000,comm=1.4*comm
where ename = 'ALLEN';

练习:
1、对20号部门中经理或所有销售人员提高15%的工资。
update emp set sal=sal*1.15 where deptno=20 and job in('M...','A...');

******************删除******************

4、删除数据库的数据
delete [from] 表名
[where过滤条件]

例:删除emp表中工资低于500元的所有员工的信息
delete from emp
where sal < 500;

**************************************
事务:通俗理解就是做一件事情的过程,这个过程有两种结果:成功、失败,在数据库中发出一条dml语句即开启一个事务,开启事务就一定要结束事务,
结束事务的两种方式:
a1)、commit,提交事务,所有的操作都生效,操作的结果直会永久保存在数据库中
a2)、rollback,回滚事务,所有的操作都不会生效,操作的结果直接扔掉,不会永久保存到数据库中
**************************************
删除表的另一种方式:
truncate table 表名
截断表,即删除表中所有的数据,和delete的区别:
delete:会发起事务,可以有where过滤条件(即删除指定的数据),属于dml语句,删除效率比truncate低
truncate:不会发起事务,不能有where过滤条件(即只能删除表中所有的数据),属于ddl语句,删除效率比delete高,但有危险性
若表中有列是其他表的外键,则不能在该表中使用truncate(即truncate会影响外键列)
drop table 表名:即删除表的数据又删除表的结构。

delete from t_student;
commit;

delete from t_class;
commit;


--思考以下sql是否有问题?
truncate table t_class;
truncate table t_student;
不能删除带有主键的表

三、数据库中常用的函数
1、ROUND(m,n) -- 当n>0时,将m四舍五入到小数点右边n位;当n<0时,将m四舍五入到小数点左边n位
例如,计算每个职工每一个工作日(一个月为22个工作日)的工资。
select ename,round(sal/22,2) avgr,round(sal/22,0) bvgr,round(sal/22,-1) cvgr from emp;

2、T0_CHAR() -- 将一种数据类型的值转换成字符串格式。
例如,将时间改为指定的字符串格式:
TO_CHAR(date,'format')
select TO_CHAR(sysdate,'YYmmDD') from dual;

3、TO_DATE() -- 将一种数据类型的值转换成格式。
例如,将一字符串改为时间格式:
TO_DATE(char,'format')
select TO_DATE('20150405','YYYYmmDD') from dual;

4、nvl -- 空值函数
空值与任何数值运算,其结果仍为空值,因此会给很多计算带来不便。
空值函数的格式为:
nvl(参数1,参数2)
参数1,可以为字段名,变量或表达式;参数2,是与参数1类型相同的常量或表达式。如果参数1不为空值,则nvl函数返回参数1的原值,否则nvl函数返回参数2的值。

例:计算30号部门中每个职工每一个工作日(一个月为22天)的薪酬
select empno,ename,round((sal+nvl(comm,0))/22,1) avgr,deptno from emp where deptno = 30;


四、单表复杂查询
4.1 分组查询
分组/聚合/统计函数:
count(字段名):计算指定字段为非空的行数
count(*):计算表中的全部行数,包括重复行和空行
avg(字段名):计算指定字段的平均值
min(字段名):计算指定字段的最小值
max(字段名):计算指定字段的最大值
sum(字段名):计算指定字段的总和

例:计算emp表中公司职工的最低工资、最高工资、平均工资和总工资的和
select min(sal),max(sal),avg(sal),sum(sal) from emp;


例:计算emp表中公司职工的总人数及工种数
select count(*),count(distinct job) from emp;

 

分组查询命令的基本格式为:
select 字段名
from 表名
[where 过滤条件]
[group by 字段];

例:计算出公司支付给每个工种的总工资
select job,sum(sal) from emp
group by job;

如果要将各个分组再进行划分出不同的小组,则需要在"group by"子句中指定多个列名。

例:计算每个部门中每种工种各有多少职工数。
select deptno,job,count(*) from emp
group by deptno,job;

在本例中,先按部门号将职工分组,在同一部门中再按职工的工种进一部分组。
但要注意,在包括"group by"子句的查询中,select子句后的列名表中,
除统计函数外,均应包含在"group by"子句中(即列名表中不能出现与分组子句无关的列名),否则出错!

练习:统计各部门的人数。
select count(*) from emp group by deptno;

4.2 带条件的分组查询
利用"group by"子句将选择到的进行分组时,可以使用 having 子句用于限制选择的组,having子句的作用同where子句相似,都是指定查询条件。不同的是where子句对行进行选择,检查每条记录是否满足条件,而having子句是检查分组之后的各组是否满足条件。having子句是配合group by子句使用,在没有"group by"子句时不能用,并且group by和having子句在命令中要出现在where子句之后。
select 列1,列2,列3...列N 或 *
from 表名
[where 过滤条件]
[group by 分组内容]
[having 组内条件];

1、分组函数只能出现在选择列表、having、order by 子句中
2、如果在select语句同时含有group by、having、order by,那么他们的顺序是group by、having、order by
3、group by 有一个原则,就是 select 后面的所有字段,必须出现在 group by 后面,否则,有语法错误(重要)
4、有having 一定有group by


例:查询各工种组的年平均工资,要求每个工种组至少在2人以上
select job,avg(sal+nvl(comm,0))*12 avgsal,count(*) from emp
group by job
having count(*)>2;

练习1:查询出至少有两名秘书的所有部门的部门号,并按人数降序排序。

练习2:查询出所有经理和销售人员的年平均工资,并按年平均工资降序排序。

 

 

五、多表查询
1、等值连接
select 表别名1.列名1,表别名1.列名2.... 或 表别名1.*,表别名2.*
from 表名1 表别名1,表名2 表别名2,...表名n,表别名n
where 表名1或表别名1.列名=表名2或表别名2.列名 and 表名(n-1)或表别名(n-1).列名=表名n或表别名n.列名


例:查找名字为"ALLEN"的职工所在的部门号、部门名和部门所在地
select e.ename,e.deptno,d.dname,d.loc from emp e,dept d
where e.deptno=d.deptno and e.ename='ALLEN';

e.deptno=d.deptno的作用:该命令对两个表进行连接查询,oracle会扫描dept表,分别检查每条记录在连接条件e.deptno=d.deptno中所用列的值从emp表取出的记录的列值是否相等。如果相等,则将这两个记录连接,产生一条新的记录作为查询到的一行,再继续从表emp中取下一条记录。重复这个步骤,一直到处理完emp表的全部符合条件的记录。
如果对多个表进行连接查询,但在where子句中没有给出连接条件(称无条件连接),则Oracle将构成一个笛卡尔积,对所有表的全部行进行组合,产生大量的行,其结果很少使用,因此在查询中要避免产生笛卡尔积。


练习:
查询部门号是20,30,40的职工的员工编号,姓名,工资,部门所在位置。

显示部门号为10的部门名、员工号和工资

显示雇员名,雇员工资及所在的部门的名字,并按部门名排序

显示平均工资高于2000的部门号和它的平均工资

----PS:多表连接查询,是重点!!!配合面试题进行讲解 *******************


--查询解题思路:
1.分析题目涉及哪几张表;
2.如果查询的数据来自于多张表,找到这些表的相同字段,在where后面,把这些字段用等于号连接起来;
3.如果需要对单条记录进行过滤,就把过滤条件追加到where子句后面,用and连接起来;
4.需要对多组数据进行统计,使用group by进行分组;
5.分组后的过滤,只能使用having;
6.需要排序,就用orader by。

------------******************华丽的分割线******************---------

2、外部连接查询(左右连接)
select 列名
from 表名1 表别名1,表名2 表别名2
where 表别名1.列名=表别名2.列名(+) 或 表别名1.列名(+)=表别名2.列名;

select ... from table1 t1,table2 t2 where t1.id = t2.id(+); --左连接
select ... from table1 t1,table2 t2 where t1.id(+) = t2.id; --右连接

在where子句的条件中必须包含外部连接操作符"(+)"。当该操作符加在表的列名上时,每当该表没有行与另一表的一行连接时,Oracle将为该表列产生空值(需要哪个表产生空值,就在哪个表的字段上加上(+) )。
PS:右连接,等号右边的表为主表,等号左边的表为从表


例:显示出所有部门的编号、名称和其职工的姓名与工种。
select d.deptno,d.dname,e.ename,e.job from dept d, emp e where d.deptno = e.deptno(+)


左右连接的另一种写法:
select * from A2 right JOIN B2 ON A2.id=B2.bid
select * from A2 left JOIN B2 ON A2.id=B2.bid


以上例子,可写成以下格式:
select d.deptno,d.dname,e.ename,e.job from emp e right join dept d on e.deptno = d.deptno;
select d.deptno,d.dname,e.ename,e.job from dept d left join emp e on d.deptno = e.deptno;

练习:列出无雇员的部门的情况。

3、子查询
格式:
SELECT <列名表>
FROM 表名
WHERE 列表或表达式 比较运算符(SELECT 列名
FROM 表名
WHERE 条件);

----子查询,必须要用圆括号括起来。

单行值子查询
单行值子查询,是指只返回一行(或者说是,一个记录)的子查询。
例:查找出与“SMITH”在同一个部门工作的所有职工姓名及工资
select ename,sal
from emp
where detpno = (select deptno from emp where ename = 'SMITH') and e.ename !='SMITH';;

--对于该子查询命令,系统执行时先执行子查询,返回一个值(即SMITH的部门号)作为主要查询(或外层查询)的条件,然后再根据该条件执行主查询选择出预期的结果,即与“SMITH”同一部门的所有职工。通常,主查询与子查询之间用"="、">"等比较运算符进行连接。


练习:
(1)、查找出工资比"SCOTT"工资高的职工的名字,工种,工资和所在的部门号,并按工资升序排序。
(2)、查找出工资比"SCOTT"高,并且在"NEW YORK"工作的职工的有关情况。
(3)、查找出具有最高月工资的雇员的姓名、工种和工资。
(4)、查找出在"CHICAGO"工作的职工的姓名、工种和工资。


4、多行值子查询
多行子查询,是指子查询会返回多个值,此时,需要用到多值比较运算符:[NOT]IN

IN运算符表示属于的关系,即是否在所选数据的集合之中。"NOT IN"表示不属于集合或不是集合的成员。

例:查找出部门10与部门30中工种相同的职工的姓名和工种。
select ename,job from emp
where deptno = 10 and job IN(select disctinct(job) from emp where deptno = 30);


-- 练习:查找出部门10中的工种与部门30中任何工种都不相同的职工的姓名与工种。
-- 查找出部门20中的工种相同的职工的姓名与工种。
-- 查找出工资在1000到3500元之间的职工所在部门的所有人员的有关信息。
-- 查找出工资高于20号部门任意一个员工工资的信息。
-- 查找出工种在部门10中没有的其他部门职工的姓名、工种和工资信息。
-- 查找出10号部门中与销售部门中任何职工工种相同的职工的信息。 --- 提示:在子查询中,查出销售部的工种。


************************* 数据库扩展知识 ********************************************

5.在from子句中使用子查询
例:显示高于自己部门平均工资的员工的信息
select e.*
from emp e,(select deptno, round(avg(sal+nvl(comm,0)),2) avgsal from emp group by deptno) t
where e.deptno = t.deptno and e.sal > t.avgsal;

 六、/*伪列

rowid:属于表中的列,是由数据库自动增加的列,是真实存在的一个列,唯一标识一条数据的物理位置(查询语句首先得到数据的rowid,然后根据rowid到数据文件中唯一定位数据)
因此,根据rowid查询的效率是最高的,数据在入库时(即成功插入数据),Oracle数据就给这条数据分配一个唯一的rowid

rownum:是给结果集增加的一个序号,不属于任何的表,先有结果集,才能有rownum,始终是从1开始编号(不能跨过1而存在)
*/
--根据rowid查询的效率是最高的,但通常情况下不知道rowid的值,rowid是整个数据库唯一(在不同的数据库中不一定唯一)
select rowid from emp where emp.rowid = 'AAAMgzAAEAAAAAgAAA';

select rowid,emp.* from emp;


--rownum不属于任何的表,以下sql是否有问题?
select * from emp st where st.rownum = 1;
select st.*, st.rownum from emp st;
select st.*, rownum from emp st;

--始终是从1开始编号(不能跨过1而存在)
select * from emp where rownum < 7;
select * from emp st where rownum > 10;
select * from emp st where rownum between 1 and 10;
select * from emp st where rownum between 2 and 10;

select *
from student st
where rownum <= 20
or rownum >= 10;


--改进
--分页查询
select *
from (select st.*, rownum rownum1 from student st where rownum <= 20) t
where rownum1 >= 10;


select *
from (select st.*, rownum rownum1 from emp st where rownum <= (select count(*) from emp)) t
where rownum1 >= 10;


--视图就是一张临时表,不能往视图中插入、修改、删除数据,只能查询数据
---切换至sys账户---
create or replace view v_emp
as
select u.*, rownum rownum1 from USER$ u where rownum <= 10;

rename v_emp to v_temp;

drop view v_temp;


---- "索引"就是一本书的目录,提升查询数据的效率
create index i_student_name on t_student(name);
drop index i_student_name;
create unique index i_studnet_name on t_student(name);

-------- 数据备份 ---------

--*********** 导出表数据 ***********
步骤:
1、选择PL/SQL菜单栏的Tools下面的Export Tables
2、切换到"SQL Inserts"窗口
3、选择"Create tables"
4、在Output file处,选择输出的地址,并自定义好以 .sql 结尾的文件名字,如 emp.sql
5、点击Output file最右边的Export按钮即可。


--*********** 导入表数据 ***********
步骤:
1、选择PL/SQL菜单栏的Tools下面的Import Tables
2、切换到"SQL Inserts"
3、选择“Use Command Window”
4、在Import file中选择要导入的sql文件
5、点击Import file最右边的Import按钮即可。