MySQL 相关
1. 什么是JDBC? 优势? 功能?
JDBC (Java Database Connectivity) 是Java数据库连接的意思, 是用来执行SQL语句的 JAVA API
优势是跨平台, 跨应用; 实现同一种API访问不同平台不同数据库系统
功能就是连接数据库, 执行SQL语句
2. JDBC 驱动程序是什么? 几种? 使用哪一种?
数据库驱动程序就是JDBC和数据库之间的转换层, 将JDBC调用映射成数据库调用
有 JDBC-ODBC, 直接将JDBC API 映射成数据库特定的客户端 API, 支持三层结构的 JDBC 访问方式, 纯JAVA直接与客户端交互4种
正常使用
第四种
3. Win 10 安装MySQL步骤?
下载MySQL安装压缩包
下载 vcredist_x86.exe 并安装
在MySQL安装包目录新建 my.ini 并正确编写
将 MySQL 添加到环境变量并在 path 种添加MySQL环境变量
CMD 执行 mysqld -install 获取密码并更改密码
重启MySQL服务 service MySQL restart
4. DBMS? MySQL数据库类型? MySQL引擎?
DBMS 是 Database management System 数据库管理系统的简称
MySQL 数据关系型数据库, 所使用的引擎是 InnoDB
5. 标准SQL语句的类型?
查询语句: 由 select 关键字完成
DML(Data Manipulation Language) 数据操作语言: 主要由 insert, update, delete 关键字完成
DDL(Data Definition Language) 数据定义语言: 主要由 create, alter, drop, truncate 关键字完成
DCL(Data Control Language) 数据控制语言: 主要由 grant(授予), revoke(撤销) 关键字完成
事务控制语句: 主要由 commit, rollback, savepoint 关键字组成
6. 创建数据库?
CREATE DATABASE test CHARSET=UTF8;
7. 创建表语法?
CREATE TABLE test_img (
id int(10) not null PRIMARY KEY AUTO_INCREMENT,
title varchar(20) not null,
post_date datetime,
photo mediumblob
);
8. 子查询建表?
CREATE TABLE new_test_img
as
SELECT * FROM test_img;
9. 增加/修改表结构?
ALTER TABLE test
ADD (
test_date date default '2019-12-31'
);
ALTER TABLE test
MODIFY name varchar(30) not null;
10. 删除数据表某一列语法?
ALTER TABLE test
drop word;
11. 重命名数据表?
ALTER TABLE test
RENAME TO user;
12. 重命名数据表中的某列?
ALTER TABLE user
CHANGE test_date age DATE NOT NULL DEFAULT '1990-01-01';
13. 删除数据库语法?
DROP TABLE new_user;
14. 删除数据表数据, 保留语法结构?
TRUNCATE user;
15. NOT NULL 只能作为列级约束例子?
CREATE TABLE category (
id INT NOT NULL AUTO_INSCREMENT PRIMARY KEY,
category varchar(50) NOT NULL);
16. UNIQUE 唯一约束, 表级, 列级语法?
-- 列级唯一约束
CREATE TABLE user1 (
id INT(10) NOT NULL UNIQUE,
username varchar(50) NOT NULL DEFAULT 'admin'
);
-- 表级唯一约束
CREATE TABLE user2 (
id INT(10) NOT NULL,
username varchar(50) NOT NULL DEFAULT 'admin',
-- 表级约束
UNIQUE (id));
-- 表级唯一约束, 且指定约束名
CREATE TABLE user3 (
id INT(10) NOT NULL,
username varchar(50) NOT NULL DEFAULT 'admin',
CONSTRAINT user3_unique UNIQUE (id, username)
);
17. 删除, 修改唯一约束?
-- 修改唯一约束
ALTER TABLE user3
MODIFY id INT(10) NOT NULL UNIQUE;
-- 删除约束
-- 可以通过 SHOW CREAE TABLE user3; 语句来查看唯一约束的约束名
ALTER TABLE user3
DROP INDEX user3_unique;
18. PRIMARY KEY 主键约束是什么?
主键约束相当于非空约束和唯一约束的组合, 每张表只能有一个主键约束
主键约束有表级以及列级约束之分, 也可以指定组合作为主键约束
19. 列级主键约束, 表级主键约束?
-- 列级约束
CREATE TABLE test1 (
id INT(10) PRIMARY KEY AUTO_INCREMENT,
test_name VARCHAR(50) NOT NULL
);
-- 表级约束
CREATE TABLE test2 (
id INT(10) AUTO_INCREMENT,
test_name VARCHAR(50),
CONSTRAINT test_pk PRIMARY KEY(id)
);
20. 删除主键约束?
ALTER TABLE test2
DROP PRIMARY KEY;
21. 什么是外键约束 FOREIGN KEY?
外键约束是一种参照关系, 即一张表的两个字段或两张表的两个字段之间的参照关系
参照关系: 子表外键列的值必须在主表被参照列的值范围之内, 或者为空
从表外键参照的只能是主表主键列或者唯一列, 同一表可以有多个外键
22. 创建外键约束的例子?
-- 例子1: 实例 建立blog数据库
create database blog charset=utf8;
-- 建立 User 表
-- 如果想删除主表(user)记录时, 从表(blog)记录也会随之删除, 则需要在建立外键约束后添加 on delete cascade
-- 或者添加 on delete set null (第一种:主表删除后,从表记录也全部级联删除; 第二种: 主表删除后, 参照该主表
-- 记录的外键设为null)
create table user (
user_id int not null primary key auto_increment,
user_name varchar(255) not null unique,
create_date datetime not null,
is_admin boolean defaule false
);
--
-- 建立 category 表
create table category (
category_id int not null auto_increment primary key,
category_name varchar(255) not null unique
);
--
-- 建立 blog 主表 使用表级约束语法
create table blog (
title varchar(255) not null,
blog_user varchar(255),
blog_category varchar(255),
blog_body text,
-- 表级约束
foreign key (blog_user) references user(user_name) on delete cascade,
foreign key (blog_category) references category(category_name) on delete set null
);
23. 索引是什么? 自动创建索引? 手动创建索引?
索引是存放在模式(schema)中的一个数据库对象, 作用是加速对表的查询
自动创建索引: 当定义了唯一约束, 主键约束, 外键约束时, 系统自动为该数据列创建对应的索引
手动创建索引: 通过 create index 语法来手动创建索引
24. 创建索引, 删除索引?
-- 创建单独列的索引
create index emp_last_name_idx
on employees(last_name);
--
-- 同时对多列创建索引
create index emp_last_name_idx2
on employees(first_name, last_name);
--
-- 删除索引
drop index emp_last_name_idx2
on employees;
25. 什么是视图?
- 视图是一个或多个数据表中数据的逻辑显示, 视图不存储数据, 也不是数据表
26. 创建删除视图?
-- 创建一个视图
create view blog_all
as
select * from blog;
--
-- 删除上面创建的视图名
drop view blog_all;
27. insert into 数据表插入语句?
-- 同时插入多条语句
insert into user values
(0, 'python', '2018-08-08'),
(0, 'java', '2019-09-01'),
(0, 'CSS', '2019-05-01');
28. update 语句修改表?
- update 语句用于修改表数据, 可一次修改一条或多条或多列记录, 可以通过 WHERE 来限定修改那些记录
-- 语法
update table_name
set column1 = value1[, column2 = value2]...
[WHERE condition];
-- 例子
update user
set name = 'Java' where id = 2;
29. delete from 语句删除指定表的记录?
- delete from 语句用于删除指定数据表的记录, delete from 总是整行删除记录, 也可以通过 WHERE 来限定删除条件
-- 语法:
delete from table_name
[WHERE condition];
--
-- 例子:
-- 删除student_table2表中的全部记录
delete from student_table2;
-- 通过 where 来限定删除条件
delete from student_table2
where teacher_id > 2;
JDBC 相关
1. 简述 JDBC4.2 常用接口和类---DriverManger类?
DriverManager 类主要是用于管理JDBC驱动的服务类, 主要功能就是获取 Connection 对象
用法:
Connection conn = DriverManager.getConnection(String url, String user, String password)
2. 简述 JDBC4.2 常用接口和类---Connection接口及接口的主要方法?
Connection 代表了数据库的连接对象, 每个Connection代表一个物理连接会话, 想访问数据库, 必须先获得数据库连接
-
Connection 常用的方法:
Statement createStatement() throws SQLException(); 获得一个Statement对象PreparedStasement preparedStatement(String sql) throws SQLException获得一个预编译的 PreparedStasement 对象, 可以传入带有参数的SQL语句CallableStatement prepareCall(String sql) throws SQLException返回 CallableStatement 对象
3. 简述 Statement 接口?
用于执行SQL语句的工具接口, 该对象可执行DDL, DCL, DML 以及 SQL查询语句, 执行SQL查询语句时返回查询到的结果集
-
Statement 常用方法:
ResultSet executeQuery(String sql) throws SQLException; 用于执行查询语句, 并返回查询结果对应的 ResultSet 对象, 该方法只能用于执行查询语句int executeUpdate(String sql) throws SQLException; 该方法用于执行DML语句, 并返回执行后受影响的行数; 也可用于执行DDL语句, 执行DDL语句返回0boolean execute(String sql) throws SQLException; 该方法可执行任何SQL语句, 如果执行后的第一个结果为 ResultSet 对象, 则返回 true; 如果执行后第一个结果为受影响的行数或没有任何结果, 则返回falseexecuteLargeUpdate()
4. 简述 PreparedStatement 接口?
预编译的 Statement 对象, 它允许数据库预编译SQL语句(这些SQL语句通常都带有参数), 以后每次只改变SQL命令参数, 避免数据库每次都要编译SQL语句
PreparedStatement 同样有 executeUpdate(), executeQuery() 以及
5. 简述 ResultSet 结果集?
ResultSet 结果集是 Statement 接口的查询方法 executeQuery(String sql) 以及 execute(String sql) 查询语句执行后的返回对象; 该对象包含执行查询语句的结果, ResultSet 可以通过列索引或列名获得列数据
当通过移动指针到指定行之后, ResultSet 可通过 getXxx(int columnIndex) 或 getXxx(String columnLabel) 方法来获取当前行, 指定列的值, 前者根据索引来获取值, 后者通过列名来获取值
-
移动指针的方法:
boolean absolute(int row)将结果集的记录指针移动到第row行, 如果 row 为负数, 则移动到倒数第 row 行void beforeFirst()定位到第一行之前void afterLast()定位到最后一行之后boolean previous()定位到前一行boolean next()定位到后一行boolean first()定位到行首boolean last()定位到行尾
6. 简述 JDBC 编程步骤(以MySQL为例)?
-
第一步: 通过 Class.forName(dirverclass) 静态方法来加载数据库驱动
Class.forName("com.mysql.cj.jdbc.Driver"); -
第二步: 通过 DriverManager.getConnection(url, user, password) 方法获取数据库连接
String url = "jdbc:mysql://localhost:3306/blog?useSSL=false&serverTimezone=UTC";
String user = "root";
String password = "password";
Connection conn = DriverManager.getConnection(url, user, password); -
第三步: 通过Connection对象创建 Statement 对象
Statement stmt = conn.createStatement(); 创建基本的Statement对象
PreparedStatement pstmt = conn.PreparedStatement(Sql); 创建预编译的 PreparedStatement 对象 -
第四步: 通过 Statement 或 PreparedStatement 对象调用 execute() 或 executeUpdate() 或 executeQuery() 方法执行SQL语句
stmt.execute()可执行任何SQL语句, 但是比较麻烦
stmt.executeUpdate()执行DML(返回int类型的受影响的行数),DDL语句(返回int类型的0)
stmt.exeuteQuery()只能执行查询语句, 返回的是 ResultSet 类型的结果集 -
第五步: 操作 ResultSet 结果集
next(), previous(), first(), last(), beforeFirst(), afterLast()这些事移动指针的方法
getString(), getInt()这些是获取移动到指定行列的数据的方法 -
第六步: 反向关闭资源
反向关闭 ResultSet, Statement, Connection 等资源
7. 使用 JDBC 进行MySQL数据库增删改查的例子?
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
/**
* JDBCUtil.java
* 用来获取 Connection 类型的数据库连接
*/
public class JDBCUtil {
final static String driver = "com.mysql.cj.jdbc.Driver";
final static String url = "jdbc:mysql://localhost:3306/blog?useSSL=false&serverTimezone=UTC";
final static String user = "root";
final static String password = "password";
static {
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
System.out.println("数据库驱动加载失败");
e.printStackTrace();
}
}
public static Connection getConn() throws SQLException{
return DriverManager.getConnection(url, user, password);
}
public static void closeConn(Connection conn) {
if (null != conn) {
try {
conn.close();
} catch (SQLException e) {
System.out.println("Connection close failed!");
e.printStackTrace();
}
}
}
}
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.ResultSetMetaData;
public class CRUDUtil {
/**
* MySQL数据库CRUD
* 执行 DML 或 DDL 语句
*/
public static void exeuteDDLOrDDM(String sql) throws Exception {
try (
Connection conn = JDBCUtil.getConn();
Statement stmt = conn.createStatement()) {
int result = stmt.executeUpdate(sql);
if (result != 0) {
System.out.println("执行DML语句后, 有[" + result + "]条记录受影响" + "\n");
} else {
System.out.println("已执行DDL语句, 并成功返回[" + result + "]" + "\n");
}
}
}
/**
* MySQL数据库CRUD
* 执行 查询 语句
*/
public static void executeSelect(String sql) throws Exception {
try (
Connection conn = JDBCUtil.getConn();
Statement stmt = conn.createStatement()) {
ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) {
System.out.println(rs.getString(1) + "\t"
+ rs.getString(2) + "\t"
+ rs.getString(3) + "\t");
}
}
}
/**
* MySQL数据库CRUD
* 可执行 任何 SQL语句
*/
public static void executeSQL(String sql) throws SQLException {
try (
Connection conn = JDBCUtil.getConn();
Statement stmt = conn.createStatement()) {
boolean hasResultSet = stmt.execute(sql);
if (hasResultSet) {
try (
ResultSet rs = stmt.getResultSet()) {
ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();
while (rs.next()) {
for (int i = 0; i < columnCount; i++) {
System.out.print(rs.getString(i + 1) + "\t");
}
System.out.print("\n");
}
}
} else {
System.out.println("该SQL语句影响的记录有["
+ stmt.getUpdateCount() + "]条");
}
}
}
}
public class JDBCDemo {
/**
* MySQL SQL语句类型:
* DML : insert, update, delete
* DDL : create, alter, drop, truncate
* DCL : grant, revoke
* 查询语句 : select
*
* Statement用于执行SQL语句的方法:
* ResultSet executeQuary(String sql)方法只能执行查询语句
* int executeUpdate(String sql) 方法可执行DML或DDL语句
* boolean execute(String sql) 可执行任何SQL语句
*/
// DDL
static String sql1 = "create table demo "
+ "(d_id int primary key auto_increment,"
+ "d_name varchar(255),"
+ "d_body text);";
static String sql8 = "truncate demo";
static String sql9 = "alter table demo add photo mediumblob";
// DML
static String sql2 = "insert into demo values(0,'jeff','desc jeff .....',null)";
static String sql3 = "insert into demo values(0,'cony','desc cony .....',null)";
static String sql4 = "insert into demo values(0,'hurry','desc hurry .....',null)";
// select
static String sql5 = "select * from demo";
static String sql10 = "desc demo";
// DML
static String sql6 = "update demo set d_name='JULIA', d_body='desc julia.....' where d_id=4";
static String sql7 = "delete from demo where d_id=4";
public static void main(String[] args) throws Exception {
// CRUDUtil.exeuteDDLOrDDM(sql9);
// CRUDUtil.executeSelect(sql5);
CRUDUtil.executeSQL(sql5);
}
}
8. 离线 RowSet 接口简述?
RowSet 接口继承了 ResultSet 接口, RowSet 接口包含了 JdbcRowSet, CachedRowSet, FilteredRowSet, JoinRowSet 和 WebRowSet 常用子接口; 其中 JdbcRowSet需要保持与数据库的连接之外, 其余4个子接口都是离线的RowSet, 无须保持与数据库的连接
离线 RowSet 会直接将底层数据读入内存中, 封装成 RowSet 对象, 而 RowSet 对象则完全可以当成 java Bean 来使用
对离线的 RowSet, 程序在创建 RowSet 时已把数据从底层数据库加载到内存,从而降低数据库服务器的负载, 提高性能
CachedRowSet 是所有离线 RowSet 的父接口
9. RowSet 接口常用方法?
setUrl(String url)设置该RowSet要访问的数据库的RULsetUserName(String Name)设置该RowSet要访问的数据库的用户名setPassword(String password)设置该RowSet要访问的数据库的密码setCommand(String sql)设置使用该sql语句的查询结果来装填该RowSetexecute()执行查询语句populate(ResultSet rs)让该RowSet直接包装给定的ResultSet对象
10. RowSetProvider 类 和 RowSetFactory 接口?
Java 7 新增了 RowSetProvider类 和 RowSetFactory 接口, 其中 RowSetProvider 负责创建 RowSetFactory,而 RowSetFactory 通过方法创建 RowSet 实例, 这样就把应用程序与RowSet实现类分离开
-
方法:
- RowSetFactory factory = RowSetProvider.newFactory();
11. RowSetFactory 提供的创建 RowSet 实例的方法?
CachedRowSet createCachedRowSet()创建一个默认的 CachedRowSetFilteredRowSet createFilteredRowSet()创建一个默认的 FilteredRowSedbcRowSet createJdbcRowSet()创建一个默认的 JdbcRowSet 不支持离线JoinRowSet createJoinRowSet()创建一个默认的 JoinRowSetWebRowSet createWebRowSet()创建一个默认的 WebRowSet
12. 装填 RowSet 两种方法?
第一种: 通过Statement对象执行 executeQuery() 方法返回 ResultSet 对象; 调用RowSet实例的 populate(ResultSet rs) 方法, 并将上述的ResultSet 对象传入其中进行装填
第二种: 通过 RowSet实例的 setCommand(sql) 和 execute() 方法执行SQL查询, 用返回的数据来装填RowSet
13. 装填 RowSet 两种方法的两种例子?
`import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import javax.sql.rowset.CachedRowSet;
import javax.sql.rowset.RowSetFactory;
import javax.sql.rowset.RowSetProvider;
import app.MyINI;
public class RowSetFactoryTest1 {
static MyINI myini = new MyINI();
public static void query1(String sql) throws Exception {
Connection conn = JDBCUtil.getConn();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql);
RowSetFactory factory = RowSetProvider.newFactory();
CachedRowSet cachedRs = factory.createCachedRowSet();
cachedRs.populate(rs);
cachedRs.beforeFirst();
while (cachedRs.next()) {
System.out.println(cachedRs.getString(1) + "\t"
+ cachedRs.getString(2) + "\t"
+ cachedRs.getString(3) + "\t"
+ cachedRs.getString(4) + "\t");
}
rs.close();
stmt.close();
}
public static void query2(String sql) throws Exception {
Class.forName(myini.driver);
//
// 使用 RowSetProvider 创建 RowSetFactory
RowSetFactory factory = RowSetProvider.newFactory();
try (
// 使用 RowSetFactory 创建默认的 JdbcRowSet 实例
CachedRowSet cachedRs = factory.createCachedRowSet()) {
cachedRs.setUrl(myini.url);
cachedRs.setUsername(myini.user);
cachedRs.setPassword(myini.pass);
// 设置SQL查询语句
cachedRs.setCommand(sql);
// 执行查询语句
cachedRs.execute();
cachedRs.beforeFirst();
// 向前滚动结果集
while (cachedRs.next()) {
System.out.println(cachedRs.getString(1) + "\t"
+ cachedRs.getString(2) + "\t"
+ cachedRs.getString(3) + "\t"
+ cachedRs.getString(4) + "\t");
}
}
}
public static void main(String[] args) throws Exception {
query1("select * from demo");
System.out.println("=========================");
query2("select * from demo");
}
}