下面技术在历史长河中已经被淘汰但老项目,小项目依然在用,只做了解.
dual是一个虚拟表,MySQL没有,用来构成select的语法规则,Oracle保证dual里永远只有一条记录,用它可以做很多事.
将结果存储在dual表中:
select 1 from dual; 虚拟出一个数字列
select 'abc' from dual; 虚拟出一个字符串列
select sysdate from dual; 获取系统当前日期
select sys_guid() from dual; 获取uuid
Oracle自身提供的自增主键支持,和MySQL的实现思路完全不同.
使用system登录,修改ht的权限为dba,否则无法创建视图.
或者
使用system账户执行,分配视图权限.
grant create any view to ht;
视图本质就是一个查询,和我们自己查询的区别是,它执行完会有缓存,下次查询就直接使用.但其它因为实现缓存,无法做优化,大型项目中禁止使用.
注意: 视图只需创建一次,后面就可以类似表来使用,只是用来查询不能更新和删除.
创建视图 ,本质上就是缓存一个查询结果
create or replace view STU_V as
select * from stu where ssex=0
查询表结构
select * from stu where ssex=0
直接查询视图,高效,但是无法优化
select * from STU_V
可以看到两者查询结果没有分别
记录生效点:BEFORE/AFTER
记录的操作:INSERT/UPDATE/DELETE
需求:当修改sex值时触发逻辑.
--设置触发器 ---禁用,因为无法控制程序员的权限,可能有安全隐患
create or replace trigger UPDATE_STU_TRI
before update on stu
for each row
declare
-- local variables here
begin
--如果 SEX>0,统一设置成1
IF :NEW.SSEX>5 THEN
:NEW.SSEX := 1;
END IF;
end UPDATE_STU_TRI;
--使用触发器:
SELECT * FROM STU
update stu set ssex=10;--触发器执行,都是1了
update stu set ssex=3;--不满足触发器,就是3
概念:
存储过程(Stored Procedure)其实就是数据库端的编程,在数据库为王的时代,虽然已经过去,当时数据库大集中,部署在超级好的服务器,甚至是小型机,所以执行的性能超群,运行在上面的程序自然也就性能极佳。但当分布式架构兴起后,数据库在整个架构中的作用一再衰落,逐步边缘化。再者存储过程中的SQL是依赖数据库厂商,每个厂商都有其个性的SQL,导致程序迁移数据库时,如从oracle迁移到mysql时基本重写,工作量巨大,造成修改的风险。于是主流方式已经将其从数据库端前置到java程序端实现,这样迁移数据库变得轻松。
我们学习了数据库,数据库实现了数据的持久化,但我们最终要在程序里处理数据,那java代码中怎么去访问数据库读写数据呢?
这就要用到sun公司设定的一套数据库标准了,这套标准就是JDBC(Java Database Connectivity)。但它只是规范,不做具体实现。于是数据库厂商又根据JDBC标准,实现自家的驱动Driver。如:MySQL驱动com.mysql.cj.jdbc.Driver,Oracle的驱动oracle.jdbc.OracleDriver。有了这套解决方案,java就可以访问数据库中的数据了。
public interface Connection extends Wrapper, AutoCloseable {}
public interface Statement extends Wrapper, AutoCloseable {}
public interface PreparedStatement extends Statement {}
public interface CallableStatement extends PreparedStatement {}
public interface ResultSet extends Wrapper, AutoCloseable {}
Java中提倡面向接口开发,而最经典的接口设计莫过于JDBC数据库接口。
Connection链接、Statement语句、PreparedStatement预处理语句、CallableStatement存储过程、ResultSet结果集。
调用方式有三种:Statement语句、PreparedStatement预处理语句、CallableStatement存储过程,推荐使用第二种PreparedStatement,防止SQL注入,其也是预编译性能高。
2.1 导入jar包(丰富的工具类)
2.2 获取和数据库的连接(用户名、密码)
2.3 通过程序执行SQL
2.4 通过程序处理结果
3.1 创建Java工程
3.2 创建lib目录,拷贝驱动 objbc6-11.1.0.7.0 到 lib 目录下
import java.sql.*;
public class Test1 {
public static void main(String[] args) throws Exception {
// 1. 注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2. 获取和数据库的连接
// String url = "jdbc:mysql://localhost:3306/py_school_db?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false";
String url = "jdbc:mysql:///py_school_db?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false";
String user = "root";
String password = "root";
Connection conn = DriverManager.getConnection(url, user, password);
// 3. 获取传输器
Statement st = conn.createStatement();
// 4. 执行SQL
ResultSet rs = st.executeQuery("select * from students");
// 5. 解析结果
while (rs.next()){
// 获取数据
for (int i = 1 ; i <= 5 ; i++){
System.out.println(resultSet.getString(i));
}
}
// 6. 释放资源
rs.close();
st.close();
conn.close();
}
}
5.1 不安全:
private static void login() throws Exception {
Class.forName("com.mysql.cj.jdbc.Driver");
String url = "jdbc:mysql:///lz?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false";
String user = "root";
String password = "root";
Connection connection = DriverManager.getConnection(url, user, password);
/**
* 传输器在执行SQL时不安全
*/
Statement statement = connection.createStatement();
System.out.println("请输入用户名: ");
String name = new Scanner(System.in).nextLine();
System.out.println("请输入密码: ");
String pass = new Scanner(System.in).nextLine();
// SQL注入攻击问题: 本质上是因为SQL语句中出现了特殊符号#,改变了SQL语义
String sql = "select * from user where name='" + name + "' and password='" + pass + "'";
ResultSet resultSet = statement.executeQuery(sql);
if (resultSet.next()){
System.out.println("登陆成功!");
}else {
System.out.println("查无此人!");
}
resultSet.close();
statement.close();
connection.close();
}
5.2 解决办法
/*总结:
作用: java程序和数据库连接的技术
SQL注入攻击问题:拼接SQL时,出现了特殊符号#,只需要输入用户名而不需要密码都可以登录
SQL注入攻击解决方案:不用Statement,换成了PreparedStatement,
新的工具类的好处:不用自己拼SQl的字符串了,安全,高效
PreparedStatement的解决过程:先把SQL骨架发给数据库,数据库进行预编译
等到设置好了参数,再和骨架一起执行,避免了人为的恶意的拼串造成的隐患
*/
private static void login2() throws Exception {
Class.forName("com.mysql.cj.jdbc.Driver");
String url = "jdbc:mysql:///lz?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false";
String user = "root";
String password = "root";
Connection connection = DriverManager.getConnection(url, user, password);
System.out.println("请输入用户名: ");
String name = new Scanner(System.in).nextLine();
System.out.println("请输入密码: ");
String pass = new Scanner(System.in).nextLine();
/**
* ?: 占位符
* SQL骨架
*/
String sql = "select * from user where name=? and password=?";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
// 给SQL设置参数
/**
* preparedStatement.setString(参数索引,参数值);
*/
preparedStatement.setString(1,name);
preparedStatement.setString(2,pass);
ResultSet resultSet = preparedStatement.executeQuery();
if (resultSet.next()){
System.out.println("登陆成功!");
}else {
System.out.println("查无此人!");
}
resultSet.close();
preparedStatement.close();
connection.close();
}