赞
踩
DB: DateBase 数据库,储存数据
DBMS:数据库管理系统,维护和获取数据
关系型数据库(SQL)
MySQL,Oracle,Sql Server,DB2,SQLIte…
通过表和表之间,行与列之间进行数据的存储
百度百科:关系型数据库,是指采用了关系模型来组织数据的数据库,其以行和列的形式存储数据,以便于用户理解,关系型数据库这一系列的行和列被称为表,一组表组成了数据库。用户通过查询来检索数据库中的数据,而查询是一个用于限定数据库中某些区域的执行代码。关系模型可以简单理解为二维表格模型,而一个关系型数据库就是由二维表及其之间的关系组成的一个数据组织。
非关系型数据库(NoSQL)Not Only
Redis,MogoDB…
非关系型数据库,对象存储,通过对象自身的属性来决定
mysql -uroot -p123456 --链接数据库 或者输完-p后敲一下回车,再输入密码,******
update mysql.user set authentication_string=password('123456') where user='root' and Host = 'localhost'; --修改用户密码
flush privileges; --刷新权限
------------------------------------
--单行注释
/*多行注释*/
show databases; --查看所有的数据库
use school -- 切换数据库 use 数据库名
show tables; --查看数据库中所有的表
describe student; -- 查看表中的信息 student为表名
create database westos; --创建一个数据库
exit; --退出
MySQL关键字不区分大小写
[ ]中内容可选
CREATE DATABASE [IF NOT EXISTS] westos;
DROP DATABASE [IF EXISTS] westos
USE ‘school’ --``这个符号可以用来修饰我们的表名或特殊字符
SHOW DATABASES --
数值
tinyint 1个字节
smallint 2个字节
mudiumint 3个字节
int 4个字节
bigint 8个字节
float 4个字节
double 8个字节
decimal 字符串形式的浮点数 用于金融计算使用
字符串
char 字符串固定大小的 0~255
varchar 可变字符串 0~65535 相当于String类型
tinytest 微型文本 2^8 - 1
test 文本串 2^16 - 1 保存大文本
时间和日期
data YYYY-MM-DD,日期格式
time HH:mm:ss 时间格式
datetime YYYY-MM-DD HH:mm:ss 最常用的时间格式
timestap 时间戳,初始时间为1970.1.1到现在的毫秒数
year 年份表示
null
没有值
不要运用NULL进行运算
CREATE TABLE IF NOT EXISTS `student`(
`name` VARCHAR(5) NOT NULL DEFAULT'匿名' COMMENT'姓名',
`age` INT(3) NOT NULL DEFAULT'0' COMMENT'年龄',
`id` INT(6) NOT NULL AUTO_INCREMENT COMMENT'学号',
`address` VARCHAR(33) DEFAULT NULL COMMENT'地址',
`birthday` DATETIME DEFAULT NULL COMMENT'生日',
PRIMARY KEY(`id`)
)ENGINE = INNODB DEFAULT CHARSET=utf8
--出现的问题 default charset = utf8 没有-
--varchar类型的引用时英文字符单引号
--所有的语句后面加,最后一句不用加
--primary key 主键,一般一个表只有唯一的主键
--注意写注释
sql语法中什么类型的值需要用单引号‘’修饰?
1)char varchar text blob date datetime boolean 要加单引号
2)int float double 不用
3)时间型数据也需要单引号修饰。
常用命令
show create database school --显示创建数据库的语句
show create table student --显示创建student数据表的语句
desc student --显示表的结构
MySAM 早些年使用,节省空间,速度较快
InnoDB 默认使用,安全性高,能进行事物的处理,多表多用户操作
MyISAM | InnoDB | |
---|---|---|
事务支持 | 不支持 | 支持 |
数据行锁定 | 不支持 | 支持 |
外键约束 | 不支持 | 支持 |
全文索引 | 支持 | 支持 |
表空间的大小 | 较小 | 较大,大约2倍 |
所有数据库文件都在data目录下,一个文件夹对应一个数据库,本质是文件的存储
InnoDB在数据库表中只有一个*.frm文件,以及上级目录下的ibdata1文件
MyISAM对应,*.frm , *.MYD(数据文件,data) , *.MYI(索引文件,index)
另:字符集编码utf-8,若不设置,不支持中文
ALTER TABLE student RENAME AS student1 -- 修改表名 alter table 旧表名 rename as 新表名
ALTER TABLE student1 ADD gpa INT(3) -- 增加字段 alter table 表名 add 字段名 类型
ALTER TABLE student1 MODIFY age VARCHAR(3) -- 修改数据类型 alter table 表名 modify 字段名 类型
ALTER TABLE student1 CHANGE age age1 INT(3) -- 修改字段名,同时可以改变类型 alter table 表名 change 旧字段名 新字段名 类型
-- modify用于修改类型约束
--change用于改变名字也可以改变约束 但是要同时出新的名字和类型
ALTER TABLE student DROP gpa -- 删除字段 alter 表名 drop 字段名
DROP TABLE [if exists]student -- 删除表
总结:
所有创建和删除尽可能加上 if exists 防止报错
字段注意用上 ``
相当于学生的年级对年级数据库中数据的引用(有点绕嘴。。。
CREATE TABLE `grade` (
`gradeid` VARCHAR(33) COMMENT'年级'
)ENGINE=INNODB DEFAULT CHARSET = utf8
ALTER TABLE `student` ADD `gradeid` VARCHAR(33)
ALTER TABLE `student`
ADD CONSTRAINT `FK_gradeid` FOREIGN KEY(`gradeid`) REFERENCES `grade`(`gradeid`);
以上操作时物理外键,数据库级别的外键,不建议使用,因为数据过多会产生麻烦
INSERT INTO `student` (`name`) VALUE('小王'),('小贾') -- 不同行的值用括号括起来,并且用逗号隔开
INSERT INTO `student`(`age`) VALUE(22),(21) -- 这样插入不会在小王和小贾的值中做修改,而是产生新的两行
INSERT INTO `student`(`name`,`age`,`address`,`gradeid`) VALUE('小王',22,'天津市','机电171')
INSERT INTO `student`(`name`,`age`,`id`,`address`,`birthday`,`gradeid`) VALUE('小张',33,170788,'深圳市','1888-11-11 22:33:33','会计162')
-- insert into 表名(类型) value(一一对应的值)
-- 各个类型和对应的值用逗号隔开
-- 若你不想写类型,插值要全部给值进行插入,且要按照表格的顺序
INSERT INTO `student` VALUE('小张',33,170788,'深圳市','1888-11-11 22:33:33','会计162')
UPDATE `student` SET `age`=22 WHERE id = 1 UPDATE `student` SET `address`='天津市',`birthday`='1111-11-11 11:33:33',`gradeid`='大三' WHERE id = 1 -- update 表名 set 要求改的属性(逗号隔开) [where条件] -- 注:<> 是 != 不等于号 UPDATE `student` SET `gradeid`='二十一世纪' WHERE id BETWEEN 1 AND 5 -- between ... and ... 是全闭区间 -- 多个条件定位 无数量上限 UPDATE `student` SET `address` = '中国' WHERE `gradeid` = '二十一世纪' AND id = 1 -- and = && UPDATE `student` SET `name` = 'dream' WHERE `gradeid`='二十世纪' OR id < 5 -- or = || UPDATE `student` SET `name`='小王' -- 不写条件就会全部修改,赶紧跑路吧。。。
-- delete from 表名 where 条件 不写条件全删,赶紧跑路。。。
DELETE FROM `student` WHERE id = 1
DELETE FROM `student` WHERE id > 3 AND `gradeid`='二十一世纪'
-- 完全清空一个数据库表,但是表的结构和索引约束不变
truncate 'student'
delete 和 truncate 的区别
相同点:都能删除数据
不同点:truncate 重新设置自增列,计数器会归零。
truncate不会影响事务
delete删除的问题(了解
重启数据库后
InnoDB 自增列会从1开始(存在内存中,断电即失
MyISAM 继续从上一个自增开始(存在文件中,不会丢失
Data Query Language:数据查询语言
数据库中最核心的语言
/*创建顾客表*/ CREATE TABLE IF NOT EXISTS customer( c_id CHAR(6) PRIMARY KEY, NAME VARCHAR(30)NOT NULL, location VARCHAR(30), salary DECIMAL(8,2) )ENGINE = INNODB DEFAULT CHARSET = utf8; /*创建银行表*/ CREATE TABLE IF NOT EXISTS bank( b_id CHAR(5) PRIMARY KEY, bank_name CHAR(30) NOT NULL )ENGINE = INNODB DEFAULT CHARSET = utf8; /*创建存款表(注意外键的代码使用)*/ CREATE TABLE IF NOT EXISTS deposite( d_id INT(10) AUTO_INCREMENT PRIMARY KEY, c_id CHAR(6), b_id CHAR(5), dep_date DATE, amount DECIMAL(8,2), CONSTRAINT FK_c_id FOREIGN KEY(c_id) REFERENCES customer(c_id) )ENGINE = INNODB DEFAULT CHARSET = utf8; /*插入数据*/ INSERT INTO customer VALUES('101001','孙杨','广州',1234), ('101002','郭海','南京',3526), ('101003','卢江','苏州',6892), ('101004','郭惠','济南',3492); INSERT INTO bank VALUES('B0001','工商银行'), ('B0002','建设银行'), ('B0003','中国银行'); INSERT INTO bank VALUES('B0004','农业银行'); INSERT INTO deposite VALUES(1,'101001','B0001','2011-04-05',42526), (2,'101002','B0003','2012-07-15',66500), (3,'101003','B0002','2010-11-24',42366), (4,'101004','B0004','2008-03-31',62362), (5,'101001','B0003','2002-02-07',56346), (6,'101002','B0001','2004-09-23',353626), (7,'101003','B0004','2003-12-14',36236), (8,'101004','B0002','2007-04-21',26267), (9,'101001','B0002','2011-02-11',435456), (10,'101002','B0004','2012-05-13',234626), (11,'101003','B0003','2001-01-24',26243), (12,'101004','B0001','2009-08-23',45671);
-- 查询表中所有的数据 -- select * from 表名 SELECT * FROM `customer` -- 查询指定列的数据 -- select 列名(用逗号隔开) from 表名 SELECT `name`,`location` FROM `customer` -- 将查询出来的列名字改个好看的 用as 同样 表名也可以改 SELECT `name` AS 姓名,`location` AS 家乡 FROM `customer` AS c -- 将姓名加上一些修饰语或者前缀 利用concat SELECT CONCAT('姓名:',`name`) AS 有前缀的姓名 FROM `customer` SELECT CONCAT('姓名:',NAME) AS 有前缀的姓名,CONCAT('家','乡','是',`location`) AS 家乡 FROM `customer` -- 多点字符串也行 -- 查询版本 SELECT VERSION() -- 用来简单加减乘除计算 SELECT 3*3+3-1 AS 结果 -- 查询自增的步长 SELECT @@auto_increment_increment -- 查询出来的值也可进行修改 将存款加1 SELECT `amount`+1 AS '存款+1' FROM`deposite`
-- 筛选出所有有存款的数据
select * from deposite
-- 选出b_id列的数据
select `b_id` from deposite
-- 取出重复的数据,重复的数据只显示一条
select distinct `b_id` from deposite
-- and = && ,or = ||
SELECT *FROM `deposite` WHERE `amount` BETWEEN 50000 AND 100000
SELECT * FROM `deposite` WHERE `amount`<50000 || `amount` > 100000
SELECT * FROM `deposite` WHERE `amount`> 100000 && `amount` <300000
SELECT * FROM `deposite` WHERE `amount` >= 330000
本质上也是比较运算符的运用
运算符 | 语法 | 描述 |
---|---|---|
IS NULL | a is null | 如果a为null,结果为true |
IS NOT NULL | a is not null | 如果操作符不为 null,结果为true |
BETWEEN | a between c and d | a 在b c之间结果为true |
Like | a like b | SQL匹配,如果a匹配b,则结果为true |
In | a in (a1,a2,a3…) | 假设a在a1,a2或者a3中为某一个值,结果为true |
数据库信息由于涉及隐私,不便公布,若仅供学习请私聊索取
like 相关
-- 查询表中 姓王两个字的人
SELECT `id`,`name`,`birthday` FROM`class` WHERE `name` LIKE '王_'
-- 查询表中 姓王的人
SELECT`id`,`name`,`sex`,`QQ` FROM `class` WHERE `name` LIKE '王%'
-- 查询表中带有明字的人
SELECT `id`,`name`,`sex` FROM `class` WHERE `name` LIKE '%明%'
-- 查询地点中包含城市的人
SELECT`name` FROM `class` WHERE `location` LIKE '%城市'
-- 注: _表示一个字符 %表示任意个字符0~n 这两个符号只在like这里用
in 相关,用于查询具体的值
-- 查询位置在'小城镇','中小城市'的人
SELECT `name`,`id`,`location` FROM `class` WHERE `location` IN ('小城镇','中小城市')
-- 查询位置在'农村'的人
SELECT `name`,`location` FROM `class` WHERE `location` IN('农村')
-- 查询学号为170788,170777,170799,170766的人
SELECT `name`,`id` FROM `class` WHERE `id` IN (170788,170777,170799,170766)
-- 查询学号在170780与170790之间且位置在农村的同学 多个条件注意运用逻辑链接符
SELECT `name`,`location`,`id` FROM`class` WHERE `id` BETWEEN 170780 AND 170790 AND `location` IN ('农村')
not null 相关
-- 查询生日不为空的且在1999-1-1之后出生的同学 注:日期写上单引号
SELECT `name`,`birthday` FROM`class` WHERE `birthday` IS NOT NULL AND `birthday`>'1999-1-1'
操作 | 描述 |
---|---|
Inner join | 返回两表的交集数据,也就是都有的才返回 |
Left join | 会从左表中返回所有的值 |
Right join | 会从右表中返回所有的值 |
-- 左表查询本班学生重修情况 会返回所有左表中的数据也就是class中的 -- 并将重修情况对应上class中的同学 -- on多个条件用and连接不用逗号 SELECT c.`id`,c.`name`,`KCM` FROM`class` AS c LEFT JOIN `chongxiu` AS cx ON c.`id` = cx.`id` AND c.`name` = cx.`name` -- 若将left改为right,则为右表查询 -- 此时会将右表中数据,也就是chongxiu中的数据全部返回 -- 并且对应上class中的id和name SELECT c.`id`,c.`name`,`KCM` FROM`class` AS c RIGHT JOIN `chongxiu` AS cx ON c.`id` = cx.`id` AND c.`name` = cx.`name` -- Inner join查询 -- 返回的是两者的交集,即返回class中chongxiu的同学 SELECT c.`id`,c.`name`,`KCM` FROM`class` AS c INNER JOIN `chongxiu` AS cx ON c.`id` = cx.`id` AND c.`name` = cx.`name` -- 三联表查询 -- 查询同学的成绩,左表查询 -- 再inner join chongxiu表中,返回本班同学的重修科目和gpa SELECT c.`name`,`location`,c.`id`,`gpa`,`KCM` FROM `class` AS c LEFT JOIN `bigclass` AS bc ON c.`id` = bc.`id` AND c.`name` = bc.`name` INNER JOIN `chongxiu` AS cx ON c.`id` = cx.`id` AND c.`name` = cx.`name`
练习
-- 左表查询以class为基准,返回gpa>3.3的同学
SELECT c.`name`,`location`,c.`id`,`gpa`
FROM `class` AS c
LEFT JOIN `bigclass` AS bc
ON c.`id` = bc.`id` AND c.`name` = bc.`name`
WHERE gpa > 3.3
总结:
自己的表和自己的表连接,核心:一张表拆为两张一模一样的表(简称我连我自己。。。后文有自我理解,我觉得稍容易接受一点儿
基础数据
CREATE TABLE `school`.`category`( `categoryid` INT(3) NOT NULL COMMENT 'id', `pid` INT(3) NOT NULL COMMENT '父id 没有父则为1', `categoryname` VARCHAR(10) NOT NULL COMMENT '种类名字', PRIMARY KEY (`categoryid`) ) ENGINE=INNODB CHARSET=utf8 COLLATE=utf8_general_ci;
INSERT INTO `school`.`category` (`categoryid`, `pid`, `categoryname`) VALUES ('2', '1', '信息技术');
insert into `school`.`CATEGOrY` (`categoryid`, `pid`, `categoryname`) values ('3', '1', '软件开发');
insert into `school`.`category` (`categoryid`, `PId`, `categoryname`) values ('5', '1', '美术设计');
insert iNTO `School`.`category` (`categoryid`, `pid`, `categorynamE`) VAlUES ('4', '3', '数据库');
insert into `school`.`category` (`CATEgoryid`, `pid`, `categoryname`) values ('8', '2', '办公信息');
insert into `school`.`category` (`categoryid`, `pid`, `CAtegoryname`) values ('6', '3', 'web开发');
inserT INTO `SCHool`.`category` (`categoryid`, `pid`, `categoryname`) valueS ('7', '5', 'ps技术');
自连接前的表格
父类
categoryid(本类id | categoryName(类名 |
---|---|
2 | 信息技术 |
3 | 软件开发 |
5 | 美术设计 |
子类
pid(父类id | categotyid(本类id | categoryName(类名 |
---|---|---|
3 | 4 | 数据库 |
2 | 8 | 办公信息 |
3 | 6 | web开发 |
5 | 7 | ps技术 |
操作代码
SELECT a.`categoryname` AS '父栏目',b.`categoryname` AS '子栏目' -- 两列数据,一列为父栏目,一列为子栏目,它们的数据源均为categoryname
FROM `category` AS a ,`category` AS b -- 在一个表中查,自连接
WHERE a.`categoryid` = b.`pid` -- 父类自身的id = 子类的父id
自连接后
我自己的理解
-- 再加上一条categoryid列,便于理解,此时这样id为父类id
SELECT a.`categoryname` AS '父栏目',b.`categoryname` AS '子栏目',a.`categoryid`
FROM `category` AS a ,`category` AS b
-- 这一步,相当于,把category这个表变成两个一模一样的表
-- 也就是前文所说的拆成两个表,其本质上也就是在category表拿不同的数据而已
-- a拿出父类数据,也就是父类的名字,b拿出子类数据,也就是子类名字
WHERE a.`categoryid` = b.`pid`
-- 这里是它们的对应关系,拿出数据后你怎么让关联起来?
-- a是父类,有自己的id,b是子类有父类id,有自己的id
-- 让子类的父类id 等于父类的id 就是让儿子找到自己的爸爸 这样就联系起来了
-- 那么这个where条件就是,软件开发:“我爸爸是3。” 这里有2,3,5的父亲,
-- 让3父亲与软件开发关联起来,就相当于 子类的父id = 父id
总结:自连接有局限,仅限于在同一列拆分出数据,分成不同栏目
升序排列
SELECT `id`,`name`,`class` FROM `bigclass`
ORDER BY `gpa` ASC
降序排列
SELECT c.`id`,c.`name`,`gpa`
FROM `class` AS c
LEFT JOIN `bigclass` AS b
ON c.`id` = b.`id` AND c.`name` = b.`name`
ORDER BY `gpa` DESC
-- 从第一个数据开始(第一个数据的索引为0),每页装5个
SELECT c.`id`,c.`name`,`gpa`
FROM `class` AS c
LEFT JOIN `bigclass` AS b
ON c.`id` = b.`id` AND c.`name` = b.`name`
ORDER BY `gpa` DESC
LIMIT 0,5
-- 查出年级前10名且绩点大于3
SELECT`id`,`name`,`class`,`gpa`
FROM`bigclass`
WHERE `gpa`>3
ORDER BY `gpa` DESC
LIMIT 0,9
-- 查询班级中绩点在3以上的同学
SELECT `id`,`name`
FROM`class`
WHERE `id` IN(
SELECT`id` FROM `bigclass` WHERE `gpa`>3)
-- 通过location来分组,来统计来自不同地区的数量,用having来划分条件
-- having是用于修饰分组的次级条件
SELECT COUNT(`name`),`location`
FROM `class`
GROUP BY `location`
HAVING `location` IN('中小城市','农村')
-- 通过性别来分组,并统计各组人数
SELECT `sex`,COUNT(`sex`)
FROM`class`
GROUP BY `sex`
顺序很重要
SELECT 去重 要查询的字段 from表名
xxx JOIN 要连接的表 ON 等值条件
WHERE 条件
GROUP BY 通过哪些字段分组
HAVING 条件和where一样,只是位置不同
ORDER BY 排序 DESC ASC
LIMIT 分页起始数据,当前页的数据数量
SELECT COUNT(1) FROM`class` -- 本质上返回所有行数 于count(*)区别不大,不会忽略null
SELECT COUNT(*) FROM`class` -- 本质上返会所有行数
SELECT COUNT(`id`) FROM `class` -- 查询固定列有内容的行数(会忽略null
SELECT SUM(`id`)FROM`class`-- 求该列的总和
SELECT AVG(`id`)FROM class -- 求该列的平均数
SELECT MAX(`id`)FROM class -- 查该列的最大值
SELECT MIN(`id`)FROM class -- 查该列的最小值
-- 把范围内的QQ变成MD5散列码
UPDATE `class` SET `QQ`=MD5(`QQ`) WHERE `id`<170788
A给B转100元钱
要么转成功要么转失败,
不能出现A转100元而B没有收到的情况
创建测试数据
CREATE DATABASE shop CHARACTER SET utf8 COLLATE utf8_general_ci
USE shop
CREATE TABLE `account`(
`id` INT (3) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(30) NOT NULL,
`money` DECIMAL(9,2) NOT NULL,
PRIMARY KEY(`id`)
)ENGINE = INNODB,DEFAULT CHARSET = utf8
INSERT INTO`account`(`name`,`money`) VALUE('A',2000.00),('B',3000.00)
模拟转账事务,一行一行执行
SET autocommit = 0; -- 关闭事务的自动提交
START TRANSACTION -- 开启一组事务
UPDATE `account` SET `money` = `money` - 300 WHERE `id` = 1 -- A给B转钱300
UPDATE `account` SET `money` = `money` + 300 WHERE `id` = 2
COMMIT; -- 提交事务,事务提交成功,就被持久化了
ROLLBACK; -- 回滚,滚到该事务提交前的状态
SET autocommit = 1; -- 恢复默认自动提交的状态
SET autocommit = 1; -- 开启自动提交,这也是数据库的默认状态
SET autocommit = 0; -- 关闭默认提交
COMMIT -- 提交,提交之后数据就持久化了
ROLLBACK -- 回滚,回到执行事务前的样子
SAVEPOINT -- 设置保存点 了解即可
SHOW INDEX FROM 表名 -- 显示所有索引
ALTER TABLE school.`class` ADD FULLTEXT INDEX `studentName`(`name`) -- 添加全文索引 索引名(列名)
创建表格
CREATE TABLE `app_user` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT '',
`eamil` varchar(50) NOT NULL,
`phone` varchar(20) DEFAULT '',
`gender` tinyint(4) unsigned DEFAULT '0',
`password` varchar(100) NOT NULL DEFAULT '',
`age` tinyint(4) DEFAULT NULL,
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
创建一百万条数据
DELIMITER $$ -- 写函数之前必须要写,标志
CREATE FUNCTION mock_data ()
RETURNS INT
BEGIN
DECLARE num INT DEFAULT 1000000;
DECLARE i INT DEFAULT 0;
WHILE i<num DO
INSERT INTO `app_user`(`name`,`eamil`,`phone`,`gender`)VALUES(CONCAT('用户',i),'19224305@qq.com','123456789',FLOOR(RAND()*2));
SET i=i+1;
END WHILE;
RETURN i;
END;
SELECT mock_data() -- 执行此函数 生成一百万条数据
测试
SELECT * FROM`app_user` WHERE `name` = '用户9999' -- 耗时0.404s
-- 创建索引 create index 索引名 on 表名(字段)
CREATE INDEX id_app_user_name ON `app_user`(`name`)
SELECT * FROM`app_user` WHERE `name` = '用户9999' -- 耗时0s 提高效率
SQL用户管理命令行操作 -- 创建名为 xiaowang 密码为 123456 的用户 CREATE USER xiaowang IDENTIFIED BY '123456' -- 设置当前账户密码为 123456 SET PASSWORD = PASSWORD('123456') -- 设置小王账户密码为123456789 SET PASSWORD FOR xiaowang = PASSWORD('123456789') -- 给xiaowang用户重命名 RENAME USER xiaowang TO dawang -- 授予用户所有的权限 库.表 但是没有赋予他能给别人授权的权限 GRANT ALL PRIVILEGES ON *.* TO xiaowang -- 查询权限 SHOW GRANTS FOR xiaowang SHOW GRANTS FOR root@localhost -- 需要加上@localhost -- 撤销权限 REVOKE ALL PRIVILEGES ON *.* FROM xiaowang -- 删除用户 DROP USER xiaowang
mysqldump -hlocalhost(本机) -u用户名 -p密码 库 表1 表2... >硬盘位置具体文件
mysqldump -hlocalhost -uroot -p123456 school class >d:\a.sql
在登陆的情况下
mysql -uroot -p123456 -- 登录
use school -- 选择库
source d:/a.sql -- 选择导入的文件,并导入
在不登陆的情况下,<为导入
mysql -u用户名 -p密码 库名<文件位置
第一范式
第二范式
第三范式
总结:第一范式的关键词是列的原子性》第二范式的关键词是不能包含部分依赖》第三范式的关键词是不能包含传递依赖。
性能和规范性的问题
创建数据库,并导入数据 CREATE DATABASE jdbcStudy CHARACTER SET utf8 COLLATE utf8_general_ci; USE jdbcStudy; CREATE TABLE users( id INT PRIMARY KEY, NAME VARCHAR(40), PASSWORD VARCHAR(40), email VARCHAR(60), birthday DATE ); INSERT INTO users(id,NAME,PASSWORD,email,birthday) VALUE(1,'zhangsan','123456','zs@sina.com','1980-12-04'), (2,'lisi','123456','ls@sina.com','1998-12-12'), (3,'wangwu','123456','ww@sina.com','1998-12-23');
import java.sql.*; public class jdbcFirst { public static void main(String[] args) throws ClassNotFoundException, SQLException { // 1.加载驱动 Class.forName("com.mysql.jdbc.Driver"); // 固定写法 // 2.用户信息和url String url = "jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8"; String username = "root"; String password = "123456"; // 3.连接成功,数据库对象,Connection代表数据库 Connection connection = DriverManager.getConnection(url,username,password); // 4.执行SQL对象,statement执行sql对象 Statement statement = connection.createStatement(); // 5.用SQL对象去执行SQL,可能存在结果,返回结果 String sql = "SELECT * FROM users"; ResultSet resultSet = statement.executeQuery(sql); while (resultSet.next()){ System.out.println("id=" + resultSet.getObject("id")); System.out.println("name=" + resultSet.getObject("name")); System.out.println("birthday=" + resultSet.getObject("birthday")); System.out.println("==="); } // 6.释放连接 resultSet.close(); statement.close(); connection.close(); } }
总结:
配置文件 db.properties
driver = com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8
username=root
password=123456
加载驱动 获取连接 释放资源 import java.io.IOException; import java.io.InputStream; import java.sql.*; import java.util.Properties; public class jdbcUtils { private static String driver = null; private static String url = null; private static String username = null; private static String password = null; static { try { InputStream in = jdbcUtils.class.getClassLoader().getResourceAsStream("db.properties"); Properties properties = new Properties(); properties.load(in); driver = properties.getProperty("driver"); url = properties.getProperty("url"); username = properties.getProperty("username"); password = properties.getProperty("password"); // 1. 驱动只用加载一次 Class.forName(driver); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); } } // 获取连接 public static Connection getConnection() throws SQLException { Connection connection = DriverManager.getConnection(url, username, password); return connection; } // 释放资源 public static void release(Connection c, Statement s, ResultSet r) throws SQLException { if (c != null) { c.close(); } if (s != null) { s.close(); } if (r != null) { r.close(); } } }
测试增添 import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class TestInsert { public static void main(String[] args) { Connection connection = null; Statement statement = null; ResultSet resultSet = null; try { // 获取数据库连接 connection = jdbcUtils.getConnection(); // 获取SQL执行对象 statement = connection.createStatement(); String sql = "INSERT INTO `users`(id,`name`,`password`,`email`,`birthday`) \n" + "VALUE(4,'xiaowang','123456','374072213','1998-12-23')"; int i = statement.executeUpdate(sql); if(i > 0){ System.out.println("插入成功"); }else { System.out.println("插入失败"); } } catch (SQLException e) { e.printStackTrace(); }finally { try { jdbcUtils.release(connection,statement,resultSet); } catch (SQLException e) { e.printStackTrace(); } } } }
测试查询 import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class TestQuery { public static void main(String[] args) { Connection connection = null; Statement statement = null; ResultSet resultSet = null; try { // 获取数据库连接 connection = jdbcUtils.getConnection(); // 获取Statemnet对象 statement = connection.createStatement(); String sql = "SELECT * FROM `users`"; resultSet = statement.executeQuery(sql); while (resultSet.next()){ System.out.println("id= " + resultSet.getObject("id")); System.out.println("name= " + resultSet.getObject("name")); } } catch (SQLException e) { e.printStackTrace(); }finally { try { jdbcUtils.release(connection,statement,resultSet); } catch (SQLException e) { e.printStackTrace(); } } } }
SQL注入测试代码 import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class SqlZhuRu { public static void main(String[] args) { //正常登录 // login("wangwu","123456"); //SQL注入 login("' or '1=1","' or '1=1"); } public static void login(String username,String password){ Connection connection = null; Statement statement = null; ResultSet resultSet = null; try { connection = jdbcUtils.getConnection(); statement = connection.createStatement(); //正常登录语句 //SELECT * FROM `users` WHERE `name` = 'wangwu' AND `password` = '123456' //SQL注入语句 // SELECT * FROM `users` WHERE `name` = '' or '1=1' and 'password' = '' or '1=1'; String sql = "SELECT * FROM `users` WHERE `name` = '" + username + "' AND `password` = '" + password + "'"; resultSet = statement.executeQuery(sql); while (resultSet.next()){ System.out.println("id=" + resultSet.getObject("id")); System.out.println("name=" + resultSet.getObject("name")); System.out.println("birthday=" + resultSet.getObject("birthday")); System.out.println("==="); } } catch (SQLException e) { e.printStackTrace(); }finally { try { jdbcUtils.release(connection,statement,resultSet); } catch (SQLException e) { e.printStackTrace(); } } } }
测试PreparmentStatement插入代码 import java.sql.Connection; import java.sql.Date; import java.sql.PreparedStatement; import java.sql.SQLException; public class TestPrepareStatement { public static void main(String[] args) { Connection connection = null; PreparedStatement preparedStatement = null; try { //获取数据库 connection = jdbcUtils.getConnection(); //写SQL语句,用?占位符 String sql = "INSERT INTO `users`(`id`,`name`,`password`,`email`,`birthday`) values(?,?,?,?,?)"; //预编译,先写好sql preparedStatement = connection.prepareStatement(sql); preparedStatement.setInt(1,4); preparedStatement.setString(2,"dawang"); preparedStatement.setString(3,"123456"); preparedStatement.setString(4,"374072213@qq.com"); preparedStatement.setDate(5,new Date(new java.util.Date().getTime()) ); int i = preparedStatement.executeUpdate(); if(i > 0){ System.out.println("插入成功!"); } } catch (SQLException e) { e.printStackTrace(); }finally { try { jdbcUtils.release(connection,preparedStatement,null); } catch (SQLException e) { e.printStackTrace(); } } } }
public class TestShiWu { public static void main(String[] args) { Connection connection = null; PreparedStatement preparedStatement = null; try { connection = jdbcUtils.getConnection(); //关闭自动提交,启动事务 connection.setAutoCommit(false); String sql = "update account set money = money - 300 where id = 1 "; preparedStatement = connection.prepareStatement(sql); preparedStatement.executeUpdate(); String sq2 = "update account set money = money + 300 where id = 2 "; preparedStatement = connection.prepareStatement(sq2); preparedStatement.executeUpdate(); connection.commit(); } catch (SQLException e) { e.printStackTrace(); try { connection.rollback(); // 失败回滚事务,不写也行,默认失败回滚 } catch (SQLException ex) { ex.printStackTrace(); } }finally { try { jdbcUtils.release(connection,preparedStatement,null); } catch (SQLException e) { e.printStackTrace(); } } } }
dbcp_properties #连接设置 driverClassName=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=false username=root password=123456 #初始化连接 initialSize=10 #最大连接数量 maxActive=50 #最大空弦连接 maxIdle=20 #最小空闲连接 minIdle=5 #超时等待 maxWait=60000 #JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:[属性名=property;] #注意:“user” 与 “password” 两个属性会被明确地传递,因此这里不需要包含他们。 connectionProperties=useUnicode=true;characterEncoding=gbk #指定由连接池所创建的连接的自动提交(auto-commit)状态。 defaultAutoCommit=true #driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。 #可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE defaultTransactionIsolation=READ_UNCOMMITTED
JdbcUtils_JDCP.class import org.apache.commons.dbcp.BasicDataSourceFactory; import javax.sql.DataSource; import java.io.IOException; import java.io.InputStream; import java.sql.*; import java.util.Properties; public class JdbcUtils_JDCP { private static DataSource dataSource = null; static { try { // 这里要会写 InputStream in = JdbcUtils_JDCP.class.getClassLoader().getResourceAsStream("dbcp.properties"); Properties properties = new Properties(); properties.load(in); //创建数据源,工厂模式-->创建对象 try { dataSource = BasicDataSourceFactory.createDataSource(properties); } catch (Exception e) { e.printStackTrace(); } } catch (IOException e) { e.printStackTrace(); } } // 获取连接 public static Connection getConnection() throws SQLException { return dataSource.getConnection(); } // 释放资源 public static void release(Connection c, Statement s, ResultSet r) throws SQLException { if (c != null) { c.close(); } if (s != null) { s.close(); } if (r != null) { r.close(); } } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。