1. 视图
概念: 从一张或多张表中抽取的虚拟表,操作虚拟表的CRUD与原表完全一样
优点:
1.简单化,从多张表抽取后,只需要管理虚拟表即可
2.安全性,能看到的只是抽取到虚拟表的字段
3.逻辑独立性
缺点:
1.性能没有提升,简单表会变得复杂
2.修改不方便,有多种情况不能修改虚拟表的
创建视图:
create view myView as
select employee_id,first_name,last_name,salary from t_employees;
select * from myView;
update myView set salary=30000 where employee_id=100;
修改视图:
方式1:创建或修改
CREATE OR REPLACE VIEW myView AS
select employee_id,first_name,last_name from t_employees;
方式2:修改视图
alter VIEW myView AS
select employee_id,first_name,last_name,salary from t_employees;
删除视图
drop view myView;
视图的不可更改性:
create view myView as
select department_id,count(*) from t_employees group by department_id;
update myView set department_id=119 where department_id=10;
2.综合练习
先导入数据,然后完成下面练习:
1.查询所有用户的订单
select * from user u inner JOIN orders o on u.userid=o.userid;
2.查询用户id为 1 的所有订单详情
select * from user u INNER JOIN orders o on u.userid=o.userid
INNER JOIN orderitem oi on o.oid= oi.oid where u.userid=1;
3.查看用户为张三的订单
select * from orders where userid=(select userid from user where username='张三');
4.查询出订单的价格大于800的所有用户信息。
select * from user where userid in (select DISTINCT userid from orders where totalprice>800);
5.查询所有订单信息,每页显示5条数据
select * from orders limit 0,5; 第一页
select * from orders limit 5,5; 第二页
select * from orders limit 10,5; 第三页
规律:
已知当前页,页大小(每页条数),求起始下标
起始下标= (当前页-1)*页大小
4. JDBC操作(重点)
回顾之前连接数据库的方式
DOS指令方式,图形化方式
缺点:
只能是简单地SQL语句的测试,无法在项目中操作数据库
引出通过java代码方式连接数据库---JDBC
概述:JDBC是一套连接数据库的标准;具体的实现是由不同的数据库提供的
JDBC核心思想:
JDBC操作步骤:
具体应用:
安装5.7的数据库,驱动包选择5.X的驱动包
导入驱动包:
- 在项目下新建 lib 文件夹,用于存放 jar 文件。
- 将 mysql 驱动mysql-connector-java-5.1.X复制到项目的 lib 文件夹中。
- 选中 lib 文件夹右键 Add as Libraay,点击 OK。
常见的异常问题:
ClassNotFoundException 驱动加载失败
MySQLSyntaxErrorException: 数据库或SQL语句异常
SQLException: Access denied 账户或密码出错
MySQLIntegrityConstraintViolationException 主键冲突
4.1 DML操作
//案例:给岗位表添加一条数据
public class DMLTest {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2.通过驱动管理器获取连接对象 alt+enter弹出异常与赋值变量
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb1", "root", "123");
//3.通过连接对象获取执行对象
Statement st = conn.createStatement();
//4.进行增删改查操作 增删改:executeUpdate
//String sql = "insert into t_jobs(job_id,job_title,min_salary,max_salary) values('QF_PRA','PRA',13000,18000)";
//String sql = "update t_jobs set min_salary=20000,max_salary=30000 where job_id='QF_PRA'";
String sql = "delete from t_jobs where job_id='QF_PRA'";
//5.反馈结果
int result = st.executeUpdate(sql);
System.out.println("影响的条数:"+result);
//6.关闭资源,先关小的再关大的
DBUtils.closeAll(st,conn);
}
}
4.2 DQL操作
class Student{
private int id;
private String name;
private int age;
//set/get及构造方法略
}
//查询学生表的数据
public class DQLTest {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql:///mydb1", "root", "123");
Statement st = conn.createStatement();
//获取结果集
ResultSet rs = st.executeQuery("select * from student");
List<Student> list = new ArrayList<>();
//循环遍历,获取所有记录(每次循环,都是一条记录
while(rs.next()){
//int id = rs.getInt(1); //1代表第1列;应用场景:聚合查询反馈
int id = rs.getInt("id"); //id:字段名获取值
String name = rs.getString("name");
int age = rs.getInt("age");
System.out.println(id+"-->"+name+"-->"+age);
//应用场景:反馈零散的内容,应该需要对象封装,
list.add(new Student(id,name,age));
}
System.out.println("集合中存储的数据:"+list);
DBUtils.closeAll(rs,st,conn); //关闭资源
}
}
4.3 安全登录案例
> - 创建一张用户表 User
> - id ,主键、自动增长。
> - 用户名,字符串类型,唯一、非空
> - 密码,字符串类型,非空
> - 手机号码,字符串类型
> - 插入 2 条测试语句
#### 实现登录
> - 通过控制台用户输入用户名和密码。
> - 用户输入的用户名和密码作为条件,编写查询 SQL 语句。
> - 如果该用户存在,提示登录成功,反之提示失败。
public class LoginTest {
public static void main(String[] args) {
System.out.println("请输入用户名");
Scanner sc = new Scanner(System.in);
String username = sc.nextLine(); //获取一行内容
System.out.println("请输入密码");
String password = sc.nextLine();
if(login2(username,password)){ //登录功能
System.out.println("登录成功~!");
}else{
System.out.println("登录失败~!");
}
}
private static boolean login2(String username, String password) {
Connection conn = null;
PreparedStatement prst = null;
ResultSet rs = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql:///mydb1", "root", "123");
//PreparedStatement:预处理执行对象 ?为占位符
//好处: 1.安全性高,解决了sql注入问题
//2. 执行性能会更高
//3. 方便进行批处理操作
prst = conn.prepareStatement("select count(*) from user where username=? and password=?");
//参数1:对应第一个占位符? 下标从1开始
prst.setString(1,username);
prst.setString(2,password);
//获取结果集
//sql注入的隐患
rs = prst.executeQuery();
if(rs.next()){
int result = rs.getInt(1); //聚合函数只有一个字段
return result>0; //result不小于0,则返回true
}
} catch (Exception e) {
e.printStackTrace();
} finally {
DBUtils.closeAll(rs,prst,conn);
}
return false;
}
private static boolean login(String username, String password) {
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql:///mydb1", "root", "123");
st = conn.createStatement();
//获取结果集
//sql注入的隐患
String sql = "select count(*) from user where username='"+username+"' and password='"+password+"'";
rs = st.executeQuery(sql);
if(rs.next()){
int result = rs.getInt(1); //聚合函数只有一个字段
return result>0; //result不小于0,则返回true
}
} catch (Exception e) {
e.printStackTrace();
} finally {
DBUtils.closeAll(rs,st,conn);
}
return false;
}
}