• MySQL数据库:SQL语句基础、库操作、表操作、数据类型、约束条件、表之间的关系


    数据库相关概念:

      1. 数据库服务器:运行数据库管理软件的计算机

      2. 数据库管理软件:MySQL、Oracle、db2、slqserver

      3. 库:文件夹,用来组织文件/表

      4. 表:文件(类似于excel),用来存放多行内容/多条记录

      5. 记录:事物一系列典型的特征

      6. 数据:描述事物特征的符号

    MySQL数据库就是一个套接字软件,用来管理其他机器上的数据文件

    MySQL介绍:

    MySQL是一个关系型数据库管理系统;就是一个基于socket编写的C/S架构的软件

    客户端软件

      mysql自带:如mysql命令,mysqldump命令等

      python模块:如pymysql

    数据库管理软件分类:

    分两大类:

      关系型:如 sqllite,db2,oracle,access,sql server,mysql,注意:sql语句通用

      非关系型:mongodb,redis,memcache

    可以简单的理解为:

      关系型数据库需要有表结构

      非关系型数据库是key-value存储的,没有表结构

    SQL语句基本操作:

    MySQL服务端软件即mysqld帮我们管理好文件夹及文件,前提是作为使用者的我们,需要下载mysql的客户端,或者其他模块来连接到mysqld,然后使用mysql软件规定的语法格式去提交自己的命令,实现对文件夹或文件的管理。该语句即sql(Structured Query Language 结构化查询语言)

    SQL语言主要用于存取数据、查询数据、更新数据和管理关系数据库系统;分为3种类型:

    1. DDL语句:  数据库定义语言:数据库、表、视图、索引、存储过程,例如create,drop,alter

    2. DML语句:  数据库操作语言:插入数据insert、删除数据delete、更新数据update、查询数据select

    3. DCL语句:  数据库控制语言:例如控制用户的访问权限grant、revoke 

    操作文件夹(库)

    增: create database db1 charset utf8;     (创建数据库db1,其字符编码为UTF-8;db1是库名)
    
    查: show create database db1;    (查看我刚创建的文件夹db1)
       show databases;    (查看所有的数据库)
    
    改: alter database db1 charset gbk; (改数据库 db1 的字符编码 为 gbk; 不能改名字,只能改字符编码)
    
    删: drop database db1;   (删数据库db1)

    操作文件(表)

    先切换文件夹: use db1;   (切换到数据库db1) 
    
    查看当前所在的文件夹(库): select database(); 
    
    增: create table t1(id int,name char(10));  (创建文件(表),文件名是t1,表中字段是id(id的数据类型是整型) 和 name(name是字符))
    
    查: show create table t1;  (查看创建的文件t1)
         desc t1;   (查看表t1;desc是describe的缩写)
       show tables;  (查看当前库下所有的表/文件)
    
    改: alter table t1 modify name char(6);    (修改表t1,把t1中name字段char的宽度改为6)
       alter table t1 change name NAME char(7);   (修改表t1,把t1中name字段改为NAME,并把char改为7)
       alter table t1 alter column name set default "NEO"; -- 修改默认值
    删:
    drop table t1; (删除t1这个表)

    操作文件内容(记录)

    增:insert t1(id,name) values(1,"neo1"),(2,"neo2"),(3,"neo3");    (往t1这个文件中插入values;插入多条value用逗号隔开;values中的值按照t1后面的字段顺序添加)
      insert t1 values(1,"neo1"),(2,"neo2"),(3,"neo3");   (t1后面不加字段名,默认按字段顺序添加values)
    
    查:select id,name from t1;    (查看当前库下t1这个表的id和name)
      select id,name from db1.t1;   (如果所查看的t1表不在当前库下,则在t1前加上db1这个库名前缀)
      select id from t1;  (只查询id)
      select * from t1;   (查询所有字段)
    
    改:update db1.t1 set name="NEO";  (更改db1库下的t1表,把name字段全部设置成NEO)
      update t1 set name="Neo" where id=2;   (更新当前库下的t1表,把id为2那一行name设置成Neo)
    
    删:delete from t1;  (把t1表下的所有记录都删除)
         delete from t1 where id=2;   (把t1表下id为2的记录删除)

    库操作:

    系统数据库:

      information_schema:虚拟库,不占用磁盘空间,存储的是数据库启动后的一些参数,如用户表信息、列信息、权限信息、字符信息等

      performance_schema:MySQL 5.5开始新增一个数据库:主要用于收集数据库服务器性能参数,记录处理查询请求时发生的各种事件、锁等现象

      mysql:授权库,主要存储系统用户胡权限信息

      test:MySQL数据库系统自动创建的测试数据库

    创建数据库:

    1. 语法: 
        create database 数据库名 charset utf8;

    2. 数据库命名规则:

      可以由字母、数字、下划线、@、#、¥

      区分大小写

      唯一性

      不能使用关键字如create、select等

      不能单独使用数字

      最长128位

    数据库相关操作:

    查看数据库:
      show databases;
      show create database db1;
      select database();
    
    选择数据库:
      use 数据库名;
    
    删除数据库:
      drop database 数据库名;
    
    修改数据库:
      alter database db1 charset utf8;

    存储引擎介绍:

    1. 数据库中的表有不同胡类型,表的类型不同,会对应mysql不同的存取机制,表类型又称存储引擎;存储引擎就是表的类型

    2. 查看MySQL支持的存储引擎: show engines;   # 默认的存储引擎是innodb

    3. 指定表类型/存储引擎:

      create table t1(id int)engine=innodb;

      create table t1(id int)engine=memory;

      create table t1(id int)engine=blackhole;

    表操作:

    1. 表介绍:表相当于文件,表中的一条记录就相当于文件的一行内容,不同的是,表中的一条记录有对应的标题,称为表的字段

    id,name,age,sex称为字段,其余的,一行内容称为一条记录

    2. 创建表:

    -- 语法:
    
      create table 表名(
    
      字段名1 类型[(宽带)约束条件],
    
      字段名2 类型[(宽带)约束条件],
    
      字段名3 类型[(宽带)约束条件]
    
      ) ;
    
    -- 附:表中最后一个字段后面不要再加逗号

    注意:

      1. 同一张表种,字段名不能相同

      2. 宽带和约束条件可选

      3. 字段名肯类型椒必须的

    3. 查看表结构:

    1.  describe 表名;    -- 查看表结构,可简写为  desc 表名;
    2.  show create table 表名;  -- 查看表详细结构,可加 G

    4. 修改表结构:

    1. 修改表名: alter table 表名 rename 新表名;
    
    2. 增加字段: alter table 表名 add 字段名 数据类型 [完整性约束条件], add 字段名 数据类型 [完整性约束条件];
           alter table 表名 add 字段名 数据类型 [完整性约束条件] first;     -- 把这个字段放到第几个位置
           alter table 表名 add 字段名 数据类型 [完整性约束条件] after 字段名;   -- 把新添加的字段放到某个字段后面
    
    3. 删除字段: alter table 表名 drop 字段名;
    4. 修改字段: alter table 表名 modify 字段名 数据类型 [完整性约束条件];   -- 修改字段的数据类型相关信息
           alter table 表名 change 旧字段名 新字段名 新/旧数据类型 [完整性约束条件];   -- 修改字段名和数据类型

    5. 删除表: 

    drop table 表名;

    6. 复制表:

      1. 复制表结构和记录: 

    create table 表名1 select name,age from db1.表名2;      -- 数据库db1中的表名2中的name和age复制到表名1中(把表2的查询结果当作复制的内容传给表1)

      2. 只复制表结构,不复制纪录:

    create table 表名1 select name,age from db1.表名2 where 1>5;   --   where 1>5是一个假条件(没有纪录能满足这个条件),但表名2的表结构却是存在的,通过这种方式去只复制表结构

      3. 只复制全部的表结构: 

    create table 表名1 like db1.表名2;   --  复制db1数据库中表名2的所有表结构,不复制纪录

     

    数据类型:

    存储引擎决定了表的类型,而表内存放的数据也要有不同的类型,每种数据类型都有自己的宽带,但宽度是可选的

    详细参考:

        http://www.runoob.com/mysql/mysql-data-types.html

        https://dev.mysql.com/doc/refman/5.7/en/data-type-overview.html

    MySQL常用数据类型:

      1. 数字

        整形:tinyint, int, bigint

        小数:

          float:在位数比较短的情况下不精确

          double:在位数比较长的情况下不精确

          decimal:精确,内部原理是字符串形式存储

      2. 字符串:

        char(10):简单粗暴,浪费空间,存取速度快;root存成root000000

        varchar:精确,节省空间,存取速度慢

      3. 时间类型: 最常用:datetime

      4. 枚举类型于集合类型

    数值类型:

    1. 整数类型:tinyint, smallint, mediumint,bigint; 作用:存储年龄、等级、id、各种号码等

      tinyint[(m)] [unsigned] [zerofill]

      小整数,数据类型用于保存一些范围的整数数值范围:

      有符号: -128~127 ;  无符号: 0~255 ; ps: MySQL中无布尔值,使用tinyint(1)构造

      int[(m)] [unsigned] [zerofill]

      整数,数据类型用于保存一些范围的整数数值范围:

      有符号:-2147483648 ~ 2147483647;无符号: 0 ~ 4294967295

    注意:为整数类型指定宽度时,仅仅只是指定查询结果的显示宽度,与存储范围无关;其实我们完全没必要为整数类型指定显示宽带,使用默认的就可以了;默认的显示宽带,都是在最大值的基础上加1

    int的存储宽度是4个bytes,即32个bit,即2**32; 无符号最大值为:4294967296-1;有符号最大值:2147483648-1

    有符号和无符号的最大数字需要的显示宽度均为10,而针对有符号的最小值则需要11位才能显示完整,所以int类型默认的显示宽带为11是非常合理的;所以,整形类型,没有必要指定显示宽度,使用默认的就行

    浮点型:定点数类型:decimal(等同于dec); 浮点类型:float,double;作用:存储薪资、身高、体重、体质参数等

      float[(m,d)] [unsigned] [zerofill]:

        定义:单精度浮点数(非准确小数值),m是数字总个数,d是小数点后个数;m最大值为255,d最大值为30;随着小数的增多,精度变得不准确

      double[(m,d)]  [unsigned] [zerofill]:

        定义:双精度浮点数(非准确小数值),m是数字总个数,d是小数点后个数。m最大值为255,d最大值为30;随着小数的增多,精度比float要高,但也会变得不准确

      decimal[(m[,d])] [unsigned] [zerofill]:

        定义: 准确的小数值,m是数字总个数(符号不算),d是小数点后个数。 m最大值为65,d最大值为30;随着小数的增多,精度始终准确;对于精确数值计算时需要用此类型;decaimal能够存储精确值的原因在于其内部按照字符串存储。

    补充知识点:加入一条sql语句写错了,可以利用 c 来终止这条语句的运行; 假如少了一个引号,就先把引号补全再用c, 如: 'c

    日期类型:year, date, time, datetime, timestamp;作用:存储用户注册时间、文章发布时间、入职时间、出生时间、过期时间等

    形式与范围:

      year:YYYY(1901/2155)

      date:YYYY-MM-DD (1000-01-01/9999-12-31)

      time:HH:MM:SS('-838:59:59'/'838:59:59')

      datetime: YYYY-MM-DD HH:MM:SS(1000-01-01 00:00:00/9999-12-31 23:59:59 )

      timestamp:YYYYMMDD HHMMSS(1970-01-01 00:00:00/2037 年某时)

    先看下面一段sql语句:

     create table stu1(
                       id int,
                       name char(6),
                       born_year year,
                       birth_date date,
                       class_time time,
                       regis_time datetime
                       );   # char(6)是最多能存储6个字符,所以名字最多6个字符
    
     insert stu1 values(1,"neo",now(),now(),now(),now()); # now()是mysql是自带的一个函数,调用当前时间

    执行结果如下:

    也可以自己添加日期: 

    insert stu1 values(2,"alex","2007","2007-1-11","08:00:00","2016-1-11 11:11:00"); 

    如下图:

    字符类型:

    char和varchar括号内的参数指的都是字符的长度

    char类型:定长,简单粗暴,浪费空间,存取速度快

      字符长度范围:0-255 (一个中文是一个字符,是utf8编码的3个字节)

      存储:存储char类型的值时,会往右填充空格来满足长度,例如:指定长度为10,存<10个字符则用空格填充直到凑够10个字符存储

      检索:在检索或者说查询时,查出的结构会自动删除尾部的空格,除非我们打开pad_char_to_full_length SQL 模式(SET sql_mode = "PAD_CHAR_TO_FULL_LENGTH";)

    varchar类型:变长,精准,节省空间,存取速度慢

      字符长度范围:0-65535(mysql行最大限制为65535字节)

      存储:varchar类型存储数据的真实内容,不会用空格填充;

         varchar类型会在真实数据前加1~2个bytes作为前缀,该前缀用来表示真实数据的bytes字节数(1~2bytes最大表示65535个数字,正好符合mysql对row的最大字节限制,即已经足够使用)

         如果真实的数据<255则需要一个bytes的前缀(1Bytes=8bit 2**8最大表示的数字为255)

         如果真实的数据>255bytes则需要2Bytes的前缀(2Bytes=16bit 2**16最大表示的数字为65535)

      检索: 尾部有空格会保存下来,在检索或者说查询时,也会正常显示包含空格在内的内容

    # length:查看字节数;  char_length:查看字符数

    1. char填充空格来满足固定长度,但是在查询时会自动删除尾部的空格来匹配查询值

    2. 虽然char和varchar的存储方式不太相同,但是取的时候(“=” 的情况),对于两个字符串的比较,都是只比较其值,忽略char存在的右填充(只会忽略后面的空格,不会忽略前面和中间的空格),即使将sql_mode设置成PAD_CHAR_TO_FULL_LENGTH也一样;但这不适用于like

    所以,虽然varchar使用起来比较灵活,但是从整个系统的性能角度来说,char数据类型的处理速度更快

    枚举类型和集合类型:

    字段的值只能在给定范围内选择,如单选框、多选框

    enum 单选 只能在给定的范围内选一个值,如性别 sex male/female

    set 多选  在给定的范围内可以选择一个或多个值(爱好1,爱好2.。。)

    create table client(name char(20),
                        age int,
                        sex enum("female","male"),
                        level enum("vip1","vip2","vip3"),
                        hobbies set("reading","working out","music","run")
                        );
    
    insert client values("neo",18,"male","vip1","music,run"),
                        ("alex",73,"female","vip3","boy");  -- 第二条数据加不进去

    运行结果:

    约束条件:

    not null和default:

    create table condition_null_default(
                                        id int,
                                        name char(10),
                                        sex enum("male","female") not null default "male"
                                        );
    
    insert condition_null_default(id,name) values(1,"neo"),
                                                 (2,"alina","female");

    如下:

    约束条件 unique key:

    单列唯一:

    方式一:

    create table department1(
    id int unique,
    name char(10) unique
    );
    
    insert department1 values(1,"IT"),(2,"Sales);

    方式二:

    create table department2(
    id int,
    name char(10),
    unique(id),
    unique(name)
    );

    联合唯一:

    create table server(
    id int unique,
    ip char(15),
    port int,
    unique(ip,port)
    );    # unique(ip,port)的含义是: ip和port拼到一起后必须是唯一的

     

    primary key: 

    约束:not null unique(不为空且唯一)

    存储引擎(默认innodb):对于innodb存储引擎来说,一张表内必须有一个主键(通常将id字段设为主键)

    单列主键:

    create table t_primary(
    id int primary key,name char(16));

    对于innodb,如果你不指定主键,innodb会找一个不为空且唯一的字段作为主键;如果没找到,就用它自己隐藏的字段作为主键;如下

    复合主键:

    create table t_union_primary(
    ip char(15),
    port int,
    primary key(ip,port)
    );    # ip和port联合组成主键

    auto_increment: (自增长)

    create table t_auto_incre(
    id int primary key auto_increment,
    name char(16));   # auto_increment的字段需要指定key  # 默认是从1开始,每次增加1
    
    insert t_auto_incre(name) values("neo"),
    ("egon"),
    ("alex");

    如果中间自己不按顺序插入了id,后面的id auto_increment时以你新插入的id作为起点

    insert t_auto_incre(id,name) values(7,"neo1");
    
    insert t_auto_incre(name) values
    ("NEO1"),
    ("NEO2"),
    ("NEO3");

    # 查看mysql关于auto_increment的默认设置
    show variables like "auto_inc%";      # show variables 是查看变量,like是模糊匹配,%代表任意长度的任意字符

      # 步长: auto_increment_increment默认为1

      # 起始偏移量(位置): auto_increment_offset默认为1

    #设置步长:
    set session auto_increment_increment=5;
    set global auto_increment_increment=5;
    
    #session是会话级别的修改,就是只在本次运行时有效,退出再登录后会恢复到原先的设置;
    #global是全局级别的修改,长期有效,但需要推出后重新登录mysql才会生效
    
    #设置起始偏移量:
    set session auto_increment_offset=3;
    set global auto_increment_offset=3;
    #用法同上;需要注意的一点:起始偏移量必须要小于等于步长

     清空表:

      delete from 表名 where xxx; 不要用delete去清空表,delete用在跟where语句连用的情况下;delete from 表名 无法删除自增长(auto_increment)的纪录

      truncate 表名;  清空表应该用 truncate(能把自增长的纪录也删除掉)

    foreign key(外键):建立表之间的关系

    1. 建表

    # 先建被关联的表,并且保证保证被关联的字段唯一
    create table dept(
    id int primary key,
    name char(16),
    comment char(50));
    
    # 再建关联表
    create table emp(
    id int primary key,
    name char(10),
    sex enum("male","female"),
    dept_id int,
    foreign key(dept_id) references dept(id));   # dept_id是外键,关联到dept表的id字段

    2. 插入数据

    # 先往被关联表中插入纪录
    insert dept values
    (1,"IT","干技术的"),
    (2,"Sales","卖东西的"),
    (3,"Finance","花钱的");
    
    # 再往关联表中插入数据
    insert emp values
    (1,"neo","male",1),
    (2,"alex","female",2),
    (3,"egon","male",3);   # 因为只有被关联表的关联字段建起来后关联表才能去关联;后有纪录的那张表加foreign key

    上述建表方式由于没有指定 on delete cascade on update cascade,所以不能直接操作被关联表

    如果想删除、更新同步(即 删除、更细被关联表的关联字段,关联表也自动跟着删除、更新),关联表建表时要加上 on delete cascase on update cascade   例如:foreign key(dept_id) references dept(id) on delete cascade on update cascade

    # 建被关联的表
    create table dept(
    id int primary key,
    name char(16),
    comment char(50));
    
    # 建关联表
    create table emp(
    id int primary key,
    name char(10),
    sex enum("male","female"),
    dept_id int,
    foreign key(dept_id) references dept(id) on delete cascade on update cascade
    );     # 加上 on delete cascade on update cascade
    delete from dept where id=1;
    update dept set id=202 where id=2;

    tips:实际项目中尽量不要把两张表建立硬性限制(foreign key),最好能从逻辑上去实现两张表的关系,即从应用程序代码的层面上去实现两张表的关系,不要再数据库利用foreign key去建立硬性关系(这样不利于扩展)

    表与表之间的关系: 多对一、多对多、一对一

    多对一:例如上面的例子,员工表emp中多个人纪录可以对应部门表dept中的一个部门纪录,但多个部门纪录却不能对应一个人(即 多个人可以在一个部门下,但一个人却不能在多个部门),这就是多对一

    多对多:A表中的多条纪录可以对应B表中的一条纪录,同时B表中的多条纪录也可以对应A表中的一条纪录,这就是多对多;多对多需要专门另外建一张表来存多对多之间的关系;例如下面的书与作者的例子:

    create table author(
    id int primary key auto_increment,
    name char(16));
    
    create table book(
    id int primary key auto_increment,
    name char(50));
    
    # 专门建一张表来保存多对多那两张表之间的关系
    create table author2book(
    id int not null unique auto_increment,
    author_id int not null,
    foreign key(author_id) references author(id)
    on delete cascade
    on update cascade,
    book_id int not null,
    foreign key(book_id) references book(id)
    on delete cascade
    on update cascade,
    primary key(author_id,book_id));   # author_id去多对一author表中的id字段,book_id去多对一book表中的id字段
    
    insert author(name) values("neo"),("egon"),("alex"),("wusir");
    insert book(name) values("python自动化"),("linux运维"),("python全栈");
    
    # 插入多对多之间的关系
    insert author2book(author_id,book_id) values
    (1,1),(1,2),(1,3),
    (2,1),(2,2),
    (3,2),
    (4,2),(4,3);

    一对一:两张表中的纪录最多只能互相对应中的一条纪录,即一一对应,例如博客园中一个昵称只能对应一个博客链接,一个博客链接也只能对应一个昵称

    以培训机构的custome和student为例,客户(customer)表中的一条纪录最多只能对应student表中的一个纪录,student表中的一条纪录也一定对应customer表中的一条纪录:

    # 先有潜在客户customer才能有学生(student),后有纪录的那钟表加foreign key
    create table customer(
    id int primary key auto_increment,
    name char(10) not null,
    phone int not null);
    
    create table student(
    id int primary key auto_increment,
    class_name char(16) not null,
    customer_id int unique,
    foreign key(customer_id) references customer(id)
    on delete cascade
    on update cascade);   # 要想称为一对一的表,student的字段 customer_id必须要指定为 unique; 外键一定要保证 unique !!!
    
    insert into customer(name,phone) values
    ('李飞机',13811341220),
    ('王大炮',15213146809),
    ('守榴弹',1867141331),
    ('吴坦克',1851143312),
    ('赢火箭',1861243314),
    ('战地雷',18811431230);
    
    insert student(class_name,customer_id) values
    ("python周末5期",3),
    ("linux运维6期",5);
  • 相关阅读:
    CF1117G Recursive Queries
    P6604 [HNOI2016]序列 加强版
    高级图论
    P7708「Wdsr-2.7」八云蓝自动机 Ⅰ
    ISIJ2020 游记
    计算几何笔记 (模板)
    AC自动机学习笔记
    KMP学习笔记
    treap学习笔记
    HolyK学长的杂题选讲
  • 原文地址:https://www.cnblogs.com/neozheng/p/8719471.html
Copyright © 2020-2023  润新知