Day19 Oracle 数据库 创建表 约束 JDBC BaseDAO
一 创建表
1.创建表(不加约束)
(1)创建新表(不加约束)
创建表
create table tb_user(
userid number(5),
username varchar2(30),
userpwd varchar2(20),
gender char(3)
)
加入注释
comment on table tb_user is '用户表';
comment on column tb_user.userid is '流水号,主键';
comment on column tb_user.username is '用户名';
comment on column tb_user.userpwd is '密码';
comment on column tb_user.gender is '性别';
(2)已有表中拷贝结构
--create table 表名 as select 字段列表 from 已有表 where 1!=1;
create table copy_emp as select * from emp where 1!=1; -- 只拷贝结构不拷贝数据
create table copy_emp2 as select empno,ename,sal from emp; --结构和数据全部拷贝
select * from copy_emp;
select * from copy_emp2;
(3)删除表
drop table copy_emp2; 删除表
--drop table 表名 cascade constraints 删除约束
2.创建表(同时创建约束+默认名称)
--表+约束 (1.字段后直接给约束|字段后指定约束名字添加约束 2.在创建表结构的最后指定约束) 3.表结构之后追加约束
create table tb_student(
--学号 主键 唯一+非空
--sid number(5) primary key,
--sid number(5) constraints pk_student_sid primary key,
sid number(5),
--学生名字不能为空
--sname varchar2(30) not null,
sname varchar2(30)constraints sname_notnull not null,
--年龄不能超过18~150
sage number(3) check(sage between 18 and 150),
--不是男就是女
sgender char(3) check(sgender='男' or sgender = '女'),
--唯一的
sqq varchar2(30) unique
)
3.创建表(同时创建约束+指定名称)
--表结构最后定义约束
create table tb_student(
--学号 主键 唯一+非空
sid number(5),
--学生名字不能为空
sname varchar2(30),
--年龄不能超过18~150
sage number(3),
--不是男就是女
sgender char(3),
--唯一的
sqq varchar2(30),
classid number(3),
--定义约束 指定名字,指定约束 ,指定字段
constraints pk_student_sid primary key(sid),
constraints sname_notnull check(sname is not null),
constraints ck_sage check(sage between 18 and 150),
constraint fk_student_classid_classid foreign key(classid) references clazz(classid) on delete set null --on delete cascade
)
4.创建表(追加创建约束+指定名称)
--表结构后面追加约束
alter table tb_student add constraints student_sqq unique(sqq);
--删除约束
alter table tb_student drop constraints student_sqq;
--班级表
create table clazz(
classid number(3) primary key,
classname varchar2(18) not null,
subject varchar2(15) not null
)
insert into clazz values(01,'27期','java');
insert into clazz values(02,'28期','java');
select * from clazz;
drop table clazz cascade constraints; --主表
delete from clazz where classid=02 ;
drop table tb_student;
select * from tb_student;
insert into tb_student(sid,sname,sage,sgender,sqq,classid) values(1,'杨建秋',23,'男',700707070,02);
insert into tb_student(sid,sname,sage,sgender,sqq,classid) values(2,'杨',23,'男',7007070702,03);
insert into tb_student(sid,sname,sage,sgender,sqq) values(2,'hah',23,'男',700707070);
insert into tb_student(sid,sname,sage,sgender,sqq) values(3,'hah',23,'男',700707070);
delete from tb_student where sid=1;
--存在主外键关系:
--删除数据:1.先删除从表中引用主表中当前这条数据的那些数据,然后再删除主表中的数据 ---默认
2.直接删除主表中的数据,一起把从表中引用了当前要删除的主表中的数据的这些子记录删除--on delete cascade 级联删除
3.在删除主表中数据的时候,从表中引用了这个数据的子记录设置为null
--删除主表:1.先删除从表,再删除主表
2.直接删除主表,级联删除主从表之间约束
二 约束
1.约束的分类
(1) not null(非空)
如果在列上定义了not null,那么当插入数据时,必须为列提供,数据不能为NULL。约束只能在列级定义,不能在表级定义。
(2) unique(唯一)
当定义了唯一约束后,该列值是不能重复的,但是可以为null。
(3) primary key(主键)
用于唯一的标识表行的数据,当定义主键约束后,该列不但不能重复而且不能为NULL。一张表最多只能有一个主键,但是可以由多个unique约束。
创建主键或唯一约束后,ORACLE会自动创建一个与约束同名的索引(UNIQUENES为UNIQUE唯一索引)。需要注意的是:每个表只能有且有一个主键约束。
(4) foreign key(外键)
用于定义主表和从表之间的关系,外键约束要定义在从表上,主要则必须具有主键约束或是unique约束,当定义外键约束后,要求外键列数据必须在主表的主键列存在或是为NULL。
用来维护从表(Child Table)和主表(Parent Table)之间的引用完整性. 外键约束是个有争议性的约束,它一方面能够维护数据库的数据一致性,数据的完整性。防止错误的垃圾数据入库; 另外一方面它会增加表插入、更新等SQL性能的额外开销,不少系统里面通过业务逻辑控制来取消外键约束。例如在数据仓库中,就推荐禁用外键约束。
(5) check
用于强制行数据必须满足的条件,假定在sal列上定义了check约束,并要求sal列值在1000~2000之间,如果不在1000~2000之间就会提示出错。
2.约束的操作
(1)查看某个用户的约束
select constraint_name, constraint_type
from user_constraints
where owner = upper('scott');
(2)查看表的约束
select constraint_name,constraint_type
from user_constraints
where table_name=upper('tb_user');
(3)查看字段名+约束
select constraint_name, column_name
from user_cons_columns
where table_name = upper('tb_user');
(4)约束的禁用与启用
ALTER TABLE tb_user disable constraint nn_user_name;
ALTER TABLE tb_user enable constraint nn_user_name;
(5)删除约束
alter table tb_user drop constraint uq_user_email cascade;
(6)修改约束
--非空alter table tb_user modify (username varchar2(20));
--默认alter table tb_user modify (age default null);
三 表的其他操作
1.修改表结构
(1)、修改表名 :rename to
--修改表名rename tb_txt to tb_txt_new;
(2)、修改列名: alter table 表名 rename column to
--修改列名alter table tb_txt_new rename column txtid to tid;
(3)、修改类型: alter table 表名 modify(字段 类型)
--修改类型alter table tb_txt_new modify(tid varchar2(20));
(4)、修改约束: 先删除 后添加
(5)、添加列: alter table 表名 add 字段 类型
--添加列alter table tb_txt_new add col varchar2(30);
(6)、删除列:alter table 表名 drop column 字段
--删除列alter table tb_txt_new drop column col;select * from tb_txt_new;
2.删除表
1、先删除从表 再删除主表
2、删除表的同时删除约束
drop table tb_txt_new cascade constraints;
drop table tb_user cascade constraints;
3.截断数据
--删除数据 delete会开启事务
delete from tb_student;
delete from clazz;
--数据截断 truncate 如果存在主从表关系,检查整个表结构是否有被引用,如果有结构上的引用就不能删除 不会开启事务
truncate table tb_student;
truncate table clazz;
truncate: 截断所有的数据 ,如果截断的是主表,结构不能存在外键关联
截断数据同时 从结构上 检查
create table emp_his as select * from emp where 1=1;
select * from emp_his;
--截断所有的数据
truncate table emp_his;
--不能截断: truncate table dept;
四 序列
1.创建
create sequence 序列名 start with 起始值 increment by 步进;
2.使用
在操作数据 添加 更新 -->主键
1)、currval :当前值
2)、nextval:下个值
create sequence seq_tb_user start with 2 increment by 2;
drop sequence seq_tb_user;
select seq_tb_user.nextval from dual;
select seq_tb_user.currval from dual
3.删除
drop sequence 序列名
五 事务
事务是指作为单个逻辑工作单元执行的一组相关操作。这些操作要求全部完成或者全部不完成。使用事务是为了保证数据的安全有效。
1.事务的四个特点
(1)原子性(Atomic):事务中所有数据的修改,要么全部执行,要么全部不执行。
(2)一致性(Consistence):事务完成时,要使所有所有的数据都保持一致的状态,换言之:通过事务进行的所有数据修改,必须在所有相关的表中得到反映。
(3)隔离性(Isolation):事务应该在另一个事务对数据的修改前或者修改后进行访问。
(4)持久性(Durability):保证事务对数据库的修改是持久有效的,即使发生系统故障,也不应该丢失
2.重点词
丢失更新:两个事务同时存储, 一个存储 100 , 一个存储 200,最终可能至存储了200 或者 100,那另一个的更新就没成功,即结果不为预想的 300
脏读:事务 T1 更新了一行数据,还没有提交所做的修改,T2 读取更新后的数据,T1回滚,T2 读取的数据无效,这种数据称为脏读据。
不可重复读:事务 T1 读取一行数据,T2 修改了 T1 刚刚读取的记录,T1 再次查询,发现与第一次读取的记录不相同,称为不可重复读。
幻读:事务 T1 读取一条带 WHERE 条件的语句,返回结果集,T2 插入一条新纪录,恰好也是 T1 的 WHERE 条件,T1 再次查询,结果集中又看到 T2 的记录,新纪录就叫做幻读。
3.事务的开启
自动开启于 DML 之 insert delete update
4.事务的结束
(1)成功
正常执行完成的 DDL 语句:create、alter、drop
正常执行完 DCL 语句 GRANT、REVOKE
正常退出的 SQLPlus 或者 SQL Developer 等客户端
如果人工要使用隐式事务,SET AUTOCOMMIT ON (只针对一个连接)
手动提交 :使用 commit
(2)失败
rollback ,手动回滚
非法退出 意外的断电
rollback 只能对未提交的数据撤销,已经 Commit 的数据是无法撤销的,因为 commit之后已经持久化到数据库中。
六 DML
1.insert
insert into 表名 [(字段列表)] values(值列表); 添加记录
添加记录时需要满足以下条件:
类型 长度 兼容: 字段 兼容值
值满足约束 :主键 (唯一+非空) 非空(必填) 唯一(不重复 ) 默认(没有填写使用默认值) 检查(满足条件) 外键(参考主表主键列的值)
个数必须相同: 指定列,个数顺序与列相同;没有指定,个数与表结构的列个数和顺序相同 (null也得占位,没有默认值)
2.update
update 为修改数据
update 表名 set 字段=值 [,....] where 过滤行记录;
要求:
记录存在
类型 长度 兼容: 字段 兼容值
个数相同
3.delete
delete 删除数据
delete [from] 表名 where 过滤行记录
说明:(1)、delete 可以删除指定部分记录,删除全部记录
(2)、记录上存在主外键关联时, 删除存在关联的主表的记录时,注意 参考外键约束, 约束强制不让删除 先删除从表 再删除主表
主外键关联时,注意 参考约束, 约束强制不让删除
--先删除从表 再删除主表
delete from tb_txt where 1=1;
delete from tb_user where 1=1;commit;
截断数据与删除数据区别 truncate 与delete 区别
1、truncate -->ddl ,不涉及事务,就不能回滚 delete -->dml ,涉及事务,可以回滚
2、truncate 截断所有的数据 delete 可以删除全部 或者部分记录
3、truncate从结构上检查是否存在主外键,如果存在,不让删除
delete 从记录上检查是否存在主外键,如果存在,按参考外键约束进行删除。
七 JDBC
接口名称 作用
java.sql.Connection 连接
java.sql.Statement 静态处理块
java.sql.PreparedStatement 预处理块
java.sql.ResultSet 结果集
java.sql.ResultSetMetaData 结果集元信息
1.加载驱动
a)、硬编码: new oracle.jdbc.driver.OracleDriver();
b)、软编码: class.forName("oracle.jdbc.driver.OracleDriver")
(1)安装数据库的目录下 复制:
(2)粘贴到:eclipse新建一个lib包
(3)构建路径 build path:
点击右键:
(4)打开文件:oracle.jdbc.driver或oracle.jdbc--->Oracle.Driver.class
(5)复制地址:Copy Qualified Name
(6)粘贴:Class.forName("oracle.jdbc.driver.OracleDriver");
2.建立连接
(1)连接字符串
用户名与密码: SCOTT TIGER
url: jdbc:oracle:thin:@db 服务器地址:端口:实例
连接 url:jdbc:oracle:thin:@localhost:1521:orcl (如果是XE版本要换成XE)
(2)编写测试类
Connection conn=DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:XE", "SCOTT", "TIGER");
3.准备处理块
Statement state=conn.createStatement();
4.准备sql语句
String sql="select ename,empno from emp";
5.发送sql语句
ResultSet result=state.executeQuery(sql);
6.处理结果集
while(result.next()){
String str=result.getString("ename");
long lo=result.getLong(2);//数据库的索引是从1开始
System.out.println(str+"\t"+lo);
}
7.关闭资源
先打开的后关闭
result.close();
state.close();
conn.close();
八 BaseDAO
1.预处理快的特点
(1)提高运行速度
只要被预处理处理过得sql语句,都会提前被数据库处理存入到缓存中,减小了对数据库的压力,提高了程序的运行速度;
(2)防止sql注入
因为SQL语句在程序运行前已经进行了预编译,在程序运行时第一次操作数据库之前,SQL语句已经被数据库分析,编译和优化,对应的执行计划也会缓存下来并允许数据库已参数化的形式进行查询,当运行时动态地把参数传给PreprareStatement时,即使参数里有敏感字符如 or '1=1'也数据库会作为一个参数一个字段的属性值来处理而不会作为一个SQL指令,如此,就起到了SQL注入的作用了!
2. BaseDAO的作用
可以理解成是一种封装
BaseDAO一般是提供从数据库 增加、删除、修改记录、查询所有记录、查询符合某个条件记录、取得某条记录等方法的底层数据操作自定义类。
由于我们可能操作多个数据库表,这样就需要为每个表提供一个操作他的类 xxDAO, 这些DAO继承BaseDAO 就可以省略很多重复代码(从数据库 增加、删除、修改记录、查询所有记录、查询符合某个条件记录、取得某条记录等方法的代码)。
3. 代码
/*
* 通用的操作于数据库的类
* 分为两大类:
* 查询
* 更新
*/
public class BaseDao<T> {
/*
* 查询
* 返回值:List<User>
* 参数:sql,参数Object[] args,Class cls
*/
public List<T> query(String sql,Object[] args,Class<T> cls){
List<T> list=new ArrayList(); //把获取到的所有对象放进list中返回
Connection conn=null;
PreparedStatement state=null;
ResultSet result=null;
try {
conn=DBUtils.getConnection();//DBUtils是一个工具类
state=conn.prepareStatement(sql);
//循环遍历参数数组,给sql中的?赋值
if(args!=null){
for(int i=0;i<args.length;i++){
state.setObject(1+i,args[i]);
}
}
//执行
result=state.executeQuery();
//获取结果集的元信息对象
ResultSetMetaData rsmd=result.getMetaData();
//获取字段个数
int count=rsmd.getColumnCount();
//循环一次是一条数据,果结果集中存在一条数据,就是一个对象
while(result.next()){
//1.创建对象
T obj=cls.newInstance();
//2.获取对象的每一个属性
for(int i=1;i<=count;i++){
//获取字段名字
String columnName=rsmd.getColumnLabel(i);
//获取对象的属每一个性值
Field field=cls.getDeclaredField(columnName);
//私有的属性放开权限
field.setAccessible(true);
String fieldType=field.getType().getName();
// if("java.lang.Double".equals(fieldType)){
// Double d=result.getDouble(i);
// field.set(obj, d);
// }else if("java.lang.Integer".equals(fieldType)){
// Integer in=result.getInt(i);
// field.set(obj, in);
// }else{
//获取字段值
Object value=result.getObject(i);
System.out.println(value.getClass().getTypeName());
//给属性赋值
field.set(obj, value);
// }
field.setAccessible(false);
}
//3.把对象装进集合
list.add(obj);
}
} catch (Exception e) {
e.printStackTrace();
}
return list;
}