现在的存储方式
java程序存储数据(变量,数组,对象,集合),数据保存在内存中,属于临时存储。
文件(File)存储数据,保存在硬盘上,属于长久状态存储
缺点
没有数据类型的区分
存储数量级较小
没有访问安全限制
没有备份,恢复机制
什么是数据库
数据库是按照数据结构来组织、存储和管理数据的仓库,是一个长期存储在计算机内的有组织,可以共享,统一管理的数据集合。
网状数据库以节点形式存储和访问层次结构数据库定向有序的树状结构进行存储和访问关系结构数据库(MySql)以表格(Table存储,多表间建立关系,通过分类,合并,连接,选取等运算实现访问)非关系型数据库多数使用哈希表,表中以键值的方式实现特定的键和一个指针指向的特定数据常见的数据库管理系统:Oracle,DB2,SQl Server
进行查询操作时显示出来的是一张虚拟表,并不会改变原表的值。
语法:SELECT 列名 FROM 表名
当查询所有列时: select 所有的列名 from 表名 注意:也可以使用 * 号代替所有的列但是 星号需要转换成所有的列,效率低,可读性差,所以优先使用列名查询对列中的数据进行运算(列的数据类型应该是数值列,否则不能进行运算)
算数运算符描述+两列相加-两列相减*两列相乘/两列相除注:%是占位符不是模运算符
列的别名 在我们查询时为了使我们清楚了解查询的是什么,我们可以建立它的别名
语法: as 别名
select employee_id as '员工编码',salary as'年薪' from t_employees;查询结果去重 通常我们创建的数据中有许多的重复,如果不想让其重复出现可以添加“DISTINCT”
语法:distinct 列名
select distinct manager_id from t_employees;语法:select 列名 from 表名 ORDER BY 排序列 [排序规则](方括号可以不加)
排序规则描述ASC对前面的排序列做升序排序DESC对前面的排序列做降序排序 **单列排序** select EMPLOYEE_ID,salary from t_employees order by salary asc; select EMPLOYEE_ID,salary from t_employees order by salary desc; **多列排序** 在前方排序列中有相同的数据后,后面的排序列才能有用并按照后面的排序规则排序 select EMPLOYEE_ID,salary from t_employees order by salary desc,EMPLOYEE_ID desc;语法:select 列名 from 表名 where 条件 where 条件:在查询结果中,筛选符合条件的结果,条件为布尔表达式,只有布尔表达式的值为真才执行。
等值判断(=)
在 sql语言中等值判断是(=),Java是(==) select EMPLOYEE_ID,FIRST_NAME,salary from t_employees where salary = 11000;逻辑判断(and ,or,not)
select EMPLOYEE_ID,FIRST_NAME,salary from t_employees where salary = 11000 and COMMISSION_PCT=0.3; #查询符合两个条件的数据 select EMPLOYEE_ID,FIRST_NAME,salary from t_employees where salary = 11000 or COMMISSION_PCT=0.3; #查询满足两个条件中一个的数据 select EMPLOYEE_ID,FIRST_NAME,salary from t_employees where not salary = 11000; #查询不满足条件的数据不等值判断(>,<,>=,<=,!=,<>)
需注意的是 != 和 <> 都表示不等于的意思 select EMPLOYEE_ID,FIRST_NAME,salary from t_employees where salary != 11000; select EMPLOYEE_ID,FIRST_NAME,salary from t_employees where salary <> 11000; #!= 和 <> 都是不等于区间判断(between…and…)
区间前面的数值一定要比后面的小 select EMPLOYEE_ID,FIRST_NAME,salary from t_employees where salary between 6000 and 10000;判断是否为空值时不能使用“=”号,需要使用 IS NULL或者 IS NOT NULL
SELECT EMPLOYEE_ID,FIRST_NAME,SALARY FROM t_employees WHERE MANAGER_ID IS NOT NULL;需要注意的是枚举查询中的枚举的值只要满足其中一个就可以,相当于各个值之间有个“or”。
SELECT EMPLOYEE_ID,FIRST_NAME,SALARY FROM t_employees where DEPARTMENT_ID in(70,80,90);需注意的是模糊查询只能和LIKE关键字结合使用
SELECT EMPLOYEE_ID,FIRST_NAME,SALARY FROM t_employees WHERE FIRST_NAME LIKE 'L__'; SELECT EMPLOYEE_ID,FIRST_NAME,SALARY FROM t_employees WHERE FIRST_NAME LIKE 'L%';AS ‘别名’是因为查询出来的虚拟表的列名会变成代码块,加了别名这样可以简单并且好理解
SELECT EMPLOYEE_ID,FIRST_NAME,SALARY, CASE WHEN SALARY >10000 THEN 'A' WHEN SALARY >6000 AND SALARY <=8000 THEN 'B' WHEN SALARY >4000 AND SALARY <=6000 THEN 'C' ELSE 'D' END AS '薪资分阶' FROM t_employees;执行时间查询会生成一张虚拟表(一行一列);
时间函数描述SYSDATE()查询系统当前的时间(包括日期和时间)CURDATE()查询当前系统日期CURTIME()查询当前时间(只有时间)WEEK(DATE)查询日期是该年的第几周YEAR(DATE)查询日期中的年份HOUR(TIME)查询时间中的小时部分MINUTE(TIME)查询时间中的分钟部分DATEDIFF(DATE1,DATE2)查询两个日期之间的天数间隔ADDDATE(DATE,N)在日期的基础上加上天数需注意DATEDIFF 中前面的日期要小于后面的日期
#当前系统时间 SELECT SYSDATE(); #当前系统日期 SELECT CURDATE(); #当前系统时间 SELECT CURTIME(); #获取当前年份的第几周 SELECT WEEK(SYSDATE()); #获取当前指定日期的年份 SELECT YEAR('2020-4-1'); #获取小时值 SELECT HOUR(CURTIME()); #获取分钟值 SELECT MINUTE(CURTIME()); #指定日期相隔的天数 SELECT DATEDIFF('2020-7-9','2020-3-8'); #指定日期再加上天数 SELECT ADDDATE('2020-3-9',6);需注意的是MySQL中字符串下标位置是从1开始,而不是java中从0开始 ,字符串连接也可以将表中各个列中的字符串连接
#多个字符串拼接 SELECT CONCAT('MY','S','QL'); SELECT CONCAT(FIRST_NAME,LAST_NAME) FROM t_employees;#MYSQL #字符串替换 SELECT INSERT('这是一个数据库',3,2,'MYSQL');#这是一个MYSQL数据库 #字符串转小写 SELECT LOWER('MYSQL');#mysql #字符串转大写 SELECT UPPER('mysql');#MYSQL #字符串截取 SELECT SUBSTRING('JAVAMYSQLPRACLE',5,5);#MYSQL聚合函数是对一列的多条数据进行运算,返回统计后的一行结果。
聚合函数描述SUM()求单列中所有行数据的总和AVG()求单列所有行数据平均MAX()求单列所有行最大值MIN()求单列所有行最小值COUNT()求对某列名中的属性在该列中出现的行数之和需注意聚合函数对值为NULL 的行数是不会计算在内的
SELECT SUM(SALARY) FROM t_employees; SELECT AVG(SALARY) FROM t_employees; SELECT MAX(SALARY) FROM t_employees; SELECT MIN(SALARY) FROM t_employees; SELECT COUNT(EMPLOYEE_ID)FROM t_employees;分组是以某列中的数据分组
查询单个列的分组依据
SELECT DEPARTMENT_ID,COUNT(EMPLOYEE_ID) FROM t_employees GROUP BY DEPARTMENT_ID;查询多个列的分组依据
后面的列是要前面的列为依据再进行分组,即先对前面的列进行分组,再对后面的列分组
SELECT DEPARTMENT_ID,JOB_ID,COUNT(EMPLOYEE_ID) FROM t_employees GROUP BY DEPARTMENT_ID,JOB_ID;常见问题
SELECT DEPARTMENT_ID,COUNT(*),FIRST_NAME FROM t_employees GROUP BY DEPARTMENT_ID;在该代码中只显示出来了DEPARTMENT_ID,FIRST_NAME虽然显出出来了结果但并不完整。所以分组查询只是显示出来分组依据的结果或者聚合函数列,不会出现其它的列
分组过滤查询
SELECT 列名 FROM 表名 WHERE 条件 GROUP BY 查询依据 HAVING 过滤规则HAVING 过滤规则是对分组后的数据进行过滤
SELECT DEPARTMENT_ID ,MAX(SALARY) FROM t_employees GROUP BY DEPARTMENT_ID HAVING DEPARTMENT_ID IN(60,70,90);最后显示的是60,70,90三个部门编号和对应的最高工资
与前面字符串不同的是行数下标是从0开始的,0表示第一行,第二个参数是你想要查询的行数
SELECT * FROM t_employees LIMIT 0,5;#表示从第1行开始查询了5行 SELECT * FROM t_employees LIMIT 5,5;#表示从第六行开始查询了5行 SELECT * FROM t_employees LIMIT 10,5;#表示从第11行开始查询了5行SQL语句编写顺序
SELECT 列名 FROM 表名 WHERE 条件 GROUP BY 查询依据 HAVING 过滤规则 ORDER BY 排序列(asc|desc)LIMIT 起始行,总行数SQL语句执行顺序
1.FROM : 指定数据来源表 2.WHERE:对查询数据做第一次过滤 3.GROUP BY:分组 4.HAVING:对分组后的数据做第二次过滤 5.SELECT:查询各字段的值 6.ORDER BY:排序 7.LIMIT:限定查询结果单行单列
SELECT 列名 FROM 表名 WHERE 子查询结果 将子查询结果单行单列作为外部查询的条件,再做第二次查询子查询得到的一行一列的结果作为外部查询等值或者不等值的判断条件 SELECT SALARY FROM t_employees WHERE FIRST_NAME = 'bruce';#结果出来是6000 #查询工资大于6000 SELECT * FROM t_employees WHERE SALARY > 6000; #整合 SELECT * FROM t_employees WHERE SALARY >( SELECT SALARY FROM t_employees WHERE FIRST_NAME = 'bruce');子查询(枚举查询,多行单列)
SELECT 列名 FROM 表名 WHERE 列名 IN (子查询结果)将子查询的结果多行单列作为外部查询的枚举查询条件,做第二次查询
#子查询(单列多行) SELECT * FROM t_employees WHERE LAST_NAME='KING';#得到的部门编号有80,90 SELECT * FROM t_employees WHERE DEPARTMENT_ID IN(80,90);#查询部门编号为80,90的信息 #整合 SELECT * FROM t_employees WHERE DEPARTMENT_ID IN(SELECT DEPARTMENT_ID FROM t_employees WHERE LAST_NAME='KING');#因为需要得到的值是编号所以不能再用星号子查询(ALL,ANY关键字使用,多行单列)
ALL 关键字表示满足子查询结果中的所有条件,ANY关键字表示满足子查询结果的部分条件也可以理解位满足其中一个条件就可以。
#查询工资高于60部门的员工信息 SELECT SALARY FROM t_employees WHERE DEPARTMENT_ID = '60'; #整合 SELECT * FROM t_employees WHERE SALARY >ALL (SELECT SALARY FROM t_employees WHERE DEPARTMENT_ID = '60');#即大于部门60中最高工资 SELECT * FROM t_employees WHERE SALARY >ANY (SELECT SALARY FROM t_employees WHERE DEPARTMENT_ID = '60');#即大于部门60中最低工资即可子查询(多行多列即一张表)
SELECT 列名 FROM (子查询结果集)WHERE 条件;子查询结果是一张表时需要在其后面给该表定义个名字(AS 表名)
#子查询(多行多列即一张表) #查询工资前五位的工资,编号和名字先做一张工资降序表再从里面找出前五个 SELECT EMPLOYEE_ID,SALARY,FIRST_NAME FROM t_employees ORDER BY SALARY DESC; SELECT * FROM (SELECT EMPLOYEE_ID,SALARY,FIRST_NAME FROM t_employees ORDER BY SALARY DESC)AS temp LIMIT 0,5; 将子查询“多行多列”的结果作为外部查询的一张表,做第二次查询注意:子查询是临时表时,需要为其赋一个临时表名UNION 合并两表会去除重复的记录,合并结果的两张表列数必须相同,数据类型可以不同
SELECT * FROM t_departments UNION SELECT * FROM t_jobsUNION ALL合并两表会不去除重复的记录,合并结果的两张表列数必须相同,数据类型可以不同
SELECT * FROM t1 UNION ALL SELECT * FROM t2 ;内连接查询(INNER JOIN ON) 结果是将两张表的数据合并,但是要ON后面的属性对应
#通用,查询所有员工的信息(不包括没有部门的) SELECT * FROM t_employees INNER JOIN t_jobs ON t_employees.JOB_ID = t_jobs.JOB_ID; #SQL标准 SELECT * FROM t_employees,t_jobs WHERE t_employees.JOB_ID=t_jobs.JOB_ID;左外连接(LEFT JOIN ON)
以左表为主表向右匹配,匹配到,返回值,匹配不到,返回NULL
#左表连接 SELECT EMPLOYEE_ID,salary,DEPARTMENT_NAME FROM t_employees LEFT JOIN t_departments ON t_employees.DEPARTMENT_ID=t_departments.DEPARTMENT_ID;右外连接(RIGHT JOIN ON)
以右表为主表向左匹配,匹配到,返回值,匹配不到,返回NULL
SELECT EMPLOYEE_ID,salary,DEPARTMENT_NAME FROM t_employees RIGHT JOIN t_departments ON t_employees.DEPARTMENT_ID=t_departments.DEPARTMENT_ID;表名后的列名要和VALUES后面的值一一对应(个数,顺序,数据类型)
要注意增加where条件,否则就会更新整张表
UPDATE t_employees SET SALARY='25000' WHERE EMPLOYEE_ID='100';同时也要注意where条件,否则会删除整张表,一般删除条件所在的元组;
DELETE FROM t_employees WHERE EMPLOYEE_ID='135';TRUNCAT 与 DELETE 的区别是DELETE 删除了表的数据,但是表的结构并为改变,而TRUNCAT 是将整张表销毁再按照该表的结构重新创建一个表
TRUNCATE TABLE t1;数值类型 日期类型 字符串类型 简单来讲,CHAR大小如果定义为20只输入一个字母a,系统会自动填满剩下的19大小空间,最后占用的还是20大小的空间,而VARCHAR你如果定义大小20,只输入一个字母a,它会自动缩减大小最后占用的空间只为1个,即a所占用的。
修改表中的列(MODIFY)
ALTER TABLE `SUBJECT` MODIFY subjectNAME VARCHAR (10); #修改了表中的数据类型删除表中的列(DROP)
#删除表中的列 ALTER TABLE `SUBJECT` DROP gradeID;修改列名(CHANGE)
ALTER TABLE `SUBJECT` CHANGE subjectHOURS classHOURS INT;修改表名(RENAME)
ALTER TABLE `SUBJECT` RENAME `SUB`;删除表
DROP TABLE 表名; DROP TABLE `SUBJECT`;主键约束
列名 数据类型 PRIMARY KEY ,表示表中的一行数据,此列的数据不能重复,且不能为NULL主键一般是编号,ID,因为主码表示的列名要能够判别数据的唯一。
唯一约束
UNIQUE ,表示表中的一行数据,此列不能重复,可以为NULL自动增长列
AUTO_INCREMENT,自动增长,给主键数值列添加自动增长,从1开始,每次加1,不能单独使用,每次配合由于自动加1,所以主键的内容需要是整型,且插入内容不用写主键编号,它会自动排好
CREATE TABLE `SUBJECT`( subjectID INT PRIMARY KEY AUTO_INCREMENT,#Z主码 subjectNAME VARCHAR(20) UNIQUE, subjectHOURS INT )CHARSET=utf8;#指定该表创建数据的字符集非空约束
NOT NULL,非空,此列必须有值默认值约束
DEFAULT 为列赋予默认值,当新增数据不指定值时,书写default,以指定的默认值填充 create table `subject`( subjectid int primary key AUTO_INCREMENT, subjectName varchar(20)unique not null, subjectHours int DEFAULT 10 )charset=utf8; insert into `subject`(subjectName,subjectHours)values('c++',default);当你插入数据不知道取何值时,在插入公式中加入default,插入的数值为默认值即为10
FOREIGN KEY 引用外部表的某个列的值时,新增数据时结束此列的值必须是被引用表中存在的值。
create table speciality( id int primary key, specialityName varchar(20)not null )charset=utf8; insert into speciality(id,specialityName)values(1,'sql'); insert into speciality(id,specialityName)values(2,'my'); select * from speciality; create table `subject`( subjectid int primary key AUTO_INCREMENT, subjectName varchar(20)unique not null, subjectHours int DEFAULT 10, specialityid int not null, constraint fk_subject_specialityid foreign key (specialityid)references speciality(id) )charset=utf8;当两张表有关系时,需要先删除引用表,才能删除被引用表;
模拟转账
#转账模拟 start transaction; create table change_money( id int primary key auto_increment, money int not null )charset=utf8; insert into change_money(money)values(9000); insert into change_money(money)values(8000); select * from change_money; update change_money set money=money-1000 where id =1; update change_money set money=money-1000 where id =2; #执行成功 commit; #执行失败 rollback;如果在该操作时账户1减钱成功,而账户2加钱操作有问题,则结果会显示账户1少了1000,而账户2并未加钱1000;
每条SQL语句都是一个独立的操作,一个操作执行完成会对数据库产生永久性的影响。
事务概念
事务是一个原子操作,是一个最小执行单位。可以由一个或者多个SQL语句组成 。在同一个事务中所有的 SQL语句都执行成功,则事务成功, 有一个SQL语句失败,则整个事务失败。事务的边界
* 开始:连接到数据库,执行一条DML语句。上一个事务结束后, 又输入 一条DML语句,则是事务的开始 * 结束: 1.提交 a.显示提交:commit; b.隐式提交:一条创建,删除的语句,正常退出(客户端退出连接) 2.回滚 a.显示回滚:rollback; b.隐式回滚:非正常退出(断电...),执行了创建,删除语句,但是失败 了,会为无效的语句执行回滚;在上述情况中 如果在该操作时账户1减钱成功,而账户2加钱操作有问题,执行回滚语句,则账户1的账户会回到减钱成功前的状态,账户2 保持不变。
注意:执行事务后(start transaction),执行的语句属于当前事务,成功再执行commit,失败执行rollback;
密码必须是字符串
创建的视图出来的表是会被保存的,原表数据改变视图也会改变。可以通过视图查询直接查询之前的数据。
视图的修改与删除 修改
create or replace view 视图名 as 查询语句 alter view 视图名 as 查询语句删除
drop view 视图名