mysql - 入门知识总结

常见的数据库

关系型数据库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  会提交事务. (还没学)

mysql 中的数据类型

数字型

  • 整形
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 /*结果限定*/

聚合函数

聚合函数是用来作纵向运算的函数

  • MAX():计算指定列的最大值,若是指定列是字符串类型,那么使用字符串排序运算;
  • MIN():计算指定列的最小值,若是指定列是字符串类型,那么使用字符串排序运算;
  • SUM():计算指定列的数值和,若是指定列类型不是数值类型,那么计算结果为0;
  • AVG():计算指定列的平均值,若是指定列类型不是数值类型,那么计算结果为0;

分组查询

当须要分组查询时须要使用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;

多表查询

多表查询的步骤

  • 1.肯定查询那些表
  • 2.肯定查询哪些字段
  • 3.肯定链接条件

交叉链接查询(产生笛卡尔积)

查询员工表和部门表的信息
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

手写SQL顺序

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>

MySql执行顺序

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>

MySql执行顺序理解

第一步:加载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

JDBC就是由java提供的一套访问数据库的统一api,切换库时十分方便.

url格式 大协议:自协议://ip:port/库名?参数键=参数值

url = jdbc:mysql://localhost:3306/day05?useUnicode=true&characterEncoding=utf8

url = jdbc:mysql:///day05?useUnicode=true&characterEncoding=utf8 //链接本机默认端口号

  • 注册驱动的方式1:
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注入攻击

登陆功能,实现逻辑以下:

数据库中存放用户名密码, 在表单上让用户输入用户名和密码

  1. 经过以下语句判断用户名密码是否一致:

    SELECT * FROM t_user WHERE NAME = 'tom' AND PASSWORD='1234';

  2. 若是如上查询返回告终果,那么说明用户名密码正确.登陆成功!

  3. 如上实现登陆的方式 很容易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);
}
相关文章
相关标签/搜索