数据库内容整理

数据库内容整理

目录

数据库内容整理

一.概述

二.使用

三.数据库结构

四.SQL语言

五.数据库的常见操作

六.对表的操作

七.对数据的操作

八.数据库的使用细节

九.字段约束

十.基础函数

十一.条件查询

十二.聚合函数

十三.事物(transaction)

十四.索引(index)

十五.表关联(association)

十六.JDBC


一.概述

数据库作用就是用来存储数据和管理数据,本质上就是需要安装MySQL软件. 分类: 关系型数据库MySQL 和 非关系型数据库Redis ,主要观察数据之间的关系

二.使用

  1. 小黑窗口/DOS窗口:

    • 从开始菜单里找MySQL/Mariadb,输入密码

    • win+r 然后输入cmd

      • 发起MySQL的命令 -u是指定用户名(root) -p是指定密码(自定义的)

      • 命令:mysql -uroot -proot

  2. 图形化的工具:sqlyog

三.数据库结构

数据库 -> 表(行和列) -> 数据

四.SQL语言

  1. 结构化查询语言,用来操作数据库的语言,是一种标准.

  2. 分类

    • DML(Data Manipulation Language)是数据操纵语言

    • DDL(Data Definition Language)是指数据定义语言

    • DCL(Data Control Language)是指数据控制语言

    • DQL(Data Query Language)是指数据查询语言

五.数据库的常见操作

  1. 建库--create database 库名 default character set utf8;

  2. 删库--drop database 库名;

  3. 查看所有数据库--show databases;

  4. 使用数据库--use 库名;

六.对表的操作

  1. 创建表:create table 表名(字段名称 字段类型(字段最大长度),字段名称 字段类型(字段最大长度));

  2. 修改表--添加列:alter table 表名 add column 列名 列的类型(7,2);

  3. 删除表:drop table 表名;

  4. 查看所有表:show tables;

  5. 查看(描述)表结构/设计表:desc 表名;

七.对数据的操作

  1. 查询表中的所有记录:select * from 表名;

  2. 插入记录:insert into 表名 values(表里有几个字段,依次按类型赋值);

  3. 修改记录:update 表名 set 表里字段名=新值 where id=1;

  4. 删除记录:delete from 表名 where id=2;

  5. 插入数据/记录注意:

    1. 需要设置几个值?要看表里有几个字段

    2. 值的顺序要和字段的顺序保持一致

    3. 如果字段是字符串类型,设置值时必须要有" " ’ '的标记

    4. 如果出现中文乱码,可以使用set names gbk;设置

八.数据库的使用细节

  • 命名规范

    1. 字段必须以字母开头,不要以数字开头,尽量不要使用拼音

    2. 长度不能超过30个字符(不同数据库,不同版本会有不同)

    3. 不能使用SQL保留字:select / from / update / delete / insert into

    4. MySQL数据库不区分大小写,多个单词用下划线分开

  • 数据类型

    1. 整型:int

    2. 小数:double(不精确) / numeric(a,b) / decimal(a,b)–a是数字的位数b是小数位数

    3. 时间: date(年月日) time(时分秒) datetime(年月日时分秒) timestamp(时间戳,指从1970年1月1日到指定日期的毫秒数)

    4. 字符串: char / varchar

      • char和varchar有什么区别?

        1. char:长度固定,不足使用空格补充,最多容纳2000个字符,查询速度极快但浪费空间

        2. varchar:可变长度,最多容纳4000个字符,查询稍慢,但节省空间

      • 特殊场景: 数据长度如果就是固定的,优先选char,因为查的快

    5. 图片: 如果想存入数据库,只会存文件的磁盘路径D:/abc/1.jpg,不是存文件本身

九.字段约束

  • 概念:当表里的字段值想要添加约束条件时,就可以使用各种字段约束

  • 字段约束的功能:哪个字段加了约束,就对哪个字段的值产生约束力

  • 常见的有: 主键约束 非空约束 唯一约束 外键约束 默认约束 检查约束

  1. 主键约束: primary key auto_increment(主键自增)

    • 给表里的某个字段设计约束,特点是字段值必须唯一且非空

    • 自增策略:auto_increment把主键值交给数据库维护,值会自增

  2. 非空约束

    • 非空:not null,给字段加了非空约束,字段值不能为空

  3. 唯一约束

    • 唯一:unique,给字段加了唯一约束,字段值不能相同

  4. 外键约束

    • foreign:通过特殊字段(外键),描述了两张表间的关系

    • foreign key(当前表的主键) references 对方表名(对方表的主键)

    • 外键约束效果:

      1. 子表的id必须取自主表的id

      2. 想删除主表的数据必须先删掉子表相关的

  5. 默认约束

    • default: 给字段设置默认值

    • 字段名 字段类型(长度) DEFAULT '默认的值'

  6. 检查约束

    • 检查约束check:不合法时会报错

    • CHECK(age>0 AND age<18)

十.基础函数

  1. lower --数据转小写

    • select lower(列名/字段名) from 表名

  2. upper--数据转大写

    • select upper(列名/字段名) from 表名

  3. length--数据的长度(一个字母一个字符,一个汉字三个字符)

    • select length(列名/字段名) from 表名

  4. substr--截取[从1开始,长度为3]

    • substr(1,2,3):1是字段名,2是从哪个字符开始,3是截取长度

  5. concat--拼接数据

    • select 列名/字段名,concat(列名/字段名,'123') from 表名

    • concat(1,2,3)拼接字符串-1是字段名2和3都是要拼的内容

  6. replace--把a字符替换成666

    • select 列名/字段名,replace(列名/字段名,'a','666') from 表名

    • replace(1,2,3)替换:1是字段名,是要把2换成3

  7. ifnull-- #判断,如果comm是null,用10替换

    • select ifnull(comm,10) comm from 表名2

  8. round & ceil & floor

    • round四舍五入,ceil向上取整,floor向下取整

  9. 日期函数 now当前时间

    • year年 month月 day日 hour时 minute分 second秒

    • select now()现在的时间

    • select year(now()),month(now()),day(now())

  10. 转义符号\

    • select 'xi'an'

    • select "xi\'an"

十一.条件查询

  1. where条件

    • 查询列名/字段名=1的部门信息

      • select * from 表名 where 列名/字段名=1

    • 多个条件可以用and 或者 or连接

    • 查询sql时尽量避免使用or,他会导致结果集过于庞大,查询过慢

    • 查询编号是2的或者编号是3的 部门信息

      • select * from 表名 where 列名/字段名=2 OR 列名/字段名=3

      • select * from 表名 where 列名/字段名 IN(2,3)#同上等效

  2. like模糊查询

    • %通配符,通配了0~n个字符,_通配符,通配了1个字符

    • 查名称里包含o的部门信息

      • select * from 表名 where 列名/字段名 like '%o%' #低效

      • select * from 表名 where 列名/字段名 like 'o%' #以o开始,高效

      • select * from 表名 where 列名/字段名 like '%o' #以o结束

      • select * from 表名 where 列名/字段名 like 'l__' #了解

  3. null操作空数据

    • select * from 表名 where 列名/字段名 is null;--查询结果是null的

  4. between and 区间范围,是包含的关系

    • select * from 表名 where 列名/字段名 between 3000 and 10000

  5. limit 实现分页 展示记录

    • select * from 表名 limit 2,2--从第三条开始,展示2条记录;

  6. order by 排序--默认为升序(ASC可以省略不写)

    • select * from 表名 order by 列名/字段名 desc #降序;

    • 按字母排序:按照字典顺序. 数字:按照数值本身大小. 汉字:按照汉字所对应的utf-8编码表数字大小.

  7. where

    • select*from 表名 where year(列名/字段名) < 2017

  8. as关键字 给列设置别名

    • select *,year(now())-year(列名/字段名) AS 年份 from 表名;

十二.聚合函数

  1. 概述

    • 把一列的值聚合在一起,再做分析

    • 聚合函数:max()最大,min()最小,avg()平均,sum()求和, count()统计个数

    • select min(列名/字段名) from 表名

    • select count(1) from 表名;

  2. 分组(当查询时出现聚合列与非聚合列时,必须按照非聚合列分组)

    • 概念:把查询结果进行分组,统计一组数据中的最大值,最小值...使用group by

    • select max(sal) 最高薪,deptno 部门 from emp group by deptno;查每个部门的最高薪

    • 完成分组后的过滤使用having(其效果和where一样)(having只能出现在group by之后)

      select count(1) 总人数,deptno 部门 from emp group by deptno having count(1)>1

十三.事物(transaction)

  1. 什么是事物?

    • 数据库事物是指作为单个逻辑工作单元执行的一系列操作,要么完全执行,要么完全的不执行.

    • 用来保证多个操作(增删改) 要么全成功,要么全失败

  2. 事物的4个特性(ACID)

    • 原子性:多个操作是绑定在一起的,要么全成功,要么全失败

    • 一致性:在多个系统中保证数据是一致的

    • 隔离性:数据库允许高并发,在保证性能的同时,隔离用户的操作(底层加了同步锁)

    • 持久性:对数据的操作是都有持久影响的

  3. 事物的隔离级别

    • 读未提交:效率高,安全性差,可能发生并发数据问题

    • 读已提交:牺牲了效率,提高了安全性--Oracle数据的默认隔离级别

    • 可重复读:牺牲了效率,进一步提高了安全性. MySQL默认隔离级别

    • 串行化:效率最低,安全性最高,不能并发(表级锁),读写都加锁

  • 开启事物:start transaction

  • 结束事物:commit(提交事务,提交后才能持久性影响数据库) 或 rollback(回滚事物,回滚到事物起点,相当于撤销之前所有操作)

  • MySQL数据库默认管理事物,会为每条SQL提供事物

十四.索引(index)

  1. 概念:

    索引--是一种排好序的快速查找的数据结构,事先对数据进行了排序,大大提高了查询效率

  2. 索引的优缺点

    • 优点:

      • 索引事先对数据库进行了排序,大大提高了查询效率

      • 索引是数据库优化

      • 表的主键会默认自动创建唯一索引

      • 每个字段都可以被索引

      • 大量降低数据库的IO磁盘读写成本,极大提高了检索速度

    • 缺点:

      • 索引本身也是一张表,所以索引列也要占用空间,不适合大量添加

      • 索引表中的内容,在业务表中都有,数据重复,空间二次浪费

      • 对数据的增删改的操作需要更新索引表的信息,如果数据量巨大,更新效率就很慢

      • 随着业务的不断变化,之前的索引可能不满足需求,需要消耗时间去更新索引

  3. 索引的分类

    • 单值索引:一个索引包含一个列

    • 唯一索引:也是一个索引包含一个列,但列的值唯一(主键会自动创建)

    • 复合索引:一个索引同时包含多个列

  4. 索引的使用

    • 查询表中的索引:show index from 表名

    • 创建单值索引(给常用来作为查询条件的字段加):

      create index 索引名 on 表名(字段名)

    • 观察SQL的性能/执行计划如何优化?

      在该条SQL语句前面使用explain关键字

    • 创建唯一索引(索引列的值不能重复):

      create unique index 索引名 on 表名(字段名)

    • 创建复合索引

      create index 索引名 on 表名(字段1,字段2)

    • 使用符合索引(最左特性(按照符合索引最左边字段名查询),否则复合索引失效)

      explain select * from 表名 where 列名='值'

    • 删除索引

      alter table 表名 drop index 索引名

十五.表关联(association)

  1. 概念

    表关联代表了表与表之间的关系

  2. 表的关系分为4种:

    • 一对一 one to one:员工与员工编号

    • 一对多 one to many:部门和员工

    • 多对一 many to one:员工和部门

    • 多对多 many to many:多个老师和多个学生

  3. 多表联查(产生了大量冗余数据)

    • 概念:多表查询是指基于两个和两个以上的表的查询.

    • 笛卡尔积 : 当两张表进行连接查询,没有任何条件限制的时候,最终查询结果条数是两张表条数的乘积,这种现象被称为笛卡尔积现象.(比如有表1(A,B,C,D)和表2(a,b,c,d)两张表,查询时使用select * from 表1,表2;查询出来的结果是Aa,Ab,Ac,Ad,Ba,Bb,Bc,Bd,Ca,Cb,Cc,Cd,Da,Db,Dc,Dd相当于查询出了大量重复的冗余数据)

      • 在多表联查中,笛卡尔积查询指把多张表用逗号隔开,最终实现两张表的所有数据,产生大量冗余数据

      • 执行顺序:先定表from,然后where过滤,接着and再过滤,最后select查询,所以效率极低

      • 查询所有内容:

      select * from 表名1,表名2 where 两张表的关系(例如:a.id=b.id)

      上面这种查询两个表的方式称为:笛卡尔积

      • 查询单个内容(例如:查询部门名称叫a的员工姓名):

      select emp.ename from dept,emp where dept.deptno=emp.deptno and dept.dname='a'

    • 连接查询(使用join连接表名)(效率比笛卡尔积高,由底层顺序决定)

      • 执行顺序:先from定左表,然后on确定关系,接着join去右表查,然后where过滤条件,最后select查询,连接查询相对高效

      • 优化原则:(由于连接查询先定左表,左表查询全部内容,右表只查询满足条件的.)将数据少的或者数据简单的作为左表,小表驱动大表

      • 查询所有内容:

      select * from 表1 join 表2 on 两张表的关系(例如:a.id=b.id)

      • 查询单个内容(例如:查询部门名称叫a的员工姓名):

      select emp.ename from dept join emp on dept.deptno=emp.deptno where dept.dname='a'

      三种连接查询:

      内连接 inner join :取两个表的交集数据(连接查询默认使用)

      左外连接 left join :左表的所有和右表满足条件的,不满足是null

      右外连接 right join :右表的所有和左表满足条件的,不满足是null

    • 子查询(查询效率较低)

      • 概念:嵌套在其他查询语句中的查询语句,也叫嵌套查询.把上一次的查询结果,当做下次查询的条件.

      • 查询单个内容(例如:查询部门名称叫a的员工姓名):

        select ename from emp where deptno=(select deptno from dept where dname='a')

      • 查询多个结果使用in

  4. SQL的执行顺序

    1. from 选择表

    2. on 连接条件

    3. join 连接

    4. where 条件过滤

    5. group by 分组

    6. agg_func(column or expression)聚合

    7. having 分组过滤

    8. select (9) distinct column 选择字段/去重

    9. order by 排序

    10. limit count offset count 分页

  5. SQL优化

    1. 使用字段名称代替*(节省资源,select * 进行查询时,很可能不会用到索引,造成全盘扫描)

    2. where里: 尽量用and不用or , 尽量用=不用!= <> , 条件越精确越好 ,(使用or可能会使索引失效,导致全盘扫描)

    3. 用varchar代替char

      • varchar按数据内容实际长度存储,存储空间小,可以节省存储空间

      • char按声明大小存储,不足补空格

      • 其次对于查询来说,在一个相对较小的字段内搜索,效率更高

    4. 字段值尽量用数字代替字符串 , 用默认值代替null

    5. 给常用来作为查询条件的字段设计索引,表里的索引不要超过5个

    6. 观察SQL性能,使用explain关键字,本质上就是看有没有用到索引

    7. 模糊查询,where name like'张%',是高效写法,甚至可以让索引生效

    8. 批量处理: 避免返回大量数据,批量查询,批量的删,最好使用分页

  6. 视图VIEW

    1. 概念:视图是基于SQL语句的结果集的可视化的表(相当于是个缓存)

    2. 创建视图:create view 视图名 as SQL语句;

    3. 使用视图:select * from 视图名;

    4. 视图的优缺点:

      优点:提高了SQL的复用率

      缺点:占内存且无法被优化

十六.JDBC

  1. 概念:全称是java database connectivity,专门用来通过Java程序操作数据库,返回结果.JDBC还是一套标准,支持对各种数据库产品的操作.

  2. 使用步骤

    1. 创建工程,导入MySQL提供的jar包,选中jar包右键Add as Library

    2. 通过Java连接数据库,需要指定连接数据库的参数:用户名,密码,端口号,ip地址,指定库名.

    3. 发起SQL语句并执行

    4. 处理结果集

  3. 基础JDBC代码

    package cn.tedu.test;
    ​
    import java.sql.*;
    ​
    public class JDBC {
        public static void main(String[] args)
                throws
                ClassNotFoundException, SQLException {
            //1.注册驱动
            Class.forName("com.mysql.jdbc.Driver");//通过反射获取到对象
            //2.获取数据库的连接(用户名,密码,端口号,ip地址,指定库名)
     // 使用数据传输协议(jdbc 连接 数据库) ip地址(   端口号  数据库名称)
            String url="jdbc:mysql://localhost:3306/cgb2107";
            //驱动管理器
            Connection c = DriverManager.getConnection(url, "root", "root");
            //3.获取传输器
            Statement s = c.createStatement();
            //4.利用传输器执行SQL,返回结果集
            ResultSet r = s.executeQuery("select * from dept");//执行查询语句
            //5.处理结果
            while (r.next()){//next()判断有数据吗,有就返回true,没有循环结束
                //解析数据,获取每个字段的值
                /*
                int a = r.getInt(1);//参数可以是字段名,或者字段参数
                System.out.println(a);
                String b = r.getString(2);
                System.out.println(b);
                String loc = r.getString(3);
                System.out.println(loc);
                */
                for (int i = 1; i < 4; i++) {
    ​
                    Object o = r.getObject(i);
                    System.out.println(o);
                }
                
            }
            //6.释放资源
            r.close();//结果集
            s.close();//传输器
            c.close();//连接
        }
    }
  4. JDBC流程优化(利用JDBC模拟用户登录,并解决SQL攻击)

    package cn.tedu.test;
    import java.sql.*;
    import java.util.Scanner;
    ​
    public class JDBCTest4 {
        public static void main(String[] args) {
    ​
            //method1();
            method2();
        }
    ​
        /*创建一个方法,封装 创建驱动 获取数据库连接 两个步骤,方便调用
        * 设置为静态的,是为了方便调用,节省内存,只加载一次且被共享,而且调用时可以直接调用不需要创建对象去调用
        * (静态资源是共享的是唯一的是只加载一次的,当类被加载时就加载,类消失他才消失)
        * 封装成方法是高内聚的思想,提高代码的复用性
         */
        public static Connection getConnection() throws Exception {
            //1.创建驱动
            Class.forName("com.mysql.jdbc.Driver");
            //2.获取数据库连接
            //                                                  防止中文乱码              设置时区
            String url ="jdbc:mysql://localhost:3306/cgb2107?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false";
            Connection c = DriverManager.getConnection(url, "root", "root");
            return c;//返回给调用者
        }
    ​
        /**
         * 模拟登陆
         * SQL攻击/注入:当SQL语句中出现了#时,会把后面的SQL语句注释,改变了SQL语义
         */
        public static void method1(){
            try {
                //调用上面封装的方法并处理方法返回值
                Connection c = getConnection();
                //3.获取传输器
                Statement s = c.createStatement();
                //传入动态的账户密码
                //当用户输入特殊的名字时jack'#,
                String n=new Scanner(System.in).nextLine();
                String p=new Scanner(System.in).nextLine();
                //4.利用传输器执行SQL,返回结果集
                String sql="select * from user where name='"+n+"' and password='"+p+"'";
                ResultSet r = s.executeQuery(sql);
                //5.判断是否查到信息
                if (r.next()){
                    System.out.println("恭喜您,登陆成功");
                }else {
                    System.out.println("登录失败");
                }
                //6.释放资源
                r.close();
                s.close();
                c.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    ​
        private static void method2() {
            //为了能让finally使用变量
            Connection c=null;
            PreparedStatement s =null;
            ResultSet r =null;
            try {
                //调用上面封装的方法并处理方法返回值
                c = getConnection();
                //3.准备SQL
                System.out.println("请输入账号");
                String n=new Scanner(System.in).nextLine();
                System.out.println("请输入密码");
                String p=new Scanner(System.in).nextLine();
               // String sql="select * from user where name='"+n+"' and password='"+p+"'";
                String sql="select * from user where name=? and password=?";
               //4.获取 新的传输器
                s = c.prepareStatement(sql);
                //给SQL设置参数
                s.setString(1, n);
                s.setString(2, p);
                r = s.executeQuery();
                //5.判断是否查到信息
                if (r.next()){
                    System.out.println("恭喜您,登陆成功");
                }else {
                    System.out.println("登录失败");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                //6.释放资源
                close(c, r, s);//调用封装的方法 ,释放资源
            }
        }
    ​
        //封装了方法,用来关闭资源
        public static void close(Connection c,ResultSet r,PreparedStatement s){
            if (c!=null){//为了防止空指针异常
                try {
                    r.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if (s!=null){//为了防止空指针异常
                try {
                    s.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if (c!=null){//为了防止空指针异常
                try {
                    c.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }
    ​
    }
    ​
    ​

  1. 什么叫SQL攻击?如何解决?

    • 什么叫SQL攻击?

      出现了特殊的符号,比如#号,改变了SQL的语义,本质上是因为使用Statement(旧的传输器,SQL中出现了#号,改变了语义,甚至注释掉了后面所有的条件).

    • 解决方案:

      利用全新的传输器PreparedStatement,把SQL骨架和SQL参数分开执行,遇到#号时,只是把它当成普通文本而不是注释符号了.优点:省去了拼接SQL语句的麻烦,防止了SQL攻击,更加高效.

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值