1、安装MySQL
-
修改my.ini
[mysqld] basedir = D:\develop\MySQL\mysql-5.7.31-winx64 datadir = D:\develop\MySQL\mysql-5.7.31-winx64\data port = 3306 character-set-server=utf8 #设置时区 default-time-zone=timezone default-time-zone = '+8:00' #lower_case_table_names=0 表名存储为给定的大小和比较是区分大小写的 #lower_case_table_names = 1 表名存储在磁盘是小写的,但是比较的时候是不区分大小写 #lower_case_table_names=2 表名存储为给定的大小写但是比较的时候是小写的 lower_case_table_names = 1 sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
-
安装
mysqld -install [名称,默认mysql]
-
启动服务
net start mysql 或 mysqld --console
-
无法启动情况下
mysqld --initialize-insecure
-
-
连接MySQL
// mysql [主机地址] -u[用户名] -p[密码]; mysql -uroot -p
-
修改密码
> use mysql; > update user set password=PASSWORD('新密码') where user='用户名'; > flush privileges; #更新权限 > quit; #退出
-
-
关闭服务
net stop mysql 或 mysqladmin -uroot shudown
-
移除
mysqld -remove [名称]
[client]
loose_prompt=\\u@\\h \\d >
default-character-set=utf8
loose_default-character-set = utf8
[mysql]
default-character-set=utf8
2、操作语句
1、DDL语句完成数据库及数据表的创建
-
查看当前数据库系统中的数据库列表
mysql>show databases;
-
使用DDL语句创建一个数据库mydb1
mysql> create database mydb1;
-
再次查看当前数据库列表
mysql> show databases;
-
切换至mydb1数据库
mysql> use mydb1;
-
查看当前数据库中的数据表
mysql> show tables;
-
使用DDL创建一个数据表
mysql> create table classes(clasid int, clasname varchar(30));
-
再次查看数据库中的数据表
mysql> show tables;
-
查看classes数据表结构
mysql> desc classes;
-
删除数据表
mysql> drop table classes;
-
删除数据库
mysql> drop database mydb1;
-
查询需要批量删除的表(模糊匹配)
SELECT CONCAT('drop table ', group_concat(TABLE_NAME), ';') FROM information_schema.`TABLES` WHERE table_schema = '数据库名' AND TABLE_NAME LIKE 'tab_%';
2、DML增删改查
-
增加
INSERT INTO [表] VALUES([],[],[],[],[]); INSERT INTO [表]([key1],[key2],...,[keyn])VALUES([],[],...,[]); INSERT INTO [表]([key1],[key2],...,[keyn])VALUES([],[],...,[]),([],[],...,[]),...,([],[],...,[]);
-
删除
DELETE FROM [表] WHERE [id] = n;
-
修改
UPDATE [表] SET key1 = value, key2 = value sql = sql*n WHERE [id] = n;
-
查找
-
*:所有
-
WHERE:条件判断
-
DISTINCT:不重复
-
BETWEEN n and m:在n和m之间
-
LIKE:模糊查询
LIKE "%条件%"
-
SUBSTRING:查询第n位开始后m位为xx
SUBSTRING(ename,n,m)='xx'
-
ORDER BY :默认情况下是升序;ASC 升序,DESC降序
SELECT * FROM tb_emp WHERE sal >=6000 ORDER BY sal ASC;
-
LIMIT:用来“截取”查询结果,常用于数据库的分页操作
-- LIMIT关键字后,只传一个参数时,从第一行开始取N条数据 SELECT * FROM tb_emp LIMIT 2; -- 设置两个参数,第一参数代表起始位置(从0开始),第二个参数,从位置开始往后几条数据 SELECT * FROM tb_emp LIMIT 0,2; -- 第一条和第二条
-
聚合函数
-- 聚合函数 SUM(expr)求和 AVG([DISTINCT] expr) 求平均值 -- MAX(expr) 取最大 MIN(expr) 取最小 COUNT(DISTINCT expr,[expr...]) 计数 SELECT AVG(sal) FROM tb_emp WHERE ename = 'XH'; SELECT AVG(DISTINCT sal) FROM tb_emp; SELECT MAX(sal) FROM tb_emp; SELECT COUNT(1) FROM tb_emp;
-
GROUP BY 分组
SELECT * FROM tb_emp GROUP BY deptno; SELECT AVG(sal),deptno FROM tb_emp GROUP BY deptno;
-
HAVING 关键字表示对分类后的结果再进行条件的过滤,经常会与WHERE进行对比
SELECT AVG(sal),deptno FROM tb_emp WHERE ename = 'XH' GROUP BY deptno HAVING AVG(sal) > 5000;
-
表关联,多表关联时,建议给表取别名
-
LEFT JOIN, 以左边表作为主表,附带显示其他关联的一些信息
SELECT * FROM tb_emp e LEFT JOIN tb_dept d ON e.deptno = d.did; --SELECT * FROM tb_emp e,tb_dept d ON e.deptno = d.did WHERE[]; SELECT e.*,d.* FROM tb_dept d LEFT JOIN tb_emp e ON d.did = e.deptno;
-
内关联 ,关联两张表时,条件必须两边都满足,能用INNER JOIN 尽量优先适用
SELECT * FROM tb_emp e INNER JOIN tb_dept d ON d.did = e.deptno;
-
RIGHT JOIN, 以右边表作为主表,进行查询操作
SELECT * FROM tb_emp e RIGHT JOIN tb_dept d ON e.deptno = d.did;
-
笛卡儿积 员工表中4条,部门3条,查询结果12条
SELECT * FROM tb_emp e, tb_dept d; SELECT * FROM tb_emp e, tb_dept d WHERE e.deptno = d.did;
-
SELECT * FROM tb_emp WHERE deptno = 10 OR deptno = 11; -- 子查询结果是一个或多个值时,采用IN/NOT IN SELECT * FROM tb_emp WHERE deptno IN (SELECT did FROM tb_dept); SELECT * FROM tb_emp WHERE deptno NOT IN (SELECT did FROM tb_dept); -- 子查询结果是一个值时,采用= 或 != SELECT * FROM tb_emp WHERE deptno = (SELECT did FROM tb_dept LIMIT 1); -- select * from A where id in(select id from B) -- SELECT * FROM A a WHERE EXISTS (SELECT * FROM B b WHERE b.id = a.id) -- 导致效率差异的原因和索引有关系 -- IN()适合B表比A表数据小的情况 -- EXISTS()适合B表比A表数据大的情况 -- 当A表数据与B表数据差不多时,IN与EXISTS效率差不多,可任选一个使用. -- NOT IN(不触发任何索引) 和 NOT EXISTS(触发索引) SELECT * FROM tb_emp e WHERE EXISTS (SELECT * FROM tb_dept d WHERE d.did = e.deptno); SELECT * FROM tb_emp e WHERE NOT EXISTS (SELECT * FROM tb_dept d WHERE d.did = e.deptno); -- UNION ALL和UNION拼接多个查询结果,保证列的个数一致,UNION有做去重操作 SELECT * FROM tb_emp UNION ALL SELECT * FROM tb_emp; SELECT * FROM tb_emp UNION SELECT * FROM tb_emp; SELECT eid,sal FROM tb_emp UNION ALL SELECT * FROM tb_dept; -- The used SELECT statements have a different number of columns
-
-
3、DCL
创建一个数据库用户z1,具有对数据库中所有表的SELECT/INSERT权限
GRANT SELECT,INSERT 数据库名.* TO 'cxl'@'localhost' IDENTIFIED BY '123'';
由于权限变更,需要将z1的权限变更,收回INSERT,只能对数据进行SELECT操作:
mysql -uroot
REVOKE INSERT ON 数据库名.* FROM 'cxl'@'localhost';
重新登录后执行前面的语句:
mysql -uz1 -p123
3、常用类型
-
常用数值类型
TINYINT:1个字节
INT:4个字节
-
近似值存储
FLOAT:4个字节
DOUBLE:8个字节
DECIMAL(M,D)/DEC(M,D):常用于精度比较高的存储,例如:银行金额计算
-
-
日期类型
DATETIME:比较常用
面试点:DATETIME和timestamp区别
-
字符类型(面试点):
CHAR(M):长度固定,当字符长度没有达到M时,左补空格,常用于身份证号的设计
VARCHAR(M):长度可变,当字符长度没有达到M时,不做任何操作
4、常用函数
a.字符串函数
concat(s1,s2,......sn) -- 连接s1,s2,.....,sn为一个字符串
insert(str,x,y,instr) -- 将字符串str从第x位置开始,y个字符长的子串替换为字符串instr
lower(str) -- 将字符串str中字符变为小写
upper(str) -- 将字符串str中字符变为大写
left(str,x) -- 返回字符串str最左边的x个字符
right(str,x) -- 返回字符串str最右边的x个字符
lpad(str,n,pad) -- 用字符串pad对str最左边进行填充,直到长度为n个字符长度
rpad(str,n,pad) -- 用字符串pad对str最右边进行填充,直到长度为n个字符长度
ltrim(str) -- 去掉字符串str左侧的空格
rtrim(str) -- 去掉字符串str右侧的空格
repeat(str,x) -- 返回str重复x次的结果
replace(str,a,b) -- 用字符串b替换字符串str中所有出现的字符串a
strcmp(s1,s2) -- 比较字符串s1和s2
trim(str) -- 去掉字符串行尾和行头的空格
substring(str,x,y) -- 返回从字符串str x位置起y个字符长度的字串
b.数值函数
abs(x) -- 返回x的绝对值
ceil(x) -- 返回大于x的最小整数值
floor(x) -- 返回小于x的最大整数值
mod(x,y) -- 返回x/y的模
rand() -- 返回0~1内的随机值
round(x,y) -- 返回参数x的四舍五入的有y位小数的值
truncate(x,y) -- 返回数字x截断为y位小数的结果
c.日期和时间函数
curdate() -- 返回当前日期
curtime() -- 返回当前时间
now() -- 返回当前的日期和时间
unix_timestamp(date) -- 返回日期date的unix时间戳
from_unixtime -- 返回unix时间戳的日期值
week(date) -- 返回日期date为一年中的第几周
year(date) -- 返回日期date的年份
hour(time) -- 返回time的小时值
minute(time) -- 返回time的分钟值
monthname(date) -- 返回日期date的月份名
date_format(date,fmt) -- 返回按字符串fmt格式化日期datee值
date_add(date,interval expr type) -- 返回一个日期或时间值加上一个时间间隔的时间值
datediff(expr,expr2) -- 返回起始时间expr和结束时间expr2之间的天数
MySQL支持的日期和时间格式:
%d -- 两位数字表示月中的天数(00,01,...,31)
%e -- 数字形式表示月中的天数(00,01,...,31)
%D -- 英文后缀表示月中的天数(1st,2nd,3rd,...)
%w -- 以数字形式表示周中的天数(0=Sunday,1=Monday,...,6=Saturday)
%j -- 以3位数字表示年中的天数(001,002,...,366)
%U -- 周(0,1,52),其中Sunday为周中的第一天
%u -- 周(0,1,52),其中Monday为周中的第一天
%M -- 月名(January,February,...,December)
%b -- 缩写的月名
%m -- 两位数字表示的月份(01,02,...,12)
%c -- 数字表示的月份(1,2,...,12)
%Y -- 4位数字表示的年份
%y -- 两位数字表示的年份
%% -- 直接值“%”
hour -- 小时 -- hh
minute -- 分 -- mm
second -- 秒 -- ss
year -- 年 -- YY
month -- 月 -- MM
day -- 日 -- DD
year_month -- 年和月 -- YY-MM
day_hour -- 日和小时 -- DD hh
day_minute -- 日和分钟 -- DD hh:mm
day_second -- 日和秒 -- DD hh:mm:ss
hour_minute -- 小时和分 -- hh:mm
hour_second -- 小时和秒 -- hh:ss
minute_second -- 分钟和秒 -- mm:ss
d.流程函数
if(value,t,f) -- 如果value是真,返回t;否则返回f
ifnull(value1,value2) -- 如果value1不为空,返回value1,否则value2
case when[value1] then [result]...else [default] end -- 如果value1是真,返回result,否则返回default
case [expr] when [value1] then [result1] ... else
[default] end -- 如果expr等于value1,返回result1,否则返回default
5、约束
- NOT NULL:非空
- DEFAULT:默认值
- PRIMARY KEY:主键,唯一且非空。
- UNIQUE:唯一,可以为空
- CHECK:检查约束(MySQL不支持)
- FOREIGN KEY:外键,把一个字段关联到另一个表的主键
6、索引
索引:它是SQL优化的重要手段之一,相当于书本的目录,根据目录页码快速找到所需的内容,索引是单独的,物理的对数据库中一列或多列的值进行排序的一种存储结构。
注意:索引并不是添加的越多越好,索引并不是添加之后就一定会触发。
-- 使用CREATE INDEX创建索引
CREATE [UNIQUE] INDEX INDEX_索引名 ON 表名(字段);
-- 使用ALTER TABLE创建索引
ALTER TABLE 表名 ADD INDEX INDEX_索引名(字段); -- 普通索引
ALTER TABLE 表名 ADD UNIQUE (字段); -- 唯一约束
ALTER TABLE 表名 ADD PRIMARY KEY (字段) -- 该语句添加一个主键,这意味着索引值必须是唯一的,且不能为NULL。
-- 验证索引被启用的情况
EXPLAIN SELECT 字段 FROM 表名;
-- 显示索引信息
SHOW INDEX FROM 表名;
SHOW KEYS FROM 表名;
-- 创建复合索引
CREATE INDEX INDEX_索引名 ON 表名(字段1,字段2);
-- 删除索引
DROP INDEX INDEX_索引名 ON 表名;
ALTER TABLE 表名 DROP INDEX INDEX_索引名;
ALTER TABLE 表名 DROP PRIMARY KEY;
-
索引分类:
普通索引、复合索引、唯一索引、主键、全文检索
-
那些场景适合添加索引?
-
经常接在WHERE后作为查询条件
-
表关联时,关联的字段
-
字段唯一,可以添加唯一索引
-
表中数据重复性不是非常高
-
经常更新的字段不建议构建索引
-
查询显示的列名不需要加索引
-
如果查询时,多个字段经常被查询,建议适用复合索引
-
-
那些场景不适合添加索引?
经常更新的字段不建议构建索引
表中数据重复率太高,例如:性别
-
一般情况下,表中添加普通索引和复合索引居多,唯一和主键,主较特殊的;
-
注意:复合索引需要遵循最左原则
最左原则:(a,b,c),有效索引 a / a,b / a,b,c
-
索引失效的情况:
-
并没有将加了索引的字段作为条件
-
字段定义的是字符类型,查询时需要添加’ ’
-
模糊查询时 LIKE ‘%ABC%’ ,但是 LIKE ‘ABC%’ 可以触发索引
-
查询条件采用了OR关键字
-
针对复合索引,没有遵循最左原则
-
应用了一些函数,也会导致索引失效
-
-
MySQL中如何查看索引是否触发?
借助EXPLAIN关键字执行SQL语句
-
possible_key:可能会触发的索引
-
key:触发的索引
-
rows:估算的结果数据行
-
Extra:执行具体描述
-
-
BTREE索引和HASH索引的区别?
-
HASH索引满足等值查询,效率非常高
-
BTREE索引查询数据时比较适用于范围的查找,例如:<> 、ORDER BY 等场景比较适用
-
7、视图
一张虚拟的表,它是由SQL语句查询结果组成的一个数据集,常用于频繁使用某些SQL语句,将他们构成一个视图。
视图经常用于查询操作,比较少也会用于更新操作(增/删/改),在更新操作时,需要注意,并不是所有的视图都可以进行更新操作,例如:表关联查询、采用聚合函数、DISTINCT、GROUP BY、HAVING、UNION、UNION ALL、子查询等等。
CREATE [OR REPLACE] VIEW v_name
AS SELECT ......;
-- 查看视图定义
SHOW CREATE VIEW v_name;
-- 显示视图的信息
SHOW TABLE STATUS [FROM db_name] [LIKE 'pattern'];
-- 查看视图设计信息
DESCRIBE | DESC v_name;
SHOW FIELDS FROM v_name;
DROP VIEW [IF EXISTS] v_name[,view_name];
8、触发器
在对某一张表进行更新(增/删/改)操作,执行触发器中定义语句集合。
-
特性:
- 触发条件:INSERT \ DELETE \ UPDATE
- 触发时机:AFTER / BEFORE
- 触发频率:针对每一行执行
-
建议:少用触发器;原因:效率问题,隐式操作等
-
触发器构建:
-- 构建触发器 CREATE TRIGGER <触发器名> < BEFORE | AFTER > <INSERT | UPDATE | DELETE > ON <表名> FOR EACH ROW<触发器主体> -- 查看创建的触发器 SHOW TRIGGERS; -- 删除触发器 DROP TRIGGER [ IF EXISTS ] [数据库名] <触发器名>
触发器主体:可以是SQL语句集,即可以是一条或n条SQL语句;当是n条SQL,需采用 BEGIN END 代码块,类似于java中的{ },还需要注意结束符号问题,MySQL默认结束符号为分号(;),可以采用 DELIMITER 关键字对结束符号进行修改,例如:$$
触发器中的OLD和NEW:
- 在INSERT型触发器中,NEW用来表示新插入的数据,不管是BEFORE 还是 AFTER
- 在UPDATE型触发器中,OLD用来表示已经被修改掉或即将被修改的数据,NEW用来表示即将要修改或者已经修改了的数据。
- 在DELETE型触发器中,OLD用来表示即将删除或已经被删除的原数据
注意:触发器是附在表上来进行定义的,触发内容不可以操作当前表
表复制操作:
-- 复制表的结构及数据,主键、索引没能够复制
CREATE TABLE 新表 SELECT * FROM 旧表;
-- 完整复制表的结构、主键、索引,未曾复制数据
CREATE TABLE 新表 LIKE 旧表;
INSERT INTO 新表 SELECT * FROM 旧表; -- 数据复制
9、存储过程
SQL语句集,也可以写一些业务内容
-
注意:
=是判断
:=是赋值
=只有在set和update时才是和:=一样
-
赋值操作时
- SELECT…INTO…
- SET param1 = param2;
- SELECT @param := value (OUT里面)
语法:
-- 创建
CREATE PROCEDURE pro_name(IN|OUT|INOUT 参数名 参数类型)
BEGIN
routine_body
END;
-- 调用
CALL sp_name(parms)
-- 删除
DROP PROCEDURE pro_name
定义变量:DECLARE 参数名 参数类型 [DEFAULT 默认值]
赋值:SELECT 字段 INTO 参数名 FROM 表 WHERE 条件
输出:SELECT 参数名
-
IF语句
IF 条件1 THEN 操作1; [ELSEIF 条件2 THEN 操作2]... [ELSE 操作3]; END IF;
-
CASE语句
CASE 变量 WHEN 值1 THEN 操作1; [WHEN 值2 THEN 操作2]... [ELSE 操作3] END CASE;
-
LOOP
name_loop:LOOP 执行语句块; -- 出循环 IF 条件1 THEN LEAVE name_loop; END IF; END LOOP;
-
WHILE
WHILE 条件 DO 执行语句块; END WHILE;
-
REPEAT
REPEAT 执行语句块; UNTIL 判定 END REPEAT;
-
函数
-- 自定义函数 CREATE FUNCTION 函数名(变量 类型) RETURNS 返回类型 BEGIN RETURN (); END; -- 调用函数 SELECT 函数名(变量); -- 删除函数 DROP FUNCTION 函数名;
-
游标/光标
CREATE PROCEDURE pro_name() BEGIN DECLARE done INT DEFAULT FALSE; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; -- 声明光标: DECLARE 光标名 CURSOR FOR [SELECT语句]; -- DECLARE cur1 CURSOR FOR SELECT empno,sal FROM t_employee; -- OPEN光标: OPEN 光标名; name_loop:LOOP -- 出循环 IF done THEN LEAVE name_loop; END IF; -- FETCH光标: 下移 FETCH [[NEXT] FROM] cursor_name INTO var_name[,var_name]...; END LOOP; -- CLOSE光标: CLOSE 光标名; END;
10、事务
BEGIN:开启事务
-
事务的特征:ACID,
原子性(Atomicity)、一致性(Correspondence)、隔离性(Isolation)、持久性(Durability)。
-
原子性:事务中所有的操作视为一个原子单元,所有操作完全提交(成功)或完全回滚(失败)
-
一致性:事务完成后,所有数据从一种状态变更为另一种状态,确保数据完整性
-
隔离性:事务和事务之间有一定隔离
-
持久性:事务完成后,所做更新操作对数据影响是永久的
-
-
隔离级别:
-
READ-UNCOMMITTED:读取未提交内容。(容易发生脏读)
-
READ-COMMITTED:读取提交内容。(可能发生不可重复读、幻读)
-
REPEATABLE-READ:可重复读
-
SEIALIZABLE:可串行化
查看当前隔离级别;
SHOW VARIABLES LIKE 'tx_isolation';
设置隔离级别
-- 读取未提交 SET GLOBAL TRANSACTION ISOLATION LEVEL [READ UNCOMMITTED];
-
脏读:某一个事务已更新一份数据,另一个事务读取了同一份数据,由于某些原因,导致前一个事务回滚操作,后面的事务读取的数据不正确。
-
不可重复读:在一个事务的两次査询数据不一致,这可能是两次查询过程中,另一个事务更新原有的数据。
-
幻读:在一个事务中两次查询数据条数不一致,例如:在一个事务中查询了几列值,另一个事务此时插入了几条新数据,先前的事务再次查询时,就发现多了几条数据是没有的。
-
11、JDBC
Java连接数据库:
public class JdbcUtil {
private static final String url = "jdbc:mysql://localhost:3306/数据库";
private static final String user = "root";
private static final String password = "";
public static Connection getConn() throws ClassNotFoundException, SQLException {
// 1. 加载驱动,通过反射 Maven
Class.forName("com.mysql.jdbc.Driver");
// 2.连接数据库
Connection conn = DriverManager.getConnection(url, user, password);
return conn;
}
public static void close(ResultSet rs , PreparedStatement pstmt, Connection conn) {
if(rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(pstmt != null) {
try {
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void close(PreparedStatement pstmt, Connection conn) {
if(pstmt != null) {
try {
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
BaseDao.java
public class BaseDao<T> {
private Class<T> clazz;
@SuppressWarnings("unchecked")
public BaseDao() {
// 得到当前类的带有泛型信息的父类型
Type type = this.getClass().getGenericSuperclass();
// 得到实际的泛型参数类型
ParameterizedType pType = (ParameterizedType) type;
clazz = (Class<T>) pType.getActualTypeArguments()[0];
}
/**
* 查询
*
* @param sql
* @param params
* @return
* @throws Exception
*/
public List<T> find(String sql, Object[] params) throws Exception {
PreparedStatement psmt = null;
ResultSet rs = null;
// 连接数据库
Connection conn = JdbcUtil.getConn();
// 预编译SQL
psmt = conn.prepareStatement(sql);
// 通过循环动态设定参数
if (params != null) {
for (int i = 0; i < params.length; i++) {
psmt.setObject(i + 1, params[i]);
}
}
// 执行SQL语句
rs = psmt.executeQuery();
// 获取列相关信息
ResultSetMetaData rsmd = rs.getMetaData();
// 查询多少列
int colCount = rsmd.getColumnCount();
List<T> dataList = new ArrayList<T>();
while (rs.next()) {
// 采用反射实例化对象
T t = (T) clazz.newInstance();
// 返回Employee类的BeanInfo对象
BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
// 使用BeanInfo返回属性描述的对象数组
PropertyDescriptor[] propDescs = beanInfo.getPropertyDescriptors();
for (int i = 1; i <= colCount; i++) {
String colName = rsmd.getColumnName(i);
for (PropertyDescriptor prop : propDescs) {
// 当列名和属性名一致的时候
if (colName.equals(prop.getName())) {
// 执行是属性对应的Setter方法
prop.getWriteMethod().invoke(t, rs.getObject(i));
continue;
}
}
}
dataList.add(t);
}
JdbcUtil.close(rs, psmt, conn);
return dataList;
}
/**
* 更新共通
* @param sql
* @param params
* @return
* @throws Exception
*/
public int update(String sql, Object[] params) throws Exception {
PreparedStatement psmt = null;
// 连接数据库
Connection conn = JdbcUtil.getConn();
// 预编译SQL
psmt = conn.prepareStatement(sql);
// 通过循环动态设定参数
if (params != null) {
for (int i = 0; i < params.length; i++) {
psmt.setObject(i + 1, params[i]);
}
}
return psmt.executeUpdate();
}
}
查
String sql = "SELECT * FROM commodity WHERE cid = ?";
Object[] param = {pid};
List<Product> list = pd.find(sql, param);
for (Product product : list) {
System.out.println(product);
}
其它
String sql = "INSERT INTO car(uid,create_time) VALUES (?,NOW());";
Object[] param = {pid};
int flat = pd.update(sql, param);
if (flat==1) {
System.out.println("已选择该商品");
}
查
public class JdbcCommon {
public List<?> find(String sql,Object[] params) throws Exception{
PreparedStatement psmt = null;
ResultSet rs = null;
//连接数据库
Connection conn = JdbcUtil.getConn();
//预编译
psmt = conn.prepareStatement(sql);
//通过循环动态设定参数
if (params!=null) {
for (int i = 0; i < params.length; i++) {
psmt.setObject(i+1, params[i]);
}
}
//执行SQL语句
rs = psmt.executeQuery();
List<Map<String, Object>> dataList = new ArrayList<>();
//获取列相关信息
ResultSetMetaData rsmd = rs.getMetaData();
//查询多少列
int colCount = rsmd.getColumnCount();
while (rs.next()) {
Map<String, Object> map = new HashMap<String, Object>();
for (int i = 0; i < colCount; i++) {
map.put(rsmd.getColumnName(i), rs.getObject(i));
}
dataList.add(map);
}
JdbcUtil.close(rs, psmt, conn);
return dataList;
}
}