1,为什么使用数据库?
作用,对数据进行持久化的操作
2,数据库的存储结构
表格:用于存储的数据结构
3,数据库分类
- SQL:适用于所有数据库的增删改查,权限分配的结构化查询(查得多)语言 标准sql
- oracle:pl-sql:功能扩展,只适用oracle
- 数据库分类
- 关系型数据库:oracle,mysql,sqlserver
- NOSQL:效率高,不用sql:
- HBase,Redis(存储在内存),
- 文档存储(MongoDB)
- 访问方式
- dos
- 主页
- 客户端
1,备份数据库
mysqldump -u root -p --all-databases>./mysql.sql 备份到当前目录下,带数据备份
2,列操作
添加列:alter table name add(列名,类型 默认值 约束,列名2 类型) 删除列:alter table name drop (zuduan) 修改列名alter table name rename old to new 级联删除表 drop table name cascade constraint 修改列的属性 alter table name modify(列名 类型 默认值....) 删除约束 alter table name drop constraint 约束名;建表时可指定 例:name char constraint1 primary key 批量插入:insert into table() values(),(),(); 授权,并建用户grant all privileges on 库名.* to username@'%' identified by '123'; 查看权限:show grants for renzhiyuan@'%'
一,基本查询
- 简单查询
- 对查询列进行运算
- select name,salary from employee;
- 没有年薪列,可用下面表示.
- select name,salary,salary*12 from employee;
- 对查询列进行运算
- 对查询列起别名
- select name as 姓名 ,salary 月薪,salary*12 年薪 from employee;
- 语法是:列名 as 别名,as可省,别名中有空格需要双引号
- 字符串连接
- --查询姓名,工资
- select last_name||first_name ,salary from employee;(字符串相加用"||")
- 注意:字符串常量往往使用单引号界定起来
- select last_name||' '||first_name ,salary from employee;(两个中间加空格)
- --查询姓名,工资
- 排序
- select 1,2,3,4, from table order by 字段1 asc,字段2 desc(asc升|desc降 默认升序)
- 注意:若排序结果不在select中认可排序
- 条件查询
- 等值比较,!= >=,逻辑运算(and or not),between xxx and xxx,
- where id (not)in(1,2,3,4)查询id在1234中的,
- is(not) null 可以查询某个字段为空
- 多个and 可用between,多个 or 可使用 in
- 模糊查询:%0-n个字符,_一个字符
- 等值比较,!= >=,逻辑运算(and or not),between xxx and xxx,
- 单行函数:作用于 表中的单行数据,每有一行数据执行该函数一次
- sysdata:获取系统当前时间
- to_char(时间类型数据,'日期格式'):select to_cahr(sysdata,'yyyy-mm-dd') from mysql
- 分组(重点)
- group by使用规则:一般分组后求组函数max,min,avg等
- 只有在group by中出现的字段,才能写在select后
- 例:select 籍贯 from student group by 籍贯;只显示能显示籍贯列,去重后显示
- 在group by 中没有出现的字段,则配合组函数也可写在select中
- 在group by中出现的单行函数,在select中可以出现,但必须保证单行函数必须完全相同
- 组函数不能放在where中
- Having(重点)
- 作用:对于分组后结果进行过滤,符合条件留下
- select 籍贯 from student group by 籍贯,having 过滤条件
- 例:统计1997年个月份的员工人数,显示人数超过3人的月份
- 筛选1997年入职的员工where to_char(hire_date,"yyyy")=1997
- 进行分组group by to_cahr(hire_date,"mm")
- select to_cahr(hire_date,"mm"),count(*) from employee
- where to_char(hire_date,"yyyy")=1997
- group by to_cahr(hire_date,"mm")
- having cout(*)>3//having只能在分组后使用
- 先找97年,之后按月份组,显示月份,及人数总数,最后having>3,也可以先月份分组,在havin中选97年 切count>3
- group by使用规则:一般分组后求组函数max,min,avg等
- where 与having区别
- 功能上:where对原始表的数据(from后的表)进行过滤,having对分组后的数据进行过滤,
- where是对于行数据的筛选,having是对于分组数据的的筛选
- where和having在某些情况下可以显示相同的效果但where效率更高,参考sql执行顺序.
- sql执行顺序
- select...
- from 表名
- where 行数据的筛选条件
- group by 分组依据
- having by 分组数据的筛选条件
- order by 排序依据
- 执行顺序:
- from:确定原始表
- where:对原始表的数据进行筛选,符合条件的留下
- group by:对留下的数据基于分组条件进行分组
- having:对分组后数据进行过滤
- select:对于留下的数据进行字段筛选或计算等
- order by:排序永远放在最后执行
伪列
- oracle独有的pl-sql的内容
- rowid
- 根据数据在硬盘中存储的物理地址计算得来,
- 作用:数据的默认索引,底层使用
- rownum对查询结果进行编号,与where同时进行的
- 按顺序对符合条件的数据进行编号
- 例:查询工资前五的员工
- 后面不能放字段,所以伪列放前
- 表别名
- 标明后面加别名
- select * ,rowid from table //错
- select rowid,*from table //对
- select 别名.* ,rowid from table 别名//对
子查询
- 子查询使用在where中
- 如某个查询结果为一条记录中一项(一行一列):把子查询结果作为一个值,直接带入主查询
- a:select max(Salary)from employee;
- b:select* from employee where salary = (a)
- 若为n行一列:也可直接把子查询带入,但是与in连用
- 查询姓名为King员工的同部门员工信息
- select part-id from table where lN="king"//可能有多个数据
- select * from table where part-id in(上面)
- 子查询使用from后面
- n行n列:将子查询当做表二次查询
- 查询工资最高前五:
- tb1:select*from表 order salary desc
- selec *from (tb1) where rowmun<5;
- 查询6-10;
- 先查前十:tb1:selectrowmnu r,*from tab where rowmun<=10//此处rownum不更换
- 在tb1结果基础上查询,rownum>6
- select * from (tb1) where r>6
- 查询工资最高的6-10;
- 工资降序
- 取前10
- 筛选>6的
表连接 join on
- 形成大表
- 分类:内连接,外链接(左右全),交叉连接,自连接
- 内连接
- select*from t1 inner join t2 on 连接条件 where ....
- slect
- from employee e1
- inner join part t2
- on e1.part_id = t2.part_id;
- 特点:1查询结果:符合条件的数据
- 两个表顺序无要求,例:工号 部门号 部门号 部门名 若某一表多一行,大表中无那一行
- 左外连接(顺序有要求,左表为主,左去右找,左边表连接右边表,左找不到右,右部分空)
- left (outer可省) join
- 右外连接(右边为主,右找左,左边无,左则为空)
- right (outer可省) join
- 全外连接
- full (outer可省) join
- 正常的匹配,不正常的左边为空的显示,右边为空的也显示
- 交叉连接
- cross join
- 表一的每条,与表二的所有连接,无条件连接,数量相乘
- 自连接
- 特殊链接 join
- 例:查找课程表中的前驱课程
- select from emp1 join emp2 on 1.名 =2.前取名
- 多表连接的语法
- 查询员工信息,
- select ..from t1 join t2 on 链接条件 join t3 on 条件 join t4 on ..
SQL分类
- DQL:数据库查询语言select(主要)
- DDL:数据定义语言(表一级的,create)
- DML:数据操纵语言(insert)
- DCL:管理员用的grant/revoke
- TCL:Transation Contriller ,事物控制 commit/rollback
DDL
1,建表
create table tablename{ 字段名 类型 默认值 约束1 约束2... }
2,数据类型
- 数字:包含小数,整数,无boolean,一般用char(3),char(1),number(1)表示
- number(n) 整数 长度为n
- number(n,m) 小数加整数n 小数m ,整数 n-m number(5.2)->12-ok,1234-on,12.3->ok但小数位数变多会四舍五入截断,整除则不行
- number(),默认小数类型
- 也有int long ,通常用number
- 字符串:
- 可变varchar2(n) 最大为n 最大4k
- 固定char(n) 长度最大为n 最大2k
- 大数据类型:oracle 独有,不常用
- clob:文本
- blob:大二进制,音频等
- 日期类型:date 毫秒级
3,默认值
- 语法:default 实际值,要与字段类型匹配
4,约束(字段级约束)
- 主键,例:如学号,但若学生学号 用1,2,3,4,5, primary key
- 唯一,表示该类内容不可重复,但可同时为空,unique
- 非空 该列必须要内容 not null
- 检查/自定义 条件筛选 check(表达式) 表达式和where基本一致
- 性别检查:sex char(3) check(sex in('男','女'))
- check(email like '%@%')
- 外键,表示该列的内容必须在其他表的作主键/或唯一字段中出现
- references table(主键/唯一)
- 外键不唯一,
5,联合及约束(表级约束)
- 如选课表:学生号,课程号(两个组合是唯一的)
- 在一张表中任意一个字段无法表示一行数据时需要多个字段联合标识:成为联合主键约束
- 联合主键约束,primary key(字段1,字段2)
- 联合唯一约束,unique(字段1,字段2)
cerate table stu{ sid varchar(2) references(..., cid varchar(2) ......, primary key(sid,cid) }
DML
- 数据库的增删改 insert into name values(...);全部数据,顺序必须相同
序列&视图&索引
- 1,序列
- 作用,用于自动按顺序生成的一组数字,通常作为oracle的一种主键生成簇
- create Sequence 序列名 start with 100;从100开始每次曾一
- create Sequence 序列名 start with 100 increment by 5;每次增5
- 使用:序列名.nextval 获取序列中下一个有效值可作为一个自增变量使用(一个序列所有表共享)
- insert into tname values(序列名.nxetval,"dzf")
- 序列值一旦产生,不能重复,不回头
- 命名规范:seq_使用表名
- 删除:drop sequence ...
- 2,视图
- 作用:一个起了别名的复杂查询语句
- 语法:create view as 查询语句(select ......)
- 使用:select ...from view
- 删除:drop view name;
- 注意:简化sql语句,不提高效率
- 不会添加任何字段标记,不影响数据的存贮空间
- 3,索引
- 作用:提高数据库的查询效率
- create index name on tablename(字段名)
- 使用:被添加索引列出现在where中 会自动使用该索引,(有的数据库要手动调用)
- 删除:drop index name;
- 注意:索引并不是创建的越多越好(会有字段标记)
- 增删改数据时,不仅要维护原始表,还要维护索引,从而降低效率
- 大量数据表中,查询少量内容时,建议使用索引
- 主键与唯一列 默认提供索引
触发器
mysql> delimiter $$ mysql> CREATE TRIGGER upd_check BEFORE UPDATE ON account -> FOR EACH ROW(是进行删除,插入,更改的行) -> BEGIN -> IF NEW.amount < 0 THEN -> SET NEW.amount = 0; -> ELSEIF NEW.amount > 100 THEN -> SET NEW.amount = 100; -> END IF; -> END$$ mysql> delimiter ;
SHOW TRIGGERS语句查看触发器信息
mysql> SHOW TRIGGERS\G; 结果,显示所有触发器的基本信息;无法查询指定的触发器。
在information_schema.triggers表中查看触发器信息
mysql> select * from information_schema.triggers -> where trigger_name='upd_check'\G;
删除
DROP TRIGGER IF EXISTS trigger_name
注意:insert 只有new,delete 只有old ,oracle 自动添加id
CREATE OR REPLACE TRIGGER MY_TGR BEFORE INSERT ON TAB_USER FOR EACH ROW--对表的每一行触发器执行一次 DECLARE //定义变量 NEXT_ID NUMBER; BEGIN SELECT MY_SEQ.NEXTVAL INTO NEXT_ID FROM DUAL; /查询值赋值给变量 :NEW.ID := NEXT_ID; --:NEW表示新插入的那条记录 END;
存储过程
查看
SHOW CREATE PROCEDURE firsttest.first;
删除
DROP PROCEDURE [过程1[,过程2…]]
修改
alter produce ...
- 只能修改函数的一些属性:谁可以执行这个函数等
- sql语句可能不能修改
- 可以删除后函数重写
in
表示从外部传入一个数,函数中 可以使用它,但不能 更改他
out
表示从外部传入一个数,函数中能更改他,好像不能访问它
inout
二者都可
CREATE PROCEDURE first(in user_id int) BEGIN select * from student where id = user_id; end call first(2) CREATE PROCEDURE second(out k int) BEGIN select math into k from student where id = 1; end set @math = 12; select @math; call second(@math);
oracle
create or replace procedure queryempname(sfindno emp.empno%type) as sName emp.ename%type; sjob emp.job%type; begin .... exception .... end;
1、SQL>exec proc_emp('参数1','参数2');//无返回值过程调用
2、SQL>var vsal number
SQL> exec proc_emp ('参数1',:vsal);// 有返回值过程调用
或者:call proc_emp ('参数1',:vsal);// 有返回值过程调用
事物
- 概念:最小执行单元,1-n条语句构成,全部成功时事物才会成功
- 原理,每个客户端都会有一块内存,存储临时sql,若sql成功则存入服务器,否则清空sql结果
- 事务边界
- 开始:第一个sql
- 结束:
- dml语句:成功后 commit 后提交数据库
- ddl语句:直接事物提交 create等
- 正常退出: 自动commit,否则rollback
- 查询无事务
- 事物特点:
- 原子性:所有sql为一个整体success ->commit fail->rollback
- 一致性:事务执行后业务和数据状态必须一致
- 隔离性:多用户并发操作,不受影响,独立
- 持久性:事务执行后,影响是永久的
- 数据安全
- 事物的底层:基于锁
- 多用户并发操作一个行,要获取所标记,操作完成时释放
sql优化
- 避免select *
- select age,name .... 固定长度属性在前
- 内存代替表, 性别等
- 读写分离,两个相同的数据库
- 分库:表多的时候,放到不同数据库
- 分表:水平(onetoone),垂直
命中索引
- 组合索引代替索引合并(多列但索引)
- 尽量使用短索引 (不要对文章建立索引)
- 如取一条数据时,使用limit 1
- select id,name from tb where name ="dzf"; 默认情况会通过逐行查询,或索引查询,找到后还会继续查询
- select id,name from tb where name ="dzf" limit 1,找到第一个就停
使用join代替子查询
- 对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引
- 应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描
如:select id from t where num is null可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:select id from t where num=0 - 应尽量避免在 where 子句中使用!=或操作符,否则引擎将放弃使用索引而进行全表扫描。
- 应尽量避免在 where 子句中使用or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,(可以使用union)
- in 和 not in 也要慎用,否则会导致全表扫描(能用 between 就不要用 in)
- 下面的查询也将导致全表扫描。
select id from t where name like '%李%',select id from t where name like '%李'
若要提高效率,可以使用此格式select id from t where name like '李%',也可以考虑全文检索。 - 避免在索引列上使用计算,也就是说,应尽量避免在 where 子句中对字段进行表达式操作和函数操作,这将导致引擎放弃使用索引而进行全表扫描。
如:select id from t where num/2=100应改为:select id from t where num=100*2 - 很多时候用 exists 代替 in 是一个好的选择:exists用于检查子查询是否至少会返回一行数据,该子查询实际上并不返回任何数据,而是返回值true或false。
select num from a where num in(select num from b)
用下面的语句替换:select num from a where exists (select 1 from b where num=a.num) - 任何地方都不要使用 select * from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段。
- 10.用>=替代>
高效: SELECT * FROM EMP WHERE DEPTNO >=4
低效: SELECT * FROM EMP WHERE DEPTNO >3
两者的区别在于, 前者DBMS将直接跳到第一个DEPT等于4的记录,而后者将首先定位到DEPTNO=3的记录并且向前扫描到第一个DEPT大于3的记录。 - 用Where子句替换having子句
- 创建索引,但无法命中索引。
- https://www.cnblogs.com/wupeiqi/articles/5716963.html
select * from tb1 where name='alex'; - like '%xx' select * from tb1 where name like '%cn'; - 使用函数 select * from tb1 where reverse(name) = 'wupeiqi'; - or select * from tb1 where nid = 1 or email = 'seven@live.com'; 特别的:当or条件中有未建立索引的列才失效,以下会走索引 select * from tb1 where nid = 1 or name = 'seven'; select * from tb1 where nid = 1 or email = 'seven@live.com' and name = 'alex' - 类型不一致 如果列是字符串类型,传入条件是必须用引号引起来,不然... select * from tb1 where name = 999; - != select * from tb1 where name != 'alex' 特别的:如果是主键,则还是会走索引 select * from tb1 where nid != 123 - > select * from tb1 where name > 'alex' 特别的:如果是主键或索引是整数类型,则还是会走索引 select * from tb1 where nid > 123 select * from tb1 where num > 123 - order by select email from tb1 order by name desc; 当根据索引排序时候,选择的映射如果不是索引,则不走索引 特别的:如果对主键排序,则还是走索引: select * from tb1 order by nid desc;
JDBC
# oracle oracle.driver=oracle.jdbc.OracleDriver oracle.url=jdbc:oracle:thin:@localhost:1521:xe oracle.username=hr oracle.password=hr