关系型数据库java
MySQL (如下内容所有基于 mysql )mysql
Oracle面试
Sql serverredis
非关系型数据库sql
mongoDB数据库
redisapi
create database 库名[character set 码表 collate 字符校对集]
drop database 库名
show databases
alter database 库名 character set 码表(utf8) collate 字符校对集(utf8_bin);
use 库名
select database();
show create database 库名;
create table t_user( id int, name varchar(20), sal double(4,3), birthday datetime, hiredate timestamp );
查看表的结构数据库设计
desc t_user;
删除表函数
drop table t_user;
修改表url
alter table t_user add photo blob;
修改列的类型
alter table 表名 modify 列名 类型;
修改列的名称
alter table 表名 change 旧列名 新列名 数据类型;
删除某列
alter table 表名 drop 列名;
修改表名
rename table t_user to t_employee;
insert into 表名(字段1,2) values(数据...)
update 表 set ... where 条件
delete from 表 [条件] truncate
面试题:
DELETE 和 TRUNCATE 有什么区别?
相同点: 这两种都是删除表中的记录. 不一样点: 1. delete 是逐行标记删除. TRUNCATE 是将整张表包括表结构都移除,而后将表从新建立. 2. delete DML语句。 TRUNCATE DDL语句。 3. delete 删除的记录能够被恢复,TRUNCATE 不能回复。 4. delete 不释放空间,TRUNCATE 释放空间. 5. TRUNCATE 会提交事务. (还没学)
数字型
TINYINT 1字节 byte -128~127 SAMLLINT 2字节 short -32768~32767 MEDIUMINT 3字节 INT 4字节 int 32bit 2^32 BIGINT 8字节 long 64bit 2^64 ---------------------------------- int(10) 和 int(3) 的区别 括号中的数字只是客户端显示时显示几位, 不会影响存储容量 若是设置 int(10) 当填入1时 默认前面会补充9个0 最种结果就是0000000001(前提设置zeorfill)
FLOAT 单精度4字节 float DOUBLE 8字节 double DECIMAL 没有精度损失 ---------------------------------- float 默认只保存6位(除去小数点),若是超过6位,则四舍五入,因此float存储的数据是不精确的,只是近似值 DOUBLE和DECIMAL区别? DOUBLE类型在运算时会有精度损失 DECIMAL就是解决精度缺失问题 单纯想表示小数属性时,使用double 须要频繁参与运算的小数,使用
字符串类型
注意:字符串类型要使用单引号包裹
CHAR/VARCHAR(最大长度225字节) --------------------------------------- 区别: char定长字符串,varchar表示变长字符串 同时指定长度10,当存储abc char='abc varchar='abc' 结论: 开发中varchar用得最多,char 只表示固定长度的枚举中使用。
TEXT/CLOB 保存文本(字符流)->当要保存的内容超过255字节 BLOB 保存字节-开发中不用 -------------------------------------- 区别: text:只能存储字符数据 BLOB:能够存储字符和多媒体信息
日期和时间类型
date 只记录日期 time 只记录时间 year 只记录年 datetime 有记录日期 又记录时间(不传值为null) timestamp 同上(不传值,为当前时间)
语法
SELECT selection_list /*要查询的列名称*/ FROM table_list /*要查询的表名称*/ WHERE condition /*行条件*/ GROUP BY grouping_columns /*对结果分组*/ HAVING condition /*分组后的行条件*/ ORDER BY sorting_columns /*对结果排序*/ LIMIT offset_start, row_count /*结果限定*/
聚合函数
聚合函数是用来作纵向运算的函数
分组查询
当须要分组查询时须要使用GROUP BY子句.
例如查询每一个部门的工资和,这说明要使用部门来分组。
1>查询每一个部门的部门编号和每一个部门的工资和: select deptno,sum(sal) from emp group by deptno; 2>查询每一个部门的部门编号以及每一个部门的人数: select deptno,count(ename) from emp group by deptno; 3>查询每一个部门的部门编号以及每一个部门工资大于1500的人数: select deptno,count(ename) from emp where sal>1500 group by deptno ;
HAVING 子句
4>查询工资总和大于9000的部门编号以及工资和: select deptno,sum(sal) from emp group by deptno having sum(sal)>9000;
分页
LIMIT(MySQL方言) LIMIT用来限定查询结果的起始行,以及总行数。
1>查询5行记录,起始行从0开始 select * from emp limit 0,5; 2> 查询10行记录,起始行从3开始 select * from emp limit 3,10; 3>若是一页记录为5条,但愿查看第3页记录应该怎么查呢? 第一页记录起始行为0,一共查询5行; select * from emp limit 0,5; 第二页记录起始行为5,一共查询5行; select * from emp limit 5,5; 第三页记录起始行为10,一共查询5行; select * from emp limit 10,5;
多表查询的步骤
交叉链接查询(产生笛卡尔积)
查询员工表和部门表的信息 SELECT t_emp.emp_name,t_dep.dep_name FROM t_emp, t_dep 这种写法不会达到咱们的目的, 因为没有足够的链接条件会产生笛卡尔积
内链接查询
隐式内链接
select * from A,B where 条件;
显示内链接
select * from A inner join B on 条件;(inner join ... on可省略)
左外链接
左表的数据所有显示, 右表的数据当知足链接条件的时候,就显示知足条件的数据 可是若是不知足链接条件, 则显示NULL
右外链接
跟左外链接相反
自链接
只是一种技巧, 本身跟本身链接而已
子查询
当一个查询是另外一个查询的条件
联合查询
union 和 union all
select <select_list> from <table_name> <join_type> join <join_table> on <join_condition> where <where_condition> group by <group_by_list> having <having_condition> order by <order_by_condition> limit <limt_number>
from <left table> on <on_condition> <join_type> join <join_table> where <where_condition> group by <group_by_list> <sum()avg()等聚合函数> having <having_condition> select <select_list> distinct order by <order_by_condition> limit <limit_number>
第一步:加载from子句的前两个表计算笛卡尔积,生成虚拟表vt1;
第二步:筛选关联表符合on表达式的数据,保留主表,生成虚拟表vt2;
第三步:若是使用的是外链接,执行on的时候,会将主表中不符合on条件的数据也加载进来,作为外部行
第四步:若是from子句中的表数量大于2,则重复第一步到第三步,直至全部的表都加载完毕,更新vt3;
第五步:执行where表达式,筛选掉不符合条件的数据生成vt4;
第六步:执行group by子句。group by 子句执行事后,会对子句组合成惟一值而且对每一个惟一值只包含一行,生成vt5,。一旦执行group by,后面的全部步骤只能获得vt5中的列(group by的子句包含的列)和聚合函数。
第七步:执行聚合函数,生成vt6;
第八步:执行having表达式,筛选vt6中的数据。having是惟一一个在分组后的条件筛选,生成vt7;
第九步:从vt7中筛选列,生成vt8;
第十步:执行distinct,对vt8去重,生成vt9。其实执行过group by后就不必再去执行distinct,由于分组后,每组只会有一条数据,而且每条数据都不相同。
第十一步:对vt9进行排序,此处返回的不是一个虚拟表,而是一个游标,记录了数据的排序顺序,此处可使用别名;
第十二步:执行limit语句,将结果返回给客户端
on 和 where 的区别?
简单地说,当有外关联表时,on主要是针对外关联表进行筛选,主表保留,当没有关联表时,两者做用相同。
例如在左外连时,首先执行on,筛选掉外连表中不符合on表达式的数据,而where的筛选是对主表的筛选。
一对多
在开发中,关系中的一方称之为主表或者一表,关系中的多方称之为多表或者从表, 为了表示一对多的关系,通常会在多表的一方添加一个字段,字段名称自定义(建议:主表的名称_id) 字段类型通常和主表的主键的类型保持一致,咱们称这个字段为外键
注意
在多表的一方添加外键约束(不是必须的,也能够经过java程序来控制)格式
alter table 多表名称 add foreign key(外键名称) references 主表名称(主键名称)
多对多
在开发中,通常引入一个中间表,在中间表中存放另外两张表的主键.这样就能够将多对多的关系拆分两个一对多的关系 为了保证数据的有效性和完整性,在中间表上添加两个外键约束(不是必须的,也能够经过java程序来控制)
默认值约束 建表时, 在数据类型后面添加 DEFAULT '默认值'
非空约束 建表时, 在数据类型后面添加 NOT NULL
惟一约束 建表时, 在数据类型后面添加 UNIQUE
主键约束(惟一 + 非空) 建表时, 在数据类型后面添加 PRIMARY KEY
自增加约束 建表时, 在数据类型后面添加 AUTO_INCREMENT
外键约束 CONSTRAINT 外键名称 FOREIGN KEY(外键字段) REFERENCES 表名(关联表id)
第一范式: 要求表的每一个字段必须是 独立 且 不可分割 的单元
第二范式: 要求表的 除主键以外 的字段都和 主键 有依赖关系 一张表只能表达一个意思, 例如不在呢
第三范式: 在第二范式的基础上, 要求表中除主键以外的字段都与主键有直接决定的依赖关系 其余字段只能由主键决定
JDBC就是由java提供的一套访问数据库的统一api,切换库时十分方便.
url格式 大协议:自协议://ip:port/库名?参数键=参数值
url = jdbc:mysql://localhost:3306/day05?useUnicode=true&characterEncoding=utf8
url = jdbc:mysql:///day05?useUnicode=true&characterEncoding=utf8 //链接本机默认端口号
DriverManager.registerDriver(new Driver()); Connection connection = DriverManager.getConnection("jdbc:mysql:///blog", "root", "root");
Class.forName("com.mysql.jdbc.Driver"); Connection connection = DriverManager.getConnection("jdbc:mysql:///blog", "root", "root");
JDBC中几个重要的API
java.sql.DriverManager java.sql.Connection java.sql.Statement java.sql.ResultSet 这里注意区分 java.sql.Driver 和 com.mysql.jdbc.Driver [@Test](https://my.oschina.net/azibug) public void test_Conn_1() throws Exception { Driver driver = new Driver(); Properties prop = new Properties(); prop.put("user", "root"); prop.put("password", "root"); Connection connect = driver.connect("jdbc:mysql://localhost:3306/blog", prop); System.out.println(connect); }
使用Statement实现数据库的增删改查
//1.先获取Statement Statement statement = connection.createStatement(); //2.调用statement的crud方法 statement.update(sql);
注意:
使用statement时,咱们须要传入参数从而拼写很长的sql语句,这个时候咱们就引入了PreparedStatement, 咱们可使用 ? 占位符去替换那些参数,经过PreparedStatement的API传入参数
sql注入攻击
登陆功能,实现逻辑以下:
数据库中存放用户名密码, 在表单上让用户输入用户名和密码
经过以下语句判断用户名密码是否一致:
SELECT * FROM t_user WHERE NAME = 'tom' AND PASSWORD='1234';
若是如上查询返回告终果,那么说明用户名密码正确.登陆成功!
如上实现登陆的方式 很容易sql注入
用户在填写用户名时 填入以下: xxx' OR 1=1 -- SELECT * FROM t_user WHERE NAME = '' AND PASSWORD='1234';
分析sql注入的缘由?
将用户填写的用户名直接拼装到sql中.至关于变相让用户参与到了sql语句的书写
解决sql注入问题
演示使用PrepareStatement对象,解决sql注入问题
public void fun2() throws Exception{ String name ="xxx' OR 1=1 -- "; String password ="1234"; //1 得到链接 Connection conn= JDBCUtils.getConnection(); //2 拼装sql语句 String sql = "SELECT * FROM t_user WHERE NAME=? AND PASSWORD=?"; //3 得到PrepareStatement PreparedStatement ps = conn.prepareStatement(sql); //4 设置参数到ps对象中 ps.setString(1, name); ps.setString(2, password); //5 运送参数,执行sql并拿到结果 ResultSet rs = ps.executeQuery(); //5 根据结果判断是否登陆成功 if(rs.next()){ System.out.println("登陆成功!"); }else{ System.out.println("登陆失败!"); } //6关闭资源 JDBCUtils.close(conn, ps, rs); }