一.DBMS 和 DB
1.DBMS 是什么
数据库管理系统 是管理数据库的软件
2.DB 是什么
真正存储数据的文件
3.RDBMS 和 RDB
关系型数据库管理系统 和 关系型数据库
基于二维表的数据库 就是关系型数据库
4.二维表中的基本概念
表头
行
列
字段名
字段值
5.关系型数据库的代表
oracle 甲骨文 oracle9i oracle10g
oracle11g
DB2 IBM
sqlserver 微软
mysql sun--->oracle
二.操作数据库的语言SQL(结构化查询语言)
1.查询
select
2.数据定义的语句 DDL
create table
drop table
alter table
3.数据操作语句 DML
insert
delete
update
4.事务控制语句 TCL
commit
rollback
savepoint
三.如何使用服务器上的数据库
1.远程登录服务器
telnet 服务器IP
2.输入用户名 密码
3.输入指令
sqlplus
4.输入用户名 密码
5.自动进入sql编程环境
SQL> !clear
四.使用Sql的编程环境 查看数据库中的表结构
SQL>desc 表名;
SQL> desc s_emp;
Name Null? Type
----------------------------------------- -------- ------------------
ID 员工编号 NOT NULL NUMBER(7)
LAST_NAME 姓 NOT NULL VARCHAR2(25)
FIRST_NAME 名 VARCHAR2(25)
USERID 用户编号 VARCHAR2(8)
START_DATE 入职日期 DATE
COMMENTS 备注 VARCHAR2(255)
MANAGER_ID 领导的员工编号 NUMBER(7)
TITLE 职位 VARCHAR2(25)
DEPT_ID 部门编号 NUMBER(7)
SALARY 月薪 NUMBER(11,2)
COMMISSION_PCT 提成 NUMBER(4,2)
1.查看表结构可以得到的信息 表头中每个字段的名
2.字段是否必须有值 如果必须有值 则显示
成 not null
3.可以得到字段名的类型
number 数字类型
varchar2 字符串类型
date 日期类型
查询每个人的月薪
select salary from s_emp;
SELECT salary FROM s_emp;
------------------------------------------------
查询语句select语句
一.from子句
1.如何从表中查询一个字段的值
1.1 语法
select 字段名 from 表名;
1.2 查询s_emp 表中的所有的 id
select id from s_emp;
2.如何从表中 查询多个字段的值
2.1 语法
select 字段名1,字段名2 from 表名;
2.2 把s_emp 表中的 id first_name salary
显示出来。
select id,first_name,salary from s_emp;
3.如何查询所有的字段的值
select id,first_name
*号可以代表所有的字段名
select * from s_emp;
4.sql中的数学运算
+ - * /
4.1 把每个员工的工资 和 工资加100之后显示出来
select salary,salary+100 from s_emp;
4.2 把每个员工的月薪 和 年薪显示出来
select salary,salary*13 from s_emp;
5.字段或者表达式的别名
5.1 语法就是在字段 或者表达式后另起一个名字
5.2 显示月薪 和 年薪的别名
select salary monsal,salary*13 yearsal from s_emp;
5.3 别名默认处理成大写 别名只能有一个
别名中有空格字符或者想原样显示
select salary monsal,salary*13 year sal from s_emp;
5.4 使用双引号 可以把多个对象看成一个整体
可以使别名原样显示
select salary "monsal",salary*13 "Year sal" from s_emp;
6.sql中如何表达字符串
6.1 语法
使用单引号 引起一串字符
6.2 举例
'' ' ' 'a' '&' 'hello world'
6.3 oracle 中如何拼接字符串
6.3.1 使用字符串拼接符号 ||
6.3.2 举例
select first_name||last_name from s_emp;
6.3.3 在first_name 和 last_name 之间拼接一个下划线字符
select first_name||'_'||last_name from s_emp;
6.3.4 思考如何在first_name 和last_name 之间拼接一个单引号
%d %lf %%表达一个%
select first_name||''''||last_name from s_emp;
6.3.5 在first_name 和 last_name 之间拼接两个单引号
select first_name||''''''||last_name from s_emp;
select first_name||''''||''''|| last_name from s_emp;
7.NULL 值的处理
7.1 查询 s_emp 表中所有 id,salary 以及对应 commission_pct
select id,salary,commission_pct from s_emp;
7.2 按照这种方式计算年薪 月薪乘以12 再加上月薪乘以12乘以提成除以100
select salary*12,salary*12+salary*12*(commission_pct/100) from s_emp;
任何值和NULL 做运算结果都是NULL
7.3 oracle中如何 处理NULL值
nvl(par1,par2) NULL值处理函数
par1如果为NULL 则返回par2的值
par1如果不为NULL 就返回par1的值
NULL 要尽早处理
select salary*12, salary*12+salary*12*(nvl(commission_pct,0)/100) from s_emp;
7.4 要求显示 s_emp 表中的 id first_name manager_id 如果manager_id 为NULL 则显示成 -1
select id,first_name,nvl(manager_id,-1) from s_emp;
8.数据的排重显示
8.1 distinct 关键字完成
select salary from s_emp;
select distinct salary from s_emp;
select distinct id from s_emp;
8.2 联合排重
id salary
1 800
2 800
2 800
显示 id salary 如果id 和salary 的值都相同 就只显示一次
select distinct id,salary from s_emp;
select title,salary from s_emp;
select distinct title,salary from s_emp;
二.where 子句(条件子句)
1.作用
限制表中的行数据的返回
符合where条件的数据 就返回 不符合where 条件的数据就被过滤掉。
2.两个极端条件
select salary from s_emp;
select salary from s_emp where 1=1;
select salary from s_emp where 1!=1;
no rows selected
3.number 类型数据的条件判断
3.1 把s_emp 表中 id salary 显示出来
要求显示 salary 大于1200的
select id,salary from s_emp where salary>1200;
3.2 把s_emp 表中 id salary 显示出来
要求显示 salary 等于1200的
select id,salary from s_emp where salary=1200;
4.字符串类型的条件判断
4.1 找出first_name 是mark 的 id first_name salary 显示出来
select id,first_name,salary from s_emp where first_name='mark';
sql语句不区分大小写
字符串的值是区分大小写的
字符串的值要加单引号
5.找出工资 在[1200,1400] 范围内的员工 的id first_name salary
where 字段 between a and b
表达闭区间
select id,first_name,salary from s_emp where salary between 1200 and 1400;
6.sql提供的其它运算符
6.1 where 字段 between a and b 表达一个闭区间
6.2 where 字段 in (列表)
列表 值1,值2,值3
where id in (1,3,7)
查询s_emp 表中部门编号 在 31 或者 32 或者 50 部门 的员工的 id first_name 以及部门编号
select id,first_name,dept_id from s_emp where dept_id in(31,32,50);
数据出现概率高的放前面
6.3 模糊查询
6.3.1 需求
找出所有姓王的人 王王王
王宝强
王安石
找出所有数据中带龙
李小龙
龙孩儿
小龙女
ls *.txt
6.3.2 统配符
% 代表0-n个任意字符
_ 代表一个任意字符
'王%' '%龙%' 统配串
6.3.3 模糊查询关键字
where 字段 like '统配串'
找出s_emp 表中 first_name 所有带a的
select first_name from s_emp where first_name like '%a%';
找出s_emp 表中 first_name 所有倒数第二个 字符是a的
select first_name from s_emp where first_name like '%a_';
6.3.4 特殊的模糊查询
字符串中 带 %或者_ 的模糊查询
s_emp
s_dept
6.3.4.1 找出所有的S 开头的表名
desc user_tables;
其中一个字段 是table_name
select table_name from user_tables where table_name like 'S%';
找出所有的S_开头的表名
select table_name from user_tables where table_name like 'S\_%' escape '\';
6.3.4.2 找出所有的S__开头的表名
select table_name from user_tables where table_name like 'S\_\_%' escape '\';
6.4 NULL 值的判断
6.4.1 使用where 字段 is null
找出提成等于10 的人的 id first_name和commission_pct
select id,first_name,commission_pct from s_emp where commission_pct=10;
找出提成不等于10 的人的 id first_name和commission_pct
select id,first_name,commission_pct from s_emp where commission_pct!=10;
6.4.2 判断NULL 使用is null
select id,first_name,commission_pct from s_emp where commission_pct is null;
6.4.3 找出manager_id 是NULL 的 员工
列出id salary manager_id
select id,salary,manager_id from s_emp where manager_id is null;
7.逻辑条件链接符
and 连接的条件都为真 则条件为真
or 只要有一个条件为真 则条件为真
not
7.1 求工资在[800,1200] 的员工 列出
id first_name salary
select id,first_name,salary from s_emp where salary>=800 and salary<=1200;
7.2 求部门号 在 31 或者 32 或者 50
中的员工的id first_name dept_id
select id,first_name,dept_id from s_emp where dept_id=31 or dept_id=32 or dept_id=50;
7.3 not
= != <> ^=
< >=
> <=
between a and b not between a and b
in not in (注意NULL值)
like not like
is null is not null
找出提成不是NULL 员工 的
id,first_name,commission_pct
select id,first_name,commission_pct from s_emp where commission_pct is not null;
三.数据排序
1.概念
把数据 按照升序 或者降序 排列显示
2.order by 排序标准 排序方式
2.1 排序方式
升序 默认的顺序 asc 自然顺序 字典顺序
降序 desc
2.2 出现的位置
永远出现在sql语句最后
3.举例
3.1 查询s_emp 表中 id,first_name,salary
按照工资排序显示
select id,first_name,salary from s_emp
order by salary;
3.2 查询s_emp 表中 id,first_name,salary
按照工资降序显示
select id,first_name,salary from s_emp
order by salary desc;
4.NULL值在排序中的处理
按照manager_id 排序显示 id,first_name,
manager_id
select id,first_name,manager_id
from s_emp order by manager_id;
结论:NULL 在排序中做最大值处理
5.多字段排序
5.1 概念
当第一排序的值相同时 可以启用第二排序字段
来对数据进行排列
5.2 举例
按照工资排序 如果工资相同 则按照id降序排列
select id,first_name,salary from s_emp
order by salary,id desc;
6.总结:
order by 排序标准 排序方式,第二排序标准
排序方式。
四.单行函数
1.单行函数 和 组函数的概念
单行函数:对sql语句的每一行数据都返回一个处理
结果,sql语句影响多少行就返回多少个结果。
组函数:对sql语句影响的所有数据 统一处理返回
一个结果,无论sql语句影响多少行 都返回一
个结果。
2.举例
2.1 单行函数 upper
select first_name,upper(first_name)
from s_emp;
2.2 组函数 count
select count(first_name) from s_emp;
select first_name,count(first_name)
from s_emp;
3.单行函数的测试
dual 表 是一张单行 单列的表
select upper('hello world') from dual;
4.oracle中常见的处理字符串的函数
4.1 upper(par1) 变大写
4.2 lower(par1) 变小写
select lower('HELLO World') from dual;
4.3 initcap(par1) 把每个单词的首字母变大写
select initcap('one world one dream')
from dual;
4.4 length(par1) 求字符串的长度
select length('hello') from dual;
4.5 concat(par1,par2) 连接字符串
用的很少 因为有||
4.6 substr(par1,par2,par3)
4.6.1 参数含义
par1 要处理的字符串
par2 从什么位置开始截取 默认从1开始编号
也可以是负数-1 代表最后一个字符的位置
par3 截取多少个字符
4.6.2 举例
把s_emp 表中 first_name 和 first_name
前三个字符截取下来
select first_name,substr(first_name,
0,3) from s_emp;
select first_name,substr(first_name,
1,3) from s_emp;
把s_emp 表中 first_name 和 first_name
后三个字符截取下来
select first_name,substr(first_name,
-3,3) from s_emp;
4.7 nvl(par1,par2) NULL值处理函数
par1 和 par2 的类型要一致
5.数字处理函数
5.1 round(par1,par2) 四舍五入
5.1.1 参数
par1 要处理的数据
par2 指定小数保留的位数 par2可以省略
5.1.2 举例
select round(12.88) from dual;
select round(12.88,1) from dual;
select round(12.874,2) from dual;
/* 对小数点前 第几位进行四舍五入 */
select round(12.874,-1) from dual;
select round(12.874,-2) from dual;
5.2 trunc(par1,par2) 截取
5.2.1 参数
par1 要处理的数据
par2 指定小数保留的位数 par2可以省略
5.2.2 举例
select trunc(12.88) from dual; 12
select trunc(12.88,1) from dual; 12.8
select trunc(12.874,2) from dual;12.87
/* 对小数点前 第几位进行四舍五入 */
select trunc(12.874,-1) from dual; 10
select trunc(12.874,-2) from dual; 0
6.数字格式显示函数
6.1 to_char(par1,par2)
par1是要处理的数据
par2 是格式 可以省略 代表把一个数据类型
变成字符串类型
格式以 fm开头
9 小数点前代表0-9的任意数字
小数点后代表1-9的任意数字
999.99 999.00
123 123. 123.00
0 小数点前代表 强制显示前导零
12345.67 012,345.67
小数点后 代表 0-9的任意数字
$ 美元符号
L 本地货币符号 ¥ RMB
, 分隔符号
. 小数点
6.2 举例
6.2.1 以fm$099,999.99 显示s_emp 中的数据
select salary, to_char(salary,'fm$099,999.99') from s_emp;
6.2.2 以fmL099,999.99 显示s_emp 中的数据
select salary, to_char(salary,'fmL099,999.99') from s_emp;
6.3 如何修改本地语言
1.进入服务的shell 切换shell
bash
2.修改配置文件
vi .bash_profile
3.写入环境变量
export NLS_LANG
='SIMPLIFIED CHINESE_CHINA.ZHS16GBK'
4.保存退出 让配置生效
source .bash_profile
5.重新进入sqlplus
7.函数嵌套
7.1 概念
把一个函数的返回值 作为另一个函数的参数
7.2 列子
7.2.1得到s_emp 表中first_name,first_name 的后三个字符(length substr)
select first_name, substr(first_name,length(first_name)-2,3) from s_emp;
7.2.2 把下面的连接改成 concat 的形式
select first_name||'_'||last_name from s_emp;
select concat(concat(first_name,'_'),last_name) from s_emp;
7.2.3 显示s_emp 表中 first_name,
manager_id 如果manager_id 为NULL 则显示成BOSS
select first_name,nvl(to_char(manager_id), 'BOSS') from s_emp;
五.多表查询
1.概念
查询的数据 分布在多张表中,所以需要根据条件把表连接起来 形成一张表。
2.列子
把每个员工的first_name和对应的 部门编号查询出来
select first_name,dept_id from s_emp;
s_dept 部门表
SQL> desc s_dept;
Name Null? Type
----------------------------------------- -------- ----
ID 部门编号 NOT NULL NUMB
NAME 部门名 NOT NULL VARC
3.在第二个例子的基础上 显示部门名
3.1笛卡尔积
select first_name,dept_id,name from s_emp,s_dept;
笛卡尔积 两张表匹配的所有可能
3.2 表连接时注意连接
select first_name,dept_id,name from s_emp,s_dept where dept_id=s_dept.id;
结论:表中有同名字段时 可以使用表名区分
4.表连接的练习
s_dept
id 部门编号
name 部门名
region_id 地区编号
s_region
id 地区编号
name 地区名
列出部门名 和 部门对应的地区名
select s_dept.name,s_region.name from s_dept,s_region where region_id=s_region.id;
5.使用表的别名 对上面程序进行简化
select d.name,r.name from s_dept d,s_region r where region_id=r.id;
6.把员工的first_name 和 对应的部门名以及部门对应的地区名 显示出来
select e.first_name,d.name,r.name from s_emp e,s_dept d,s_region r
where e.dept_id=d.id and d.region_id=r.id;
设置name的这一列一行最多显示15个字符
col name for a15;
7.上面的连接条件都是用等号作为连接符号则称之为等值连接。
如果连接两张表的连接符号 不是等号则称之为非等值连接。
7.1 工资级别表 salgrade
得到初始化脚本 上传到服务器
进入sqlplus 执行脚本
SQL>@路径名/脚本名
SQL> desc salgrade;
Name
--------------------
GRADE 工资等级
LOSAL 这个等级低工资
HISAL 这个等级的高工资
7.2 列出每个员工的id,工资 和 工资对应的工资级别。
select id,salary,grade from s_emp ,salgrade where salary between losal and hisal;
8.特殊的表连接(自连接)
把两层业务含义的数据放到了一张表中。
s_emp 表有普通员工 和 领导
把s_emp 表中所有的领导查询出来
id manager_id
9527 9527
9528 9527
9529 9527
有员工的领导id 是你的id 则你是领导
select id,first_name from s_emp where manager_id=id;
六 表连接的总结
1.内连接
等值连接 员工名和对应的部门名
非等值连接 工资和工资对应的级别
自连接 谁是领导
符合连接条件 数据就被选中 不符合连接条件数据就被过滤掉。这种总称为内连接。
2.列出每个部门名 和 部门对应的地区名
select d.name,r.name from s_dept d,s_region r where d.region_id=r.id;
公司业务发展 增加了新的部门
insert into s_dept values(101,'Test1',NULL);
commit;
3.外连接:目的就是为了找回在内连接连接时 丢掉的不符合条件的数据。
外连接的结果集 等于内连接的结果集加上匹配不上记录。(一个也不能少)
(+) (+)字段对面的表的数据全部被匹配出来
select d.name,r.name from s_dept d,s_region r where d.region_id=r.id(+);
4.列出所有的员工id first_name和员工对应部门名
select e.id,e.first_name,d.name from s_emp e,s_dept d where e.dept_id=d.id;
把老板开除即 把老板的dept_id 变成NULL
update s_emp set dept_id=NULL where id=1;
commit;
列出所有员工 包括没有部门的员工
select e.id,e.first_name,d.name from s_emp e,s_dept d where d.id(+)=e.dept_id;
5.思考如何使用外连接找出所有的普通员工
列出id 和first_name
/* 找回过滤掉的员工 */
select distinct m.id,m.first_name from s_emp e,s_emp m where e.manager_id(+)=m.id;
/* 过滤掉的哪部分员工就是假领导 */
select distinct m.id,m.first_name from s_emp e,s_emp m where e.manager_id(+)=m.id and e.manager_id is null;
6.列出员工的id salary 和 工资对应的工资级别
select id,salary,grade from s_emp,salgrade where salary between losal and hisal;
/*给老板涨工资*/
update s_emp set salary=12500 where id=25;
commit;
select id,salary,grade from s_emp,salgrade where salary between losal(+) and hisal(+);
七.(+) 是oracle的外连接
SQL99 sql标准委员会 规定了内外连接的标准
7.1 SQL99内连接:
from a表 join b 表 on 连接条件;
from a表 inner join b 表 on 连接条件;
from a表 ,b 表
where 连接条件;
列出每个员工的first_name 和对应的部门名
select first_name,d.name from s_emp e,s_dept d where e.dept_id=d.id;
select first_name,d.name from s_emp e join s_dept d on e.dept_id=d.id;
7.2 SQL99的外连接
from a表 left outer join b表 on 连接条件;
from a表 right outer join b表 on 连接条件;
from a表 full outer join b表 on 连接条件;
多表查询
表连接:
内连接:在表连接时 符合连接条件的数据 就被选中,不符合连接条件的就被过滤掉。
等值连接:员工 部门 地区
非等值连接:员工工资 和 工资级别
自连接:谁是领导
外连接:外连接的结果集 等于内连接的结果集 加上匹配不上的记录。
(+) (+)字段对面表的数据全部被匹配出来
等值连接:员工 部门 地区
非等值连接:员工工资 和 工资级别
自连接:谁是领导
一.SQL99 中的内外连接
1.sql99中内连接
from a 表 join b表 on 连接条件;
from a 表 inner join b表 on 连接条件;
2.把每个部门名 和对应的地区名显示出来
s_dept
s_region
select d.name,r.name from s_dept d,s_region r where d.region_id=r.id;
select d.name,r.name from s_dept d join s_region r on d.region_id=r.id;
3.sql99 中的外连接
3.1把每个部门名 和对应的地区名显示出来
即使没有对应的地区名 也要显示出这个部门
select d.name,r.name from s_dept d,s_region r
where d.region_id=r.id(+);
3.2 语法
from a表 left outer join b 表 on 连接条件;
from a表 right outer join b 表 on 连接条件;
要把a表的数据全部匹配出来 就让a表发起连接。
select d.name,r.name from s_dept d left outer join s_region r
on d.region_id=r.id;
select d.name,r.name from s_region r right outer join s_dept d
on d.region_id=r.id;
3.3 谁是普通员工?
(+) 实现之后 再使用left outer join 实现
select distinct m.id,m.first_name from s_emp e,s_emp m
where e.manager_id(+)=m.id and e.manager_id is null;
select distinct m.id,m.first_name from s_emp m left outer join s_emp e
on e.manager_id=m.id where e.manager_id is null;
3.4 全外连接:全外连接的结果集 等于左外连接的
结果集 加上右外连接结果集 减去重复的记录。
a 表 full outer join b表 on 连接条件;
oracle 中不是通过两端都加(+)
union 合并两个结果集 排重
union all 合并两个结果集
select id from s_emp union select id from s_emp;
select id from s_emp union all select id from s_emp;
二. 组函数
1. 特点就是对一组数据处理之后 得到一个结果。
2. 常见的组函数
count 统计数据个数
max 统计最大值
min 统计最小值
avg 统计平均值
sum 统计和
3. 统计 s_emp 表中的人数 统计工资的最大值和 工资的最小值
select count(id),max(salary),min(salary) from s_emp;
4. 统计s_emp 中工资的平均值 和工资的和
select avg(salary),sum(salary), sum(distinct salary) from s_emp;
组函数中可以使用 distinct
5. 组函数对NULL值的处理 是忽略的
统计s_emp 表中提成的个数 和 提成的和
commission_pct select count(commission_pct), sum(commission_pct) from s_emp;
三. 分组
1.概念
按照一定的标准 把数据分成若干组
2.group by 分组标准 (用在where后)
select dept_id,count(id) from s_emp
where 1=1 group by dept_id;
3.按照部门号分组,统计每个部门的人数
能不能把部门名显示出来?
select dept_id,count(s_emp.id),max(name) from s_emp,s_dept
where dept_id=s_dept.id group by dept_id;
在分组语句中 select 后的字段要么是分组标准
要么是经过合适的组函数处理过的。
select dept_id,count(s_emp.id),name from s_emp,s_dept
where dept_id=s_dept.id group by dept_id,name;
4.对组数据的过滤 having
按照部门号分组,统计每个部门的平均工资
要求显示工资大于 1500
select dept_id,avg(salary) asal from s_emp
where asal>1500 group by dept_id; /* error */
from
where
group by
select dept_id,avg(salary) asal from s_emp
group by dept_id having asal>1500; /* error */
from
where
group by
having
select
order by
select dept_id,avg(salary) asal from s_emp group by dept_id
having avg(salary)>1500 order by asal;
5.按照部门号 分组 求每个部门的人数
要求显示人数大于1的部门
要求按照部门号排序
要求显示部门名
select dept_id,count(e.id),max(d.name) from s_emp e,s_dept d
where e.dept_id=d.id group by dept_id having count(e.id)>1 order by dept_id;
四.子查询
4.1 概念
把一个查询的结果 作为另一个查询的基础
4.2 举例
/* 找出所有的领导id */
select distinct manager_id from s_emp;
/* 让员工的id出现在领导id中 */
select id,first_name from s_emp where id in( select distinct
manager_id from s_emp );
/* 使用子查询找出所有的普通员工?
注意NULL */
select id,first_name from s_emp where id not in(
select distinct manager_id from s_emp where manager_id is not NULL);
commission_pct=10 2
commission_pct!=10 or commission is null
4.3 子查询 还可以用在 having 之后
求平均工资大于 41部门平均工资的
select avg(salary) from s_emp where dept_id=41;//1510
select dept_id,avg(salary) from s_emp group by dept_id
having avg(salary)>(select avg(salary) from s_emp where dept_id=41);
4.4 子查询 用在 from 后面
任何一条sql语句 都对应内存中的一张表
select id,first_name name,salary from s_emp;
select id,name from ( select id, first_name name,salary from s_emp ) where id>10;
求平均工资大于 41部门平均工资的
select*from(select dept_id,avg(salary) asal from s_emp group by dept_id) where
asal>(select avg(salary)from s_emp where dept_id=41);
五.表的操作
5.1 如何建立表
create table 表名(
字段名 类型,
字段名 类型,
字段名 类型
);
5.2 建立一张员工表 myemp
id number
name varchar2(30)
salary number
drop table myemp;
create table myemp(
id number,
name varchar2(30),
salary number
);
5.3 删除表
drop table 表名;
drop table myemp;
5.4 建立一张订单表 myorder123
id number
name varchar2(50)
money number
odate date
drop table myorder9526;
create table myorder9526(
id number,
name varchar2(50),
money number,
odate date
);
desc myorder9526;
六.对表中数据的操作
create table myorder19527(
id number,
name varchar2(50),
money number,
odate date
);
6.1.增加数据 insert
6.1.1 insert into 表名 values(字段值1,字段值2,字段值3);
insert into myorder19527 values(1,'test1',1888.88,NULL);
6.1.2 insert into 表名(字段名1,字段名3) values(字段值1,字段值3);
选择部分字段插入数据 必须包含所有的非空字段。
没有选择的字段当做NULL值插入数据库
insert into myorder19527(id) values(1001);
6.1.3 向s_dept 表中放入数据
insert into s_dept values(100,'test', NULL);
6.2 删除数据 delete
delete from 表名 where 条件;
delete from myorder19527 where id=1001;
6.3 修改数据 update
update 表名 set 字段名=值, 字段名2=值2 where 条件;
update myorderbdl set id=9527 ,name='zhouxingxing' where id=1;
commit;
create table myorderbdl(
id number,
name varchar2(50),
money number,
odate date
);
insert into myorderbdl values( 1,'test1',1888.88,NULL);
commit;
七.数据库中的事务操作
原子性:一个事务中sql语句,是不可分隔的整体。
转账
update account set money=money-20000
where ano='A';
a
update account set money=money+20000
where ano='B';
b
if(a&&b){
/* 确认这次操作 */
commit;
}else{
/* 撤销这次操作 */
rollback;
}
隔离性:一个事务中的操作 在没有提交以前
数据的变化 不能被另一个事务发现数据
的变化。
update s_emp set salary=salary+2000 where id=1;
insert delete update 是有事务操作的
select 没有事务可言
create drop 事务自动提交
持久性
一致性
事务的补充:
事务中的语句一起成功 一起失败太严格
部分成功 部分失败
update account set money=money-0.1 where ano='1581100****';
savepoint a;
insert into logtable values();
发送短信
savepoint b;
update logtable
savepoint c;
if(a&& b&& c){
commit;
}else{
rollback to b;
commit;
}
update account ...;
savepoint a;
insert into ....;
savepoint b;
update account ... ;
rollback to a;
commit;
八.日期类型的操作
8.1 日期的默认格式
'dd-MON-yy'
'23-DEC-13'
'23-12月-13'
select start_date from s_emp;
8.2 四位年
按照入职日期排序 显示 id first_name
start_date
select id,first_name,start_date from s_emp order by start_date;
to_char(日期数据,'日期格式')
yyyy 四位年
mm 两位月
dd 两位天
hh 12小时制
hh24 24小时制
mi 分钟
ss 秒
MON 月的英文缩写
month 月的英文全写
pm am pm
day 星期几
select id,first_name, to_char(start_date,
'yyyy-mm-dd hh24:mi:ss') from s_emp order by start_date;
select id,first_name, to_char(start_date,
'yyyy-mm-dd hh24:mi:ss mon day pm') from s_emp order by start_date;
8.3 如何插入日期
建立一张订单表 myorder1112
id varchar2(50)
name varchar2(50)
money number
odate date
create table myorder1112(
id varchar2(50),
name varchar2(50),
money number,
odate date
);
insert into myorder1112 values('bj001','bjolp00001',280000,'08-AUG-08');
select to_char(odate,'yyyy-mm-dd hh24:mi:ss') from myorder1112;
默认无法放入时分秒信息 默认是00:00:00
8.4 to_date(par1,par2)
par1 要处理的日期字符串
par2 日期字符串的格式
'2008-08-08 20:08:08'
'yyyy-mm-dd hh24:mi:ss'
insert into myorder1112 values( 'bj002','bjolp00002',290000,
to_date('2008-08-08 20:08:08', 'yyyy-mm-dd hh24:mi:ss'));
'2012-12-20 23:59:59'
八.日期类型的操作
8.1 日期的默认格式
'dd-MON-yy'
'23-DEC-13'
'23-12月-13'
select start_date from s_emp;
8.2 四位年
按照入职日期排序 显示 id first_name
start_date
select id,first_name,start_date from s_emp order by start_date;
to_char(日期数据,'日期格式')
yyyy 四位年
mm 两位月
dd 两位天
hh 12小时制
hh24 24小时制
mi 分钟
ss 秒
MON 月的英文缩写
month 月的英文全写
pm am pm
day 星期几
select id,first_name, to_char(start_date, 'yyyy-mm-dd hh24:mi:ss') from s_emp order by start_date;
select id,first_name, to_char(start_date, 'yyyy-mm-dd hh24:mi:ss mon day pm') from s_emp order by start_date;
8.3 如何插入日期
建立一张订单表 myorder1112
id varchar2(50)
name varchar2(50)
money number
odate date
create table myorder1112(
id varchar2(50),
name varchar2(50),
money number,
odate date
);
insert into myorder1112 values( 'bj001','bjolp00001',280000,'08-AUG-08');
select to_char(odate,'yyyy-mm-dd hh24:mi:ss') from myorder1112;
默认无法放入时分秒信息 默认是00:00:00
8.4 to_date(par1,par2)
par1 要处理的日期字符串
par2 日期字符串的格式
'2008-08-08 20:08:08'
'yyyy-mm-dd hh24:mi:ss'
insert into myorder1112 values( 'bj002','bjolp00002',290000, to_date('2008-08-08 20:08:08', 'yyyy-mm-dd hh24:mi:ss'));
'2012-12-20 23:59:59'
to_date('2012-12-20 23:59:59', 'yyyy-mm-dd hh24:mi:ss')
8.5 代表系统时间的函数
sysdate
select to_char(sysdate, 'yyyy-mm-dd hh24:mi:ss') from dual;
insert into myorder1112 values( 'bj0001','bjtest',18888,sysdate);
select to_char(odate,'yyyy-mm-dd hh24:mi:ss') from myorder1112;
8.6 日期的调整
8.6.1 按照天进行调整
select to_char(sysdate, 'yyyy-mm-dd hh24:mi:ss'),
to_char(sysdate+8, 'yyyy-mm-dd hh24:mi:ss') from dual;
8.6.2 按照小时为单位进行调整
select to_char(sysdate, 'yyyy-mm-dd hh24:mi:ss'),
to_char(sysdate+1/24, 'yyyy-mm-dd hh24:mi:ss') from dual;
8.6.3 按照分钟 秒为单位调整
select to_char(sysdate, 'yyyy-mm-dd hh24:mi:ss'),
to_char(sysdate+31/(24*60), 'yyyy-mm-dd hh24:mi:ss') from dual;
select to_char(sysdate, 'yyyy-mm-dd hh24:mi:ss'),
to_char(sysdate-1/(24*60*60), 'yyyy-mm-dd hh24:mi:ss') from dual;
8.6.4 按照月为单位进行调整
add_months(par1,par2)
par1要调整的日期
par2 要调整几个月 正数向后调整 负数向前调
select to_char(add_months(sysdate,-2),
'yyyy-mm-dd hh24:mi:ss')
from dual;
8.6.5 得到一个日期对应月的最后一天
last_day(par1)
select to_char(last_day(sysdate),
'yyyy-mm-dd hh24:mi:ss') from dual;
8.6.6 下一个星期几
next_day(par1,par2)
par1 要处理的日期
par2 星期几
select next_day(sysdate,'monday') from dual;
select next_day(sysdate,'friday') from dual;
select next_day(next_day(sysdate, 'friday'),'friday') from dual;
8.6.7 日期的其它处理
8.6.7.1 round(par1,par2)
par1 要进行四舍五入的日期
par2 按照什么单位进行四舍五入 默认是dd
select to_char(round(sysdate), 'yyyy-mm-dd hh24:mi:ss') from dual;
select to_char(round(sysdate,'mm'), 'yyyy-mm-dd hh24:mi:ss') from dual;
8.6.7.2 trunc(par1,par2)
par1 要进行截取的日期
par2 按照什么单位进行截取 默认是dd
select to_char(trunc(sysdate), 'yyyy-mm-dd hh24:mi:ss') from dual;
select to_char(trunc(sysdate,'mm'), 'yyyy-mm-dd hh24:mi:ss') from dual;
---------------------------------------------
日期综合练习
给定一个日期 得到这个日期对应月的最后一天
最后一秒 使用 to_char做验证
sysdate 2013-12-31 23:59:59
2008-08-08 2008-08-31 23:59:59
select to_char(trunc(last_day(sysdate)) +1-1/(24*60*60),'yyyy-mm-dd hh24:mi:ss') from dual;
trunc(add_months(sysdate,1),'mm')-1/(24*60*60)
select to_char(trunc(add_months(sysdate,1),'mm') -1/(24*60*60),'yyyy-mm-dd hh24:mi:ss') from dual;
last_day(trunc(sysdate,'mm'))+1-1/(24*60*60)
-------------------------------------------------
九.数据库中的约束
9.1 概念
对表中的字段 加的一些限制
9.2 约束的具体种类
9.2.1主键约束 primary key
字段的值必须非空 并且不能重复
一个表只能有一个主键
9.2.2 唯一性约束 unique
代表值不能重复
9.2.3 非空约束 not null
字段的值不能是NULL值
9.2.4 检查约束 check
字段的值必须符合检查条件 否则报错
9.2.5 外键约束 references
foreign key
9.3 约束的实现方式
9.3.1 列级约束
在定义表的某一列时 直接在这一列的后面
加约束限制。
9.3.1.1 主键的列级约束
create table test_columncons(
id number primary key,
name varchar2(30)
);
insert into test_columncons values(1,'test');
ERROR at line 1:
ORA-00001: unique constraint
(OPENLAB.SYS_C00393099) violated
如果不给约束起名字 则系统会自动提供
一个约束名。
9.3.1.2 给约束起名字
drop table test_columncons;
create table test_columncons(
id number constraint
test_columncons_id_pk primary key,
name varchar2(30)
);
insert into test_columncons values(1,'test');
ERROR at line 1:
ORA-00001: unique constraint
(OPENLAB.TEST_COLUMNCONS_ID_PK) violated
9.3.1.3 使用列级约束 完成一张表
要求表有三个字段 id number
要求设置成主键 name varchar2(30)
要求设置成唯一 sname varchar2(30)
要求设置成非空
create table test_columncons(
id number constraint
test_columncons_id_pk primary key,
name varchar2(30) constraint
test_columncons_name_uk unique,
sname varchar2(30) constraint
test_columncons_sname_nn not null
);
9.3.1.4 使用列级约束 建立一张表 有两个字段
id number 设置成主键salary number 要求符合检查条件工资大于3500
create table testemp1007(
id number constraint
testemp1007_id_pk primary key,
salary number constraint
testemp1007_salary_ck
check(salary>3500)
);
insert into testemp1007 values(
1,3501);
9.3.2 表级约束
在定义完表的所有列之后 再选择某些列加约束限制。
表级约束可以完成联合约束
create table testemp1008(
id number,
name varchar2(30),
salary number,
constraint testemp1008_id_pk
primary key(id),
constraint testemp1008_name_uk
unique(name),
constraint testemp1008_salary_ck
check(salary>3500)
);
在数据库层面上 没有联合非空的需求导致非空没有表级别的形式
id name
1 a
1 c
9.4 外键约束
9.4.1 概念
一个表的一个字段的值 要参考或者引用另一张表的字段的值。子表中的外键字段值要么取NULL 要么是父表字段对应的值。
9.4.2 实现
create table parent191(
id number constraint
parent191_id_pk primary key,
name varchar2(30)
);
create table child191(
id number constraint
child191_id_pk primary key,
name varchar2(30),
fid number constraint
child191_fid_fk references
parent191(id)
);
9.4.3 外键中的一些规则
a.建立表 一般先建立父表 后建立子表。先不考虑主外键就可以先建立子表。
b.插入数据 一般先插入父表数据后插入子表数据,除非子表的外键值是NULL
insert into child191 values(1,'test',1);
ORA-02291: integrity constraint
insert into parent191 values(1,'test1');
insert into parent191 values(2,'test2');
insert into child191 values(2,'test2',NULL);
c.删除数据
先删除子表中关联的数据 再删除父表
中的数据。除非使用了级联。
d.删除表?
先删子表 后删子表
drop table parent191 cascade
constraints;
9.4.4 用外键实现一个关系
一个部门中可以有多个员工
一个员工只能属于一个部门
1:m
mydept
id number
name varchar2(30)
myemp
id number
name varchar2(30)
dept_id number
drop table mydept1 cascade constraints;
drop table myemp1 cascade constraints;
create table mydept1(
id number constraint
mydept1_id_pk primary key,
name varchar2(30)
);
insert into mydept1 values(1,'test');
insert into mydept1 values(2,'app');
commit;
create table myemp1(
id number constraint
myemp1_id_pk primary key,
name varchar2(30),
dept_id number constraint
myemp1_dept_id_fk references
mydept1(id)
);
insert into myemp1 values(1,'x',1);
insert into myemp1 values(2,'y',1);
insert into myemp1 values(3,'z',1);
insert into myemp1 values(4,'m',2);
insert into myemp1 values(5,'n',2);
commit;
9.5 级联
on delete cascade 级联删除
on delete set null 级联置空
drop table mydept1 cascade constraints;
drop table myemp1 cascade constraints;
create table mydept1(
id number constraint
mydept1_id_pk primary key,
name varchar2(30)
);
insert into mydept1 values(1,'test');
insert into mydept1 values(2,'app');
commit;
create table myemp1(
id number constraint
myemp1_id_pk primary key,
name varchar2(30),
dept_id number constraint
myemp1_dept_id_fk references
mydept1(id) on delete set null
);
insert into myemp1 values(1,'x',1);
insert into myemp1 values(2,'y',1);
insert into myemp1 values(3,'z',1);
insert into myemp1 values(4,'m',2);
insert into myemp1 values(5,'n',2);
commit;
9.6 把上面的例子改成 表级约束的外键约束
drop table mydept1 cascade constraints;
drop table myemp1 cascade constraints;
create table mydept1(
id number constraint
mydept1_id_pk primary key,
name varchar2(30)
);
insert into mydept1 values(1,'test');
insert into mydept1 values(2,'app');
commit;
create table myemp1(
id number constraint
myemp1_id_pk primary key,
name varchar2(30),
dept_id number,
constraint
myemp1_dept_id_fk
foreign key(dept_id)
references mydept1(id)
on delete set null
);
insert into myemp1 values(1,'x',1);
insert into myemp1 values(2,'y',1);
insert into myemp1 values(3,'z',1);
insert into myemp1 values(4,'m',2);
insert into myemp1 values(5,'n',2);
commit;
--------------------------------
约束:
具体的约束种类
主键 primary key
唯一 unique
非空 not null
检查 check
外键 references foreign key
on delete cascade
on delete set null
列级约束:在定义表的某一列时 直接在这一列
后面加约束限制。
表级约束:在定义完表的所有列之后 再选择某些
列加约束限制。
外键约束:
1.建立表 先建立父表后建立子表
除非使用修改表结构 alter table add
constraint
2.插入数据先插入 父表数据
除非子表的外键值是NULL
3.删除数据
先删除子表中关联的数据
再删除父表数据
除非使用了级联
on delete cascade
on delete set null
4.删除表
一般先删除子表 后删除父表
除非使用 drop table 表
cascade constrints
------------------------------
十.数据库中的其它对象
10.1 序列
10.1.1 作用
用来产生主键的值
10.1.2 如何创建序列
create sequence 序列名;
create sequence myemp1001_id;
CREATE SEQUENCE myemp1001_id
MINVALUE 1
MAXVALUE 9999999
INCREMENT BY 1
START WITH 51
NOCACHE
NOORDER
NOCYCLE;
10.1.3 使用序列
drop table myemp1001;
create table myemp1001(
id number primary key,
name varchar2(30)
);
insert into myemp1001 values(
myemp1001_id.nextval,
'test'||myemp1001_id.currval
);
10.1.4 删除序列
drop sequence 序列名;
drop sequence myemp1001_id;
10.2 索引
10.2.1 作用
加速查询
10.2.2 如何实现底层通过树状结构组织数据 配合消耗空间和消耗时间 来达到加速查询的目的。
3亿条 8分钟
使用索引 0.01秒 0.00
10.2.3 如何创建索引
数据库管理系统 会自动为 唯一性字段建立
索引。
create index 索引名 on 表(字段);
set timing on;
drop table copyemp;
create table copyemp as select *from s_emp;
create index copyemp_salary_ind on copyemp(salary);
10.2.4 删除索引
drop index copyemp_start_date_ind12;
create index copyemp_start_date_ind12 on copyemp(start_date);
10.3 视图
10.3.1 视图的本质
就是一条sql语句
10.3.2 如何创建一个视图
create or replace view 视图名 as select 语句;
create or replace view myview as select id,first_name from s_emp;
select * from myview;
作用可以简化查询可以对同一份物理数据做不同的表现
10.3.3 删除视图
drop view myview;
十一. 分页技术
oracle 中的分页技术 rownum
mysql limit m,n
sqlserver top n
select id,first_name,salary from s_emp;
select rownum,first_name,salary from s_emp;
一页显示10条 要第一页数据
select rownum,first_name, salary from s_emp where rownum<11;
一页显示10条 要第二页数据
select rownum,first_name, salary from s_emp where rownum<21 and rownum>10;
select * from(select rownum r,first_name, salary from s_emp where rownum<21) where r>10;
按照工资排序 每页显示10条 显示第二页数据 先排序 还是先编号? 先排序 后编号
select*from(select rownum r,first_name,salary from(select first_name,salary
from s_emp order by salary) where rownum<2*10+1) where r>(2-1)*10;
最内层select 完成数据的排序
第二层select 完成数据的编号
第三层select 完成rownum 特性的去除
按照工资排序 每页显示10条 显示第三页数据
select*from(select rownum r,first_name,salary from(select first_name,salary
from s_emp order by salary) where rownum<3*10+1) where r>(3-1)*10;