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");
}
}