zoukankan      html  css  js  c++  java
  • MySQL数据库(安装+增删改查)

    一. 安装

     下载地址 : https://dev.mysql.com/downloads/mysql/

     1. 安装步骤

        (1) 选择5.7版本

      (2) 针对操作系统的不同下载不同的版本

      (3) 解压

       将解压后的文件夹解压到你所指定的目录

      (4) 添加环境变量

      【右键计算机】--》【属性】--》【高级系统设置】--》【高级】--》【环境变量】--》【在第二个内容框中找到 变量名为Path 的一行,双击】 --> 【将MySQL的bin目录路径追加到变值值中,用 ; 分割】

      window10系统可以在点击Path后,可以选择添加,把MySQL的bin目录粘贴到新的行里.

      (5) 初始化

      添加完环境变量后, 一定要先初始化,用管理员权限打开cmd窗口,写入按回车  :  mysqld --initialize-insecure 按回车然后等待初始化完成,在mysql-5.7.23-winx64文件下出现一个新的文件夹data

      (6) 启动mysql服务端

      在cmd(管理员身份)输入 mysqld, 启动MySQL服务 

      (7) 启动mysql客户端并连接mysql服务端(新开一个cmd窗口)

      再开启一个新的cmd窗口,输入 mysql -u root -p 命令,按enter出现输入密码行,不用输入,继续按enter.

      (8) install mysql

      在install之前复制bin文件夹的绝对路径,例如: D:mysql-5.7.23-winx64mysql-5.7.23-winx64in

      关闭任务管理器里关闭mysqld.exe程序进程.

      用管理员权限再开启一个cmd窗口,

      开启MySQL的window服务,输入 :  D:mysql-5.7.23-winx64mysql-5.7.23-winx64inmysqld --install    按enter键

      移除MySQL的window服务,输入 :  D:mysql-5.7.23-winx64mysql-5.7.23-winx64inmysqld --remove   按enter键

      在服务里面查看是否有MySQL

       鼠标右键有启动,停止等选项

      也可以在cmd窗口进行操作 :

      在cmd窗口开启MySQL服务 :  net start MySQL  (以管理员身份开启cmd)

      在cmd窗口关闭MySQL服务 :  net stop MySQL

      (9) 统一字符编码

      进入mysql客户端,执行s,查看编码格式

      把编码格式改成utf-8,执行以下操作:

              1)my.ini文件是mysql的配置文件,在D:mysql-5.7.23-winx64mysql-5.7.23-winx64(安装路径)文件下创建my.ini文件

       2) 把下面的代码拷贝到my.ini文件里,并保存.

    #mysql5.5以上:修改方式为
    [mysqld]
    character-set-server=utf8
    collation-server=utf8_general_ci
    [client] default-character-set=utf8 [mysql] default-character-set=utf8

         3)以管理员身份重启服务, 执行如下命令 

    C:Windowssystem32>net stop MySQL  # 先停止服务
    MySQL 服务正在停止..
    MySQL 服务已成功停止。
    
    C:Windowssystem32>net start MySQL
    MySQL 服务正在启动 .
    MySQL 服务已经启动成功。

        4)在cmd中输入mysql进入mysql环境,执行s,显示编码格式都为utf-8,表示成功.

    二. 库的操作

     1. 系统数据库

       执行下面命令,查看系统的数据库

    show databases;

      nformation_schema: 虚拟库,不占用磁盘空间,存储的是数据库启动后的一些参数,如用户表信息、列信息、权限信息、字符信息等
      performance_schema: MySQL 5.5开始新增一个数据库:主要用于收集数据库服务器性能参数,记录处理查询请求时发生的各种事件、锁等现象
      mysql: 授权库,主要存储系统用户的权限信息
      test: MySQL数据库系统自动创建的测试数据库

    2. 创建数据库

      语法:

    CREATE DATABASE 数据库名;

      命名规则:

    可以由字母、数字、下划线、@、#、$
    区分大小写
    唯一性
    不能使用关键字如 create select
    不能单独使用数字
    最长128位
    # 基本上跟python或者js的命名规则一样

    3. 数据库的相关操作

    #查看数据库
    show databases;
    #查看当前库
    show create database db1;
    #查看所在的库
    select database();
    
    #选择数据库
    use 数据库名
    
    #删除数据库
    DROP DATABASE 数据库名;
    # 修改数据库
    alter database db1 charset utf8;

    三. 表的操作

     1. 存储引擎  

      现实生活中我们用来存储数据的文件有不同的类型,每种文件类型对应各自不同的处理机制:比如处理文本用txt类型,处理表格用excel,处理图片用png等数据库中的表也应该有不同的类型,表的类型不同,会对应mysql不同的存取机制,表类型又称为存储引擎. MySql数据库提供了多种存储引擎, 用户可以根据不同的需求为数据表选择不同的存储引擎,用户也可以根据自己的需要编写自己的存储引擎.

    mysql> show enginesG;  # 查看所有支持的引擎
    mysql> show variables like 'storage_engine%'; # 查看正在使用的存储引擎
    create table t1(id int)engine=innodb;  # 默认不写就是innodb

    2. 创建表

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

        语法: 

    create table 表名(
    字段名1 类型[(宽度) 约束条件],
    字段名2 类型[(宽度) 约束条件],
    字段名3 类型[(宽度) 约束条件]
    );
    
    #注意:
    1. 在同一张表中,字段名是不能相同
    2. 宽度和约束条件可选
    3. 字段名和类型是必须的

      步骤 :

      (1) 创建数据库

    CREATE DATABASE db1;

      (2) 使用数据库

    USE db1;

      (3) 创建表

    create table t1(
      id int,       # 字段id
      name varchar(50),   # 字段 name
      age int()   # 字段age
    );

      (4) 插入表的记录

    insert into t1 values      # values 也可以写成values(id,name,age)括号呢可以指定字段进行插入
    (1,'jack',18),  # 插入多条记录,用逗号隔开
    (2,'tom',22);

      (5) 对记录修改

    update db1.t1 set name='ben';
    update db1.t1 set name='steve' where id=2;  # 指定id为2的记录

      (6) 删除记录

    delete from t1;
    delete from t1 where id=2;

    3. 表的其它操作  

      (1) 查询表的存储数据

         语法 : select * from 表名;

    mysql> select * from t1;
    +------+-------+------+
    | id   | name  | age  |
    +------+-------+------+
    | 1    | jack  | 18   |
    | 2    | tom   | 22   |
    +------+-------+------+
    2 rows in set (0.02 sec)

      (2) 查询表的结构

      语法 : desc 表名

    mysql> desc t1;
    +-------+-------------+------+-----+---------+-------+
    | Field | Type        | Null | Key | Default | Extra |
    +-------+-------------+------+-----+---------+-------+
    | id    | int(11)     | YES  |      | NULL   |       |
    | name  | varchar(50) | YES  |      | NULL   |       |
    | age   | int()       | YES  |      | NULL   |       |
    +-------+-------------+------+-----+---------+-------+
    rows in set (0.16 sec)

      (3) 查看表的详细结构

    mysql> show create table a1G;
    *************************** 1. row ***************************
    Table: a1
    Create Table: CREATE TABLE `a1` (
    `id` int(11) DEFAULT NULL,
    `name` varchar(50) DEFAULT NULL,
    `age` int(3) DEFAULT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8
    row in set (0.00 sec)

      (4) 复制表

        1) 新创建一个数据库db2

    create database db2;

        2) 使用db2

    use db2;

        3) 复制db1中的表t1

    # 这就是复制表的操作(既复制了表结构,又复制了记录)
    mysql> create table t2 select * from db1.t1;
    Query OK, 2 rows affected (0.03 sec)

        4) 查看db2中的表t2

    #再去查看db3文件夹下的t3表发现 跟db3文件下的t1表数据一样
    mysql> select * from db3.b1;
    +------+-------+------+
    | id   | name  | age  |
    +------+-------+------+
    |    1 | jack  |   18 |
    |    2 | tom   |   22 |
    +------+-------+------+
    2 rows in set (0.00 sec)
    # 查看表结构
    mysql> desc t2;
    +-------+-------------+------+-----+---------+-------+
    | Field | Type        | Null | Key | Default | Extra |
    +-------+-------------+------+-----+---------+-------+
    | id    | int(11)     | YES  |     | NULL    |       |
    | name  | varchar(50) | YES  |     | NULL    |       |
    | age   | int()       | YES  |     | NULL    |       |
    +-------+-------------+------+-----+---------+-------+
    3 rows in set (0.02 sec)

        只拷贝表结构,不要记录:

    #在db2数据库下新创建一个t2表,给一个where条件,条件要求不成立,条件为false,只拷贝表结构
    mysql> create table t2 select * from db2.a1 where 1>5;  # where 为条件判断,只要where后面的条件为假即可
    Query OK, 0 rows affected (0.05 sec)
    Records: 0  Duplicates: 0  Warnings: 0
    #查看表结构中的数据,发现是空数据
    mysql> select * from t2;
    Empty set (0.00 sec)

      使用like也是只拷贝表结构,不拷贝记录

    mysql> create table t2 like db1.t1;
    Query OK, 0 rows affected (0.01 sec)

    (5) 删除表

    drop table 表名;

    四. 数据类型

     1. mysql 常用数据类型

    #1. 数字:
        整型:tinyint  int  bigint
        小数:
            float :在位数比较短的情况下不精准
            double :在位数比较长的情况下不精准
                0.000001230123123123
                存成:0.000001230000
    
            decimal:(如果用小数,则用推荐使用decimal)
                精准
                内部原理是以字符串形式去存
    
    #2. 字符串:
        char10):简单粗暴,浪费空间,存取速度快
                root存成root000000
        varchar:精准,节省空间,存取速度慢
    
        sql优化:创建表时,定长的类型往前放,变长的往后放
                        比如性别           比如地址或描述信息
    
        >255个字符,超了就把文件路径存放到数据库中。
                比如图片,视频等找一个文件服务器,数据库中只存路径或url。
    
    
    #3. 时间类型:
        最常用:datetime
    
    
    #4. 枚举类型与集合类型
       enum 和set

    2. 数值类型

      整数类型:TINYINT   SMALLINT   MEDIUMINT   INT   BIGINT

      作用:存储年龄,等级,id,各种号码等

    =======================================================
            tinyint[(m)] [unsigned] [zerofill]
    
                小整数,数据类型用于保存一些范围的整数数值范围:
                有符号:
                    -128127
                无符号:0~ 255
    
                PS: MySQL中无布尔值,使用tinyint(1)构造。
    =======================================================
            int[(m)][unsigned][zerofill]
    
                整数,数据类型用于保存一些范围的整数数值范围:
                有符号:
                        -21474836482147483647
                无符号:0 ~ 4294967295
    =======================================================
            bigint[(m)][unsigned][zerofill]
                大整数,数据类型用于保存一些范围的整数数值范围:
                有符号:
                        -92233720368547758089223372036854775807
                无符号:0 ~ 18446744073709551615

      注意:

      1)  整数类型都是默认有符号的,可以设置成无符号

    mysql> create table t3(x tinyint unsigned);  # 申明数据类型后加上 unsigned 变为无符号

      2) int类型后面的存储是显示宽度,而不是存储宽度. 整形类型,其实没有必要指定显示宽度,使用默认的就ok

    mysql> create table t3(id int(1) unsigned);
    
    #插入255555记录也是可以的
    mysql> insert into t3 values(255555);
    
    mysql> select * from t3;
    +--------+
    | id     |
    +--------+
    | 255555 |
    +--------+
    ps:以上操作还不能够验证,再来一张表验证用zerofill 用0填充
    
    # zerofill 用0填充
    mysql> create table t4(id int(5) unsigned zerofill);
    
    
    mysql> insert into t4 value(1);
    Query OK, 1 row affected (0.00 sec)
    
    #插入的记录是1,但是显示的宽度是00001
    mysql> select * from t4;
    +-------+
    | id    |
    +-------+
    | 00001 |
    +-------+
    row in set (0.00 sec)

    3. 浮点型

      定点数类型: DEC等同于DECIMAL  

      浮点类型:FLOAT DOUBLE

      作用:存储薪资、身高、体重、体质参数等

    -------------------------FLOAT-------------------
    FLOAT[(M,D)] [UNSIGNED] [ZEROFILL]
    #参数解释:单精度浮点数(非准确小数值),M是全长,D是小数点后个数。M最大值为255,D最大值为30
    
    #有符号:
               -3.402823466E+38 to -1.175494351E-38,
               1.175494351E-38 to 3.402823466E+38
    
    #无符号:
               1.175494351E-38 to 3.402823466E+38
    #精确度: 
               **** 随着小数的增多,精度变得不准确 ****
    
    
     -------------------------DOUBLE-----------------------
    DOUBLE[(M,D)] [UNSIGNED] [ZEROFILL]
    
    #参数解释: 双精度浮点数(非准确小数值),M是全长,D是小数点后个数。M最大值为255,D最大值为30
    
    #有符号:
               -1.7976931348623157E+308 to -2.2250738585072014E-308
               2.2250738585072014E-308 to 1.7976931348623157E+308
    
    #无符号:
               2.2250738585072014E-308 to 1.7976931348623157E+308
    
    #精确度:
               ****随着小数的增多,精度比float要高,但也会变得不准确 ****
    
    ======================================
    --------------------DECIMAL------------------------
    decimal[(m[,d])] [unsigned] [zerofill]
    
    #参数解释:准确的小数值,M是整数部分总个数(负号不算),D是小数点后个数。 M最大值为65,D最大值为30。
    
    
    #精确度:
               **** 随着小数的增多,精度始终准确 ****
               对于精确数值计算时需要用此类型
               decaimal能够存储精确值的原因在于其内部按照字符串存储。

      验证三种浮点数类型建表

    #1验证FLOAT类型建表:
    mysql> create table t5(x float(256,31));
    ERROR 1425 (42000): Too big scale 31 specified for column 'x'. Maximum is 30.
    mysql> create table t5(x float(256,30));
    ERROR 1439 (42000): Display width out of range for column 'x' (max = 255)
    mysql> create table t5(x float(255,30)); #建表成功
    Query OK, 0 rows affected (0.03 sec)
    
    #2验证DOUBLE类型建表:
    mysql> create table t6(x double(255,30)); #建表成功
    Query OK, 0 rows affected (0.03 sec)
    
    #3验证deimal类型建表:
    mysql> create table t7(x decimal(66,31));
    ERROR 1425 (42000): Too big scale 31 specified for column 'x'. Maximum is 30.
    mysql> create table t7(x decimal(66,30));
    ERROR 1426 (42000): Too big precision 66 specified for column 'x'. Maximum is 65.
    mysql> create table t7(x decimal(65,30)); #建表成功
    Query OK, 0 rows affected (0.00 sec)

    4. 日期类型

      DATE TIME DATETIME TIMESTAMP YEAR
      作用:存储用户注册时间,文章发布时间,员工入职时间,出生时间,过期时间等

    语法:
            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    Y)
    
            TIMESTAMP
    
                YYYYMMDD HHMMSS(1970-01-01 00:00:00/2037 年某时)

    5. 字符串类型

    # 注意:char和varchar括号内的参数指的都是字符的长度
    
    # char类型:定长,简单粗暴,浪费空间,存取速度快
        字符长度范围:0-255(一个中文是一个字符,是utf8编码的3个字节)
        存储:
            存储char类型的值时,会往右填充空格来满足长度
            例如:指定长度为10,存>10个字符则报错,存<10个字符则用空格填充直到凑够10个字符存储
    
        检索:
            在检索或者说查询时,查出的结果会自动删除尾部的空格,除非我们打开pad_char_to_full_length SQL模式(设置SQL模式:SET sql_mode = 'PAD_CHAR_TO_FULL_LENGTH';
          查询sql的默认模式:select @@sql_mode;)
    
    # varchar类型:变长,精准,节省空间,存取速度慢
        字符长度范围:0-65535(如果大于21845会提示用其他类型 。mysql行最大限制为65535字节,字符编码为utf-8:https://dev.mysql.com/doc/refman/5.7/en/column-count-limit.html)
        存储:
            varchar类型存储数据的真实内容,不会用空格填充,如果'ab  ',尾部的空格也会被存起来
            强调:varchar类型会在真实数据前加1-2Bytes的前缀,该前缀用来表示真实数据的bytes字节数(1-2Bytes最大表示65535个数字,正好符合mysql对row的最大字节限制,即已经足够使用)
            如果真实的数据<255bytes则需要1Bytes的前缀(1Bytes=8bit 2**8最大表示的数字为255)
            如果真实的数据>255bytes则需要2Bytes的前缀(2Bytes=16bit 2**16最大表示的数字为65535)
    
        检索:
            尾部有空格会保存下来,在检索或者说查询时,也会正常显示包含空格在内的内容

     char填充空格来满足固定长度,但是在查询时却会删除尾部的空格,修改sql_mode让其现出原形。

    
    
    length():查看字节数;  char_length():查看字符数
    # 创建t1表,分别指明字段x为char类型,字段y为varchar类型
    mysql> create table t1(x char(5),y varchar(4));
    Query OK, 0 rows affected (0.16 sec)
    
    # char存放的是5个字符,而varchar存4个字符
    mysql>  insert into t1 values('你瞅啥 ','你瞅啥 ');
    Query OK, 1 row affected (0.01 sec)
    
    # 在检索时char将自己浪费的2个字符给删掉了,装的好像自己没浪费过空间一样,而varchar很老实,存了多少,就显示多少
    mysql> select x,char_length(x),y,char_length(y) from t1;
    +-----------+----------------+------------+----------------+
    | x         | char_length(x) | y          | char_length(y) |
    +-----------+----------------+------------+----------------+
    | 你瞅啥     |              3 | 你瞅啥      |              4 |
    +-----------+----------------+------------+----------------+
    row in set (0.02 sec)
    
     #略施小计,让char现原形
     mysql> SET sql_mode = 'PAD_CHAR_TO_FULL_LENGTH';
    Query OK, 0 rows affected (0.00 sec)
    
    #查看当前mysql的mode模式
    mysql> select @@sql_mode;
    +-------------------------+
    | @@sql_mode              |
    +-------------------------+
    | PAD_CHAR_TO_FULL_LENGTH |
    +-------------------------+
    row in set (0.00 sec)
    
    #原形毕露了吧。。。。
    mysql> select x,char_length(x) y,char_length(y) from t1;
    +-------------+------+----------------+
    | x           | y    | char_length(y) |
    +-------------+------+----------------+
    | 你瞅啥       |    5 |              4 |
    +-------------+------+----------------+
    row in set (0.00 sec)
    
    # 查看字节数
    #char类型:3个中文字符+2个空格=11Bytes
    #varchar类型:3个中文字符+1个空格=10Bytes
    mysql> select x,length(x),y,length(y) from t1;
    +-------------+-----------+------------+-----------+
    | x           | length(x) | y          | length(y) |
    +-------------+-----------+------------+-----------+
    | 你瞅啥       |        11 | 你瞅啥      |        10 |
    +-------------+-----------+------------+-----------+
    row in set (0.02 sec)

    6. 枚举类型和集合类型

         枚举和集合可以让字段的值只能在给定范围中选择,如单选框,多选框

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

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

     

    mysql> create table consumer(
        -> id int,
        -> name varchar(50),
        -> sex enum('male','female','other'),
        -> level enum('vip1','vip2','vip3','vip4'),#在指定范围内,多选一
        -> fav set('play','music','read','study') #在指定范围内,多选多
        -> );
    Query OK, 0 rows affected (0.03 sec)
    
    
    mysql> insert into consumer values
        -> (1,'jack','male','vip2','read,study'),
        -> (2,'steve','other','vip4','play');
    Query OK, 2 rows affected (0.00 sec)
    Records: 2  Duplicates: 0  Warnings: 0
    
    mysql> select * from consumer;
    +------+---------+-------+-------+------------+
    | id   | name    | sex   | level | fav        |
    +------+---------+-------+-------+------------+
    |    1 | jack    | male  | vip2  | read,study |
    |    2 | steve   | other | vip4  | play       |
    +------+---------+-------+-------+------------+
    rows in set (0.00 sec)

    五. 完整性约束

     1. 介绍

      约束条件与数据类型的宽度一样,都是可选参数

      作用:用于保证数据的完整性和一致性

    主要分为:
    PRIMARY KEY (PK)    #标识该字段为该表的主键,可以唯一的标识记录
    FOREIGN KEY (FK)    #标识该字段为该表的外键
    NOT NULL    #标识该字段不能为空
    UNIQUE KEY (UK)    #标识该字段的值是唯一的
    AUTO_INCREMENT    #标识该字段的值自动增长(整数类型,而且为主键)
    DEFAULT    #为该字段设置默认值
    
    UNSIGNED #无符号
    ZEROFILL #使用0填充
    说明:
    #1. 是否允许为空,默认NULL,可设置NOT NULL,字段不允许为空,必须赋值
    #2. 字段是否有默认值,缺省的默认值是NULL,如果插入记录时不给字段赋值,此字段使用默认值
    sex enum('male','female') not null default 'male'
    
    #必须为正值(无符号) 不允许为空 默认是20
    age int unsigned NOT NULL default 20 
    # 3. 是否是key
    主键 primary key
    外键 foreign key
    索引 (index,unique...)

    2. not null 和 default

    是否可空,null表示空,非字符串
    not null - 不可空
    null - 可空
    
    默认值,创建列时可以指定默认值,当插入数据时如果未主动设置,则自动添加默认值
    create table tb1(
        nid int not null defalut 2,  # 约束nid不能为空,默认值为2, 设置nid字段有默认值后,则无论id字段是null还是not null,都可以插入空,插入空默认填入default指定的默认值
        num int not null  # 约束num不能为空
    
    );

    3. unique

       在mysql中称为单列唯一

        举例说明:

      创建表:

    # 创建公司部门表(每个公司都有唯一的一个部门)。
    mysql> create table department(
        -> id int,
        -> name char(10)
        -> );
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> insert into department values(1,'IT'),(2,'IT');
    Query OK, 2 rows affected (0.00 sec)
    Records: 2  Duplicates: 0  Warnings: 0
    
    mysql> select * from department;
    +------+------+
    | id   | name |
    +------+------+
    |    1 | IT   |
    |    2 | IT   |
    +------+------+
    rows in set (0.00 sec)
    # 发现: 同时插入两个IT部门也是可以的,但这是不合理的,所以我们要设置name字段为unique 解决这种不合理的现象。
    
    验证之前重复插入记录的操作是可行的,但是不符合场景

      使用约束条件unique,来对公司部门的字段进行设置

    #第一种创建unique的方式
    #例子1:
    create table department(
        id int,
        name char(10) unique
    );
    mysql> insert into department values(1,'it'),(2,'it');
    ERROR 1062 (23000): Duplicate entry 'it' for key 'name'
    
    #例子2:
    create table department(
        id int unique,
        name char(10) unique
    );
    insert into department values(1,'it'),(2,'sale');
    
    #第二种创建unique的方式
    create table department(
        id int,
        name char(10) ,
        unique(id),
        unique(name)
    );
    insert into department values(1,'it'),(2,'sale');

      联合唯一: 只要两列记录,有一列不同,既符合联合唯一的约束

    # 创建services表
    mysql> create table services(
        -> id int,
        -> ip char(15),
        -> port int,
        -> unique(id),
        -> unique(ip,port)
        -> );
    Query OK, 0 rows affected (0.05 sec)
    
    mysql> desc services;
    +-------+----------+------+-----+---------+-------+
    | Field | Type     | Null | Key | Default | Extra |
    +-------+----------+------+-----+---------+-------+
    | id    | int(11)  | YES  | UNI | NULL    |    
    |
     | ip | char(15) | YES | MUL | NULL | | | port | int(11) | YES | | NULL | | +-------+----------+------+-----+---------+-------+ rows in set (0.01 sec) #联合唯一,只要两列记录,有一列不同,既符合联合唯一的约束 mysql> insert into services values -> (1,'192,168,11,23',80), -> (2,'192,168,11,23',81), -> (3,'192,168,11,25',80); Query OK, 3 rows affected (0.01 sec) Records: 3 Duplicates: 0 Warnings: 0 mysql> select * from services; +------+---------------+------+ | id | ip | port | +------+---------------+------+ | 1 | 192,168,11,23 | 80 | | 2 | 192,168,11,23 | 81 | | 3 | 192,168,11,25 | 80 | +------+---------------+------+ rows in set (0.00 sec) mysql> insert into services values (4,'192,168,11,23',80); ERROR 1062 (23000): Duplicate entry '192,168,11,23-80' for key 'ip'

    4. primary key : 主键

      一个表中可以:

        单列做主键
        多列做主键(复合主键)

        约束:等价于 not null unique,字段的值不为空且唯一

        存储引擎默认是(innodb):对于innodb存储引擎来说,一张表必须有一个主键。

     单列主键:

    # 创建t14表,为id字段设置主键,唯一的不同的记录
    create table t14(
        id int primary key,
        name char(16)
    );
    
    insert into t14 values
    (1,'xiaoma'),
    (2,'xiaohong');
    
    mysql> insert into t14 values(2,'wxxx');
    ERROR 1062 (23000): Duplicate entry '6' for key 'PRIMARY'
    
    
    #   not null + unique的化学反应,相当于给id设置primary key
    create table t15(
        id int not null unique,
        name char(16)
    );
    mysql> create table t15(
        -> id int not null unique,
        -> name char(16)
        -> );
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> desc t15;
    +-------+----------+------+-----+---------+-------+
    | Field | Type     | Null | Key | Default | Extra |
    +-------+----------+------+-----+---------+-------+
    | id    | int(11)  | NO   | PRI | NULL    |       |
    | name  | char(16) | YES  |     | NULL    |       |
    +-------+----------+------+-----+---------+-------+
    rows in set (0.02 sec)

    复合主键:

    create table t16(
        ip char(15),
        port int,
        primary key(ip,port)
    );
    
    insert into t16 values
    ('1.1.1.2',80),
    ('1.1.1.2',81);

    5. auto_increment

      让约束的字段为自动增长,约束的字段必须同时被key约束

    # 不指定id,则自动增长
    
    # 创建student
    create table student(
    id int primary key auto_increment,
    name varchar(20),
    sex enum('male','female') default 'male'
    );
    
    mysql>  desc student;
    +-------+-----------------------+------+-----+---------+----------------+
    | Field | Type                  | Null | Key | Default | Extra          |
    +-------+-----------------------+------+-----+---------+----------------+
    | id    | int(11)               | NO   | PRI | NULL    | auto_increment |
    | name  | varchar(20)           | YES  |     | NULL    |                |
    | sex   | enum('male','female') | YES  |     | male    |                |
    +-------+-----------------------+------+-----+---------+----------------+
    rows in set (0.17 sec)
    
    #插入记录
    mysql>  insert into student(name) values ('老白'),('小白');
    Query OK, 2 rows affected (0.01 sec)
    Records: 2  Duplicates: 0  Warnings: 0
    
    mysql> select * from student;
    +----+--------+------+
    | id | name   | sex  |
    +----+--------+------+
    |  1 | 老白    | male |
    |  2 | 小白    | male |
    +----+--------+------+
    rows in set (0.00 sec)

      也可以指定id

    mysql> insert into student values(4,'asb','female');
    Query OK, 1 row affected (0.00 sec)
    
    mysql> insert into student values(7,'wsb','female');
    Query OK, 1 row affected (0.01 sec)
    
    mysql> select * from student;
    +----+--------+--------+
    | id | name   | sex    |
    +----+--------+--------+
    |  1 | 老白    | male   |
    |  2 | 小白    | male   |
    |  4 | asb    | female |
    |  7 | wsb    | female |
    +----+--------+--------+
    rows in set (0.00 sec)
    
    # 再次插入一条不指定id的记录,会在之前的最后一条记录继续增长
    mysql>  insert into student(name) values ('大白');
    Query OK, 1 row affected (0.00 sec)
    
    mysql> select * from student;
    +----+--------+--------+
    | id | name   | sex    |
    +----+--------+--------+
    |  1 | 老白    | male   |
    |  2 | 小白    | male   |
    |  4 | asb    | female |
    |  7 | wsb    | female |
    |  8 | 大白    | male   |
    +----+--------+--------+
    rows in set (0.00 sec)

    对于自增的字段,在用delete删除后,再插入值,该字段仍按照删除前的位置继续增长

    mysql> delete from student;
    Query OK, 5 rows affected (0.00 sec)
    
    mysql> select * from student;
    Empty set (0.00 sec)
    
    mysql> select * from student;
    Empty set (0.00 sec)
    
    mysql> insert into student(name) values('ysb');
    Query OK, 1 row affected (0.01 sec)
    
    mysql> select * from student;
    +----+------+------+
    | id | name | sex  |
    +----+------+------+
    |  9 | ysb  | male |
    +----+------+------+
    row in set (0.00 sec)
    
    #应该用truncate清空表,比起delete一条一条地删除记录,truncate是直接清空表,在删除大表时用它
    mysql> truncate student;
    Query OK, 0 rows affected (0.03 sec)
    
    mysql>  insert into student(name) values('xiaobai');
    Query OK, 1 row affected (0.00 sec)
    
    mysql> select * from student;
    +----+---------+------+
    | id | name    | sex  |
    +----+---------+------+
    |  1 | xiaobai | male |
    +----+---------+------+
    row in set (0.00 sec)
    
    mysql>

      清空表区分delete和truncate的区别:

        delete from t1,      如果有自增id,新增的数据,仍然是以删除前的最后一样作为起始.

        truncate table t1,  数据量大,删除速度比上一条快,且直接从零开始.

    6. foreign key

      一个表中的 FOREIGN KEY 指向另一个表中的 PRIMARY KEY.

    employee表

    idnameagedep_id
      1    a    19        2
      2   b    23        1
      3   c    27        2
    4   d    24    3

    department 表

      id  Address
       1     技术部
       2     销售部
       3     财务部

    注意: 

      1) 先建主表(独立的表),即department表,再建被关联表(也叫从表,有外键),即employee表.

      2) 在建关联表时,要加入一下sql语句:

        on delete cascade      同步删除
        on update cascade     同步更新

    create table employee(
        id int primary key,
        name varchar(20) not null,
        age int not null,
        dep_id int,
        constraint fk_dep foreign key(dep_id) references dep(id)  # 建立外键, fk_dep是我们起的外键名
        on delete cascade # 同步删除
        on update cascade # 同步更新
    );

    六. 单表查询

    一、单表查询的语法
       SELECT 字段1,字段2... FROM 表名
                      WHERE 条件
                      GROUP BY field
                      HAVING 筛选
                      ORDER BY field
                      LIMIT 限制条数
    二、关键字的执行优先级(重点)
    
    重点中的重点:关键字的执行优先级
    from
    where
    group by
    having
    select
    distinct
    order by
    limit
    
    1.找到表:from
    
    2.拿着where指定的约束条件,去文件/表中取出一条条记录
    
    3.将取出的一条条记录进行分组group by,如果没有group by,则整体作为一组
    
    4.将分组的结果进行having过滤
    
    5.执行select
    
    6.去重
    
    7.将结果按条件排序:order by
    
    8.限制结果的显示条数

      公司员工表,表的字段和数据类型如下

    company.employee
        员工id          id                          int                  
        姓名            name                        varchar                                                             
        性别            sex                         enum                                                                  
        年龄            age                         int
        入职日期         hire_date                   date
        岗位            post                        varchar
        职位描述         post_comment             varchar
        薪水            salary                    double
        办公室           office                     int
        部门编号         depart_id                   int

      sql语句建公司员工表,并插入记录

    #创建表,设置字段的约束条件
    create table employee(
        id int primary key auto_increment,
        name  varchar(20) not null,
        sex enum('male','female') not null default 'male', #大部分是男的
        age int(3) unsigned not null default 28,
        hire_date date not null,
        post varchar(50),
        post_comment varchar(100),
        salary  double(15,2),
        office int,# 一个部门一个屋
        depart_id int
    );
    # 查看表结构
    mysql> desc employee;
    +--------------+-----------------------+------+-----+---------+----------------+
    | Field        | Type                  | Null | Key | Default | Extra          |
    +--------------+-----------------------+------+-----+---------+----------------+
    | id           | int(11)               | NO   | PRI  | NULL    | auto_increment|
    | emp_name     | varchar(20)           | NO   |      | NULL    |               |
    | sex          | enum('male','female') | NO   |      | male    |               |
    | age          | int(3) unsigned       | NO   |      | 28      |               |
    | hire_date    | date                  | NO   |      | NULL    |               |
    | post         | varchar(50)           | YES  |      | NULL    |               |
    | post_comment | varchar(100)          | YES  |      | NULL    |               |
    | salary       | double(15,2)          | YES  |      | NULL    |               |
    | office       | int(11)               | YES  |      | NULL    |               |
    | depart_id    | int(11)               | YES  |      | NULL    |               |
    +--------------+-----------------------+------+-----+---------+----------------+
    rows in set (0.08 sec)
    
    #插入记录
    #三个部门:教学,销售,运营
    insert into employee(name ,sex,age,hire_date,post,salary,office,depart_id) values
    ('jack','male',18,'20170301','办事处',7300.33,401,1), #以下是教学部
    ('tom','male',78,'20150302','teacher',1000000.31,401,1),
    ('wusir','male',81,'20130305','teacher',8300,401,1),
    ('ben','male',73,'20140701','teacher',3500,401,1),
    ('nezha','male',28,'20121101','teacher',2100,401,1),
    ('steve','female',18,'20110211','teacher',9000,401,1),
    ('jerry','male',18,'19000301','teacher',30000,401,1),
    ('xiaomage','male',48,'20101111','teacher',10000,401,1),
    
    ('歪歪','female',48,'20150311','sale',3000.13,402,2),#以下是销售部门
    ('丫丫','female',38,'20101101','sale',2000.35,402,2),
    ('丁丁','female',18,'20110312','sale',1000.37,402,2),
    ('星星','female',18,'20160513','sale',3000.29,402,2),
    ('格格','female',28,'20170127','sale',4000.33,402,2),
    
    ('a','male',28,'20160311','operation',10000.13,403,3), #以下是运营部门
    ('b','male',18,'19970312','operation',20000,403,3),
    ('c','female',18,'20130311','operation',19000,403,3),
    ('d','male',18,'20150411','operation',18000,403,3),
    ('e','female',18,'20140512','operation',17000,403,3)
    ;

      (1) where 约束

    where子句中可以使用
    1.比较运算符:><>=<=<>!=
    2.between 80 and 100 :值在80到100之间
    3.in(80,90,100)值是10或20或30
    4.like 'xiaomagepattern': pattern可以是%或者_。%小时任意多字符,_表示一个字符
    5.逻辑运算符:在多个条件直接可以使用逻辑运算符 and or not
    #1 :单条件查询
    mysql> select id,emp_name from employee where id > 5;
    +----+------------+
    | id | emp_name   |
    +----+------------+
    |  6 | steve    |
    |  7 | jerry      |
    |  8 | xiaomage   |
    |  9 | 歪歪       
    | 10 | 丫丫        
    | 11 | 丁丁      
    | 12 | 星星      
    | 13 | 格格       
    | 14 | a         
    | 15 | b         
    | 16 | c         
    | 17 | d         
    | 18 | e         
    
    #2 多条件查询
    mysql> select emp_name from employee where post='teacher' and salary>10000;
    +----------+
    | emp_name |
    +----------+
    | tom    |
    | jerry    |
    +----------+
    
    #3.关键字BETWEEN AND
     SELECT name,salary FROM employee 
            WHERE salary BETWEEN 10000 AND 20000;
    
     SELECT name,salary FROM employee 
            WHERE salary NOT BETWEEN 10000 AND 20000;
    
    #注意''是空字符串,不是null
     SELECT name,post_comment FROM employee WHERE post_comment='';
     ps:
            执行
            update employee set post_comment='' where id=2;
            再用上条查看,就会有结果了
    #5:关键字IN集合查询
    mysql>  SELECT name,salary FROM employee WHERE salary=3000 OR salary=3500 OR salary=4000 OR salary=9000 ;
    +------------+---------+
    | name       | salary  |
    +------------+---------+
    | ben        | 3500.00 |
    | steve    | 9000.00 |
    +------------+---------+
    rows in set (0.00 sec)
    
    mysql>  SELECT name,salary FROM employee  WHERE salary IN (3000,3500,4000,9000) ;
    +------------+---------+
    | name       | salary  |
    +------------+---------+
    | ben        | 3500.00 |
    | steve      | 9000.00 |
    +------------+---------+
    mysql>  SELECT name,salary FROM employee  WHERE salary NOT IN (3000,3500,4000,9000) ;
    +-----------+------------+
    | name      | salary     |
    +-----------+------------+
    | jack      |    7300.33 |
    | tom       | 1000000.31 |
    | wusir     |    8300.00 |
    | nezha     |    2100.00 |
    | jerry     |   30000.00 |
    | xiaomage  |   10000.00 |
    | 歪歪       |    3000.13 |
    | 丫丫       |    2000.35 |
    | 丁丁       |    1000.37 |
    | 星星       |    3000.29 |
    | 格格       |    4000.33 |
    | a        |   10000.13 |
    | b         |   20000.00 |
    | c         |   19000.00 |
    | d         |   18000.00 |
    | e         |   17000.00 |
    +-----------+------------+
    rows in set (0.00 sec)
    
    #6:关键字LIKE模糊查询
    通配符’%’
    mysql> SELECT * FROM employee WHERE name LIKE 'jin%';
    +----+------------+--------+-----+------------+---------+--------------+----------+--------+-----------+
    | id | name       | sex    | age | hire_date  | post    | post_comment | salary   | office | depart_id |
    +----+------------+--------+-----+------------+---------+--------------+----------+--------+-----------+
    |  6 | steve     | female |  18 | 2011-02-11 | teacher | NULL         |  9000.00 |    401 |         1 |
    |  7 | jerry      | male   |  18 | 1900-03-01 | teacher | NULL         | 30000.00 |    401 |         1 |
    +----+------------+--------+-----+------------+---------+--------------+----------+--------+-----------+
    rows in set (0.00 sec)
    
    
    通配符'_'
    
    mysql> SELECT  age FROM employee WHERE name LIKE 'to_';
    +-----+
    | age |
    +-----+
    |  78 |
    +-----+
    row in set (0.00 sec)
    
    练习:
    1. 查看岗位是teacher的员工姓名、年龄
    2. 查看岗位是teacher且年龄大于30岁的员工姓名、年龄
    3. 查看岗位是teacher且薪资在9000-1000范围内的员工姓名、年龄、薪资
    4. 查看岗位描述不为NULL的员工信息
    5. 查看岗位是teacher且薪资是10000或9000或30000的员工姓名、年龄、薪资
    6. 查看岗位是teacher且薪资不是10000或9000或30000的员工姓名、年龄、薪资
    7. 查看岗位是teacher且名字是jin开头的员工姓名、年薪
    
    #对应的sql语句
    select name,age from employee where post = 'teacher';
    select name,age from employee where post='teacher' and age > 30; 
    select name,age,salary from employee where post='teacher' and salary between 9000 and 10000;
    select * from employee where post_comment is not null;
    select name,age,salary from employee where post='teacher' and salary in (10000,9000,30000);
    select name,age,salary from employee where post='teacher' and salary not in (10000,9000,30000);
    select name,salary*12 from employee where post='teacher' and name like 'jin%';

      (2) group by 分组查询

    #1、首先明确一点:分组发生在where之后,即分组是基于where之后得到的记录而进行的
    
    #2、分组指的是:将所有记录按照某个相同字段进行归类,比如针对员工信息表的职位分组,或者按照性别进行分组等
    
    #3、为何要分组呢?
        取每个部门的最高工资
        取每个部门的员工数
        取男人数和女人数
    
    小窍门:‘每’这个字后面的字段,就是我们分组的依据
    
    #4、大前提:
        可以按照任意字段分组,但是分组完毕后,比如group by post,只能查看post字段,如果想查看组内信息,需要借助于聚合函数
    mysql> select * from employee group by post;
    +----+--------+--------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
    | id | name   | sex    | age | hire_date  | post                                    | post_comment | salary     | office | depart_id |
    +----+--------+--------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
    | 14 | a      | male   |  28 | 2016-03-11 | operation                               | NULL         |   10000.13 |    403 |         3 |
    |  9 | 歪歪    | female |  48 | 2015-03-11 | sale                                  | NULL         |    3000.13 |    402 |         2 |
    |  2 | tom    | male   |  78 | 2015-03-02 | teacher                                 |              | 1000000.31 |    401 |         1 |
    |  1 | jack   | male   |  18 | 2017-03-01 | 办事处                             | NULL         |    7300.33 |    401 |         1 |
    +----+--------+--------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
    rows in set (0.00 sec)
    
    #由于没有设置ONLY_FULL_GROUP_BY,于是也可以有结果,默认都是组内的第一条记录,但其实这是没有意义的
    如果想分组,则必须要设置全局的sql的模式为ONLY_FULL_GROUP_BY
    mysql> set global sql_mode='ONLY_FULL_GROUP_BY';
    Query OK, 0 rows affected (0.00 sec)
    
    #查看MySQL 5.7默认的sql_mode如下:
    mysql> select @@global.sql_mode;
    +--------------------+
    | @@global.sql_mode  |
    +--------------------+
    | ONLY_FULL_GROUP_BY |
    +--------------------+
    row in set (0.00 sec)
    
    mysql> exit;#设置成功后,一定要退出,然后重新登录方可生效
    # group by分组之后,只能查看当前字段,如果想查看组内信息
    mysql> select * from emp group by post;# 报错
    ERROR 1054 (42S22): Unknown column 'post' in 'group statement'
    
    
    
    mysql>  select post from employee group by post;
    +-----------------------------------------+
    | post                                    |
    +-----------------------------------------+
    | operation                               |
    | sale                                    |
    | teacher                                 |
    | 办事处              |
    +-----------------------------------------+
    rows in set (0.00 sec)

      (3) 聚合函数

      group by分组之后,只能查看当前字段,如果想查看组内信息,可以借助于聚合函数

    max()求最大值
    min()求最小值
    avg()求平均值
    sum() 求和
    count() 求总个数
    
    #强调:聚合函数聚合的是组的内容,若是没有分组,则默认一组
    # 每个部门有多少个员工
    select post,count(id) from employee group by post;
    # 每个部门的最高薪水
    select post,max(salary) from employee group by post;
    # 每个部门的最低薪水
    select post,min(salary) from employee group by post;
    # 每个部门的平均薪水
    select post,avg(salary) from employee group by post;
    # 每个部门的所有薪水
    select post,sum(age) from employee group by post;

      (4) having 过滤

    HAVING与WHERE不一样的地方在于
    
    #!!!执行优先级从高到低:where > group by > having 
    #1. Where 发生在分组group by之前,因而Where中可以有任意字段,但是绝对不能使用聚合函数。
    
    #2. Having发生在分组group by之后,因而Having中可以使用分组的字段,无法直接取到其他字段,可以使用聚合函数
    mysql> select * from employee where salary>1000000;
    +----+------+------+-----+------------+---------+--------------+------------+--------+-----------+
    | id | name | sex  | age | hire_date  | post    | post_comment | salary     | office | depart_id |
    +----+------+------+-----+------------+---------+--------------+------------+--------+-----------+
    |  2 | tom  | male |  78 | 2015-03-02 | teacher |              | 1000000.31 |    401 |         1 |
    +----+------+------+-----+------------+---------+--------------+------------+--------+-----------+
    row in set (0.00 sec)
    
    mysql> select post,group_concat(name) from emp group by post having salary > 10000; ##错误,分组后无法直接取到salary字段
    ERROR 1054 (42S22): Unknown column 'post' in 'field list'

      (5) order by 查询顺序

    按单列排序
        SELECT * FROM employee ORDER BY age;
        SELECT * FROM employee ORDER BY age ASC;
        SELECT * FROM employee ORDER BY age DESC;
    按多列排序:先按照age升序排序,如果年纪相同,则按照id降序
        SELECT * from employee
            ORDER BY age ASC,
            id DESC;
    验证多列排序:
    SELECT * from employee ORDER BY age ASC,id DESC;
    mysql> SELECT * from employee ORDER BY age ASC,id DESC;
    +----+------------+--------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
    | id | name       | sex    | age | hire_date  | post                                    | post_comment | salary     | office | depart_id |
    +----+------------+--------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
    | 18 | d         | female |  18 | 2014-05-12 | operation                                | NULL        |   17000.00 |    403 |        3 |
    | 17 | c        | male   |  18 | 2015-04-11 | operation                                | NULL        |   18000.00 |    403 |        3  |
    | 16 | b        | female |  18 | 2013-03-11 | operation                                | NULL        |   19000.00 |    403 |        3  |
    | 15 | a        | male   |  18 | 1997-03-12 | operation                                | NULL        |   20000.00 |    403 |        3  |
    | 12 | 星星        | female |  18 | 2016-05-13 | sale                                     | NULL        |    3000.29 |    402 |        2  |
    | 11 | 丁丁        | female |  18 | 2011-03-12 | sale                                     | NULL        |    1000.37 |    402 |        2  |
    |  7 | jerry      | male   |  18 | 1900-03-01 | teacher                                 | NULL         |   30000.00 |    401 |         1 |
    |  6 | steve      | female |  18 | 2011-02-11 | teacher                                 | NULL         |    9000.00 |    401 |         1 |
    |  1 | jack       | male   |  18 | 2017-03-01 | 办事处                          | NULL          |    7300.33|    401 |         1  |
    | 14 | a          | male   |  28 | 2016-03-11 | operation                                | NULL        |   10000.13 |    403 |        3  |
    | 13 | 格格        | female |  28 | 2017-01-27 | sale                                     | NULL        |    4000.33 |    402 |        2  |
    |  5 | nezha      | male   |  28 | 2012-11-01 | teacher                                 | NULL         |    2100.00 |    401 |         1 |
    | 10 | 丫丫        | female |  38 | 2010-11-01 | sale                                     | NULL        |    2000.35 |    402 |        2  |
    |  9 | 歪歪        | female |  48 | 2015-03-11 | sale                                     | NULL        |    3000.13 |    402 |        2  |
    |  8 | xiaomage   | male   |  48 | 2010-11-11 | teacher                                 | NULL         |   10000.00 |    401 |         1 |
    |  4 | ben        | male   |  73 | 2014-07-01 | teacher                                 | NULL         |    3500.00 |    401 |         1 |
    |  2 | tom        | male   |  78 | 2015-03-02 | teacher                                 |              | 1000000.31 |    401 |         1 |
    |  3 | wusir      | male   |  81 | 2013-03-05 | teacher                                 | NULL         |    8300.00 |    401 |         1 |
    +----+------------+--------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
    rows in set (0.01 sec)
    
    mysql>

      (6) limit 限制查询的记录数

    示例:
        SELECT * FROM employee ORDER BY salary DESC 
         LIMIT 3;                    #默认初始位置为0 
    
        SELECT * FROM employee ORDER BY salary DESC
            LIMIT 0,5; #从第0开始,即先查询出第一条,然后包含这一条在内往后查5条
    
        SELECT * FROM employee ORDER BY salary DESC
            LIMIT 5,5; #从第5开始,即先查询出第6条,然后包含这一条在内往后查5条
    # 第1页数据
      mysql> select * from  employee limit 0,5;
    +----+-----------+------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
    | id | name      | sex  | age | hire_date  | post                                    | post_comment | salary     | office | depart_id |
    +----+-----------+------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
    |  1 | jack      | male |  18 | 2017-03-01 | 河办事                          | NULL         |    7300.33 |    401 |         1 |
    |  2 | tom       | male |  78 | 2015-03-02 | teacher                                 |              | 1000000.31 |    401 |         1 |
    |  3 | wusir i   | male |  81 | 2013-03-05 | teacher                                 | NULL         |    8300.00 |    401 |         1 |
    |  4 | ben       | male |  73 | 2014-07-01 | teacher                                 | NULL         |    3500.00 |    401 |         1 |
    |  5 | nezha     | male |  28 | 2012-11-01 | teacher                                 | NULL         |    2100.00 |    401 |         1 |
    +----+-----------+------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
    rows in set (0.00 sec)
    # 第2页数据
    mysql> select * from  employee limit 5,5;
    +----+------------+--------+-----+------------+---------+--------------+----------+--------+-----------+
    | id | name       | sex    | age | hire_date  | post    | post_comment | salary   | office | depart_id |
    +----+------------+--------+-----+------------+---------+--------------+----------+--------+-----------+
    |  6 | steve      | female |  18 | 2011-02-11 | teacher | NULL         |  9000.00 |    401 |         1 |
    |  7 | jerry      | male   |  18 | 1900-03-01 | teacher | NULL         | 30000.00 |    401 |         1 |
    |  8 | xiaomage   | male   |  48 | 2010-11-11 | teacher | NULL         | 10000.00 |    401 |         1 |
    |  9 | 歪歪       | female |  48 | 2015-03-11 | sale    | NULL         |  3000.13 |    402 |         2 |
    | 10 | 丫丫       | female |  38 | 2010-11-01 | sale    | NULL         |  2000.35 |    402 |         2 |
    +----+------------+--------+-----+------------+---------+--------------+----------+--------+-----------+
    rows in set (0.00 sec)
    # 第3页数据
    mysql> select * from  employee limit 10,5;
    +----+-----------+--------+-----+------------+-----------+--------------+----------+--------+-----------+
    | id | name      | sex    | age | hire_date  | post      | post_comment | salary   | office | depart_id |
    +----+-----------+--------+-----+------------+-----------+--------------+----------+--------+-----------+
    | 11 | 丁丁      | female |  18 | 2011-03-12 | sale      | NULL         |  1000.37 |    402 |         2 |
    | 12 | 星星      | female |  18 | 2016-05-13 | sale      | NULL         |  3000.29 |    402 |         2 |
    | 13 | 格格      | female |  28 | 2017-01-27 | sale      | NULL         |  4000.33 |    402 |         2 |
    | 14 | a        | male   |  28 | 2016-03-11 | operation | NULL         | 10000.13 |    403 |         3 |
    | 15 | b       | male   |  18 | 1997-03-12 | operation | NULL         | 20000.00 |    403 |         3 |
    +----+-----------+--------+-----+------------+-----------+--------------+----------+--------+-----------+
    rows in set (0.00 sec)

    七. 多表查询

      准备两张表,部门表(department)、员工表(employee)

    create table department(
    id int,
    name varchar(20) 
    );
    
    create table employee(
    id int primary key auto_increment,
    name varchar(20),
    sex enum('male','female') not null default 'male',
    age int,
    dep_id int
    );
    
    #插入数据
    insert into department values
    (200,'技术'),
    (201,'人力资源'),
    (202,'销售'),
    (203,'运营');
    
    insert into employee(name,sex,age,dep_id) values
    ('egon','male',18,200),
    ('alex','female',48,201),
    ('wupeiqi','male',38,201),
    ('yuanhao','female',28,202),
    ('nvshen','male',18,200),
    ('xiaomage','female',18,204)
    ;
    
    # 查看表结构和数据
    mysql> desc department;
    +-------+-------------+------+-----+---------+-------+
    | Field | Type        | Null | Key | Default | Extra |
    +-------+-------------+------+-----+---------+-------+
    | id    | int(11)     | YES  |     | NULL    |       |
    | name  | varchar(20) | YES  |     | NULL    |       |
    +-------+-------------+------+-----+---------+-------+
    rows in set (0.19 sec)
    
    mysql> desc employee;
    +--------+-----------------------+------+-----+---------+----------------+
    | Field  | Type                  | Null | Key | Default | Extra          |
    +--------+-----------------------+------+-----+---------+----------------+
    | id     | int(11)               | NO   | PRI | NULL    | auto_increment |
    | name   | varchar(20)           | YES  |     | NULL    |                |
    | sex    | enum('male','female') | NO   |     | male    |                |
    | age    | int(11)               | YES  |     | NULL    |                |
    | dep_id | int(11)               | YES  |     | NULL    |                |
    +--------+-----------------------+------+-----+---------+----------------+
    rows in set (0.01 sec)
    
    mysql> select * from department;
    +------+--------------+
    | id   | name         |
    +------+--------------+
    |  200 | 技术         |
    |  201 | 人力资源     |
    |  202 | 销售         |
    |  203 | 运营         |
    +------+--------------+
    rows in set (0.02 sec)
    
    mysql> select * from employee;
    +----+----------+--------+------+--------+
    | id | name     | sex    | age  | dep_id |
    +----+----------+--------+------+--------+
    |  1 | a       | male   |   18 |    200 |
    |  2 | b        | female |   48 |    201 |
    |  3 | c        | male   |   38 |    201 |
    |  4 | d        | female |   28 |    202 |
    |  5 | e        | male   |   18 |    200 |
    |  6 | f        | female |   18 |    204 |
    +----+----------+--------+------+--------+
    rows in set (0.00 sec)

    1. 多表连接查询

      外链接语法:

    SELECT 字段列表
        FROM 表1 INNER|LEFT|RIGHT JOIN 表2
        ON 表1.字段 = 表2.字段;

      (1) 交叉连接

    mysql> select * from employee,department;
    +----+----------+--------+------+--------+------+--------------+
    | id | name     | sex    | age  | dep_id | id   | name         |
    +----+----------+--------+------+--------+------+--------------+
    |  1 | a       | male   |   18 |    200 |  200 | 技术         |
    |  1 | a     | male   |   18 |    200 |  201 | 人力资源      |
    |  1 | a      | male   |   18 |    200 |  202 | 销售         |
    |  1 | a      | male   |   18 |    200 |  203 | 运营         |
    |  2 | b      | female |   48 |    201 |  200 | 技术         |
    |  2 | b       | female |   48 |    201 |  201 | 人力资源      |
    |  2 | b     | female |   48 |    201 |  202 | 销售         |
    |  2 | b     | female |   48 |    201 |  203 | 运营         |
    |  3 | c     | male   |   38 |    201 |  200 | 技术         |
    |  3 | c      | male   |   38 |    201 |  201 | 人力资源      |
    |  3 | c      | male   |   38 |    201 |  202 | 销售         |
    |  3 | c      | male   |   38 |    201 |  203 | 运营         |
    |  4 | d       | female |   28 |    202 |  200 | 技术         |
    |  4 | d      | female |   28 |    202 |  201 | 人力资源      |
    |  4 | d      | female |   28 |    202 |  202 | 销售         |
    |  4 | d      | female |   28 |    202 |  203 | 运营         |
    |  5 | e      | male   |   18 |    200 |  200 | 技术         |
    |  5 | e       | male   |   18 |    200 |  201 | 人力资源      |
    |  5 | e     | male   |   18 |    200 |  202 | 销售         |
    |  5 | e      | male   |   18 |    200 |  203 | 运营         |
    |  6 | f      | female |   18 |    204 |  200 | 技术         |
    |  6 | f      | female |   18 |    204 |  201 | 人力资源      |
    |  6 | f      | female |   18 |    204 |  202 | 销售         |
    |  6 | f     | female |   18 |    204 |  203 | 运营         |

    (2) 内连接:只连接匹配的行

    #找两张表共有的部分,相当于利用条件从笛卡尔积结果中筛选出了匹配的结果
    #department没有204这个部门,因而employee表中关于204这条员工信息没有匹配出来
    mysql> select employee.id,employee.name,employee.age,employee.sex,department.name from employee inner join department on employee.dep_id=department.id;
    +----+---------+------+--------+--------------+
    | id | name    | age  | sex    | name         |
    +----+---------+------+--------+--------------+
    |  1 | a       |   18 | male   | 技术         |
    |  2 | b       |   48 | female | 人力资源     |
    |  3 | c       |   38 | male   | 人力资源     |
    |  4 | d       |   28 | female | 销售         |
    |  5 | e       |   18 | male   | 技术         |
    +----+---------+------+--------+--------------+
    rows in set (0.00 sec)
    
    #上述sql等同于
    mysql> select employee.id,employee.name,employee.age,employee.sex,department.name from employee,department where employee.dep_id=department.id;

    (3) 外链接之左连接:优先显示左表全部记录

    #以左表为准,即找出所有员工信息,当然包括没有部门的员工
    #本质就是:在内连接的基础上增加左边有,右边没有的结果
    mysql> select employee.id,employee.name,department.name as depart_name from employee left join department on employee.dep_id=department.id;
    +----+----------+--------------+
    | id | name     | depart_name  |
    +----+----------+--------------+
    |  1 | a        | 技术         |
    |  5 | e        | 技术         |
    |  2 | b        | 人力资源     |
    |  3 | c        | 人力资源     |
    |  4 | d        | 销售         |
    |  6 | f        | NULL         |
    +----+----------+--------------+
    rows in set (0.00 sec)

    (4) 外链接之左连接:优先显示左表全部记录

    #以右表为准,即找出所有部门信息,包括没有员工的部门
    #本质就是:在内连接的基础上增加右边有,左边没有的结果
    mysql> select employee.id,employee.name,department.name as depart_name from employee right join department on employee.dep_id=department.id;
    +------+---------+--------------+
    | id   | name    | depart_name  |
    +------+---------+--------------+
    |    1 | a       | 技术         |
    |    2 | b       | 人力资源     |
    |    3 | c       | 人力资源     |
    |    4 | d       | 销售         |
    |    5 | e       | 技术         |
    | NULL | NULL    | 运营         |
    +------+---------+--------------+
    rows in set (0.00 sec)

    (5) 全外连接:显示左右两个表全部记录

    #外连接:在内连接的基础上增加左边有右边没有的和右边有左边没有的结果
    #注意:mysql不支持全外连接 full JOIN
    #强调:mysql可以使用此种方式间接实现全外连接
    语法:select * from employee left join department on employee.dep_id = department.id 
           union all
          select * from employee right join department on employee.dep_id = department.id;
    
     mysql> select * from employee left join department on employee.dep_id = department.id
              union
            select * from employee right join department on employee.dep_id = department.id
               ;
    +------+----------+--------+------+--------+------+--------------+
    | id   | name     | sex    | age  | dep_id | id   | name         |
    +------+----------+--------+------+--------+------+--------------+
    |    1 | a        | male   |   18 |    200 |  200 | 技术         |
    |    5 | b        | male   |   18 |    200 |  200 | 技术         |
    |    2 | c        | female |   48 |    201 |  201 | 人力资源     |
    |    3 | d        | male   |   38 |    201 |  201 | 人力资源     |
    |    4 | e        | female |   28 |    202 |  202 | 销售         |
    |    6 | f        | female |   18 |    204 | NULL | NULL         |
    | NULL | NULL     | NULL   | NULL |   NULL |  203 | 运营         |
    +------+----------+--------+------+--------+------+--------------+
    rows in set (0.01 sec)
    
    #注意 union与union all的区别:union会去掉相同的纪录

    2.子查询

    #1:子查询是将一个查询语句嵌套在另一个查询语句中。
    #2:内层查询语句的查询结果,可以为外层查询语句提供查询条件。
    #3:子查询中可以包含:IN、NOT IN、ANY、ALL、EXISTS 和 NOT EXISTS等关键字
    #4:还可以包含比较运算符:= 、 !=、> 、<等

      (1) 带 in 关键字的子查询

    #查询平均年龄在25岁以上的部门名
    select id,name from department
        where id in 
            (select dep_id from employee group by dep_id having avg(age) > 25);
    # 查看技术部员工姓名
    select name from employee
        where dep_id in 
            (select id from department where name='技术');
    #查看不足1人的部门名
    select name from department
        where id not in 
            (select dep_id from employee group by dep_id);

      (2) 带比较运算符的子查询

    #比较运算符:=、!=、>、>=、<、<=、<>
    #查询大于所有人平均年龄的员工名与年龄
    mysql> select name,age from employee where age > (select avg(age) from employee);
    +---------+------+
    | name    | age  |
    +---------+------+
    | a       |   48 |
    | c       |   38 |
    +---------+------+
    
    #查询大于部门内平均年龄的员工名、年龄
    思路:
          (1)先对员工表(employee)中的人员分组(group by),查询出dep_id以及平均年龄。
           (2)将查出的结果作为临时表,再对根据临时表的dep_id和employee的dep_id作为筛选条件将employee表和临时表进行内连接。
           (3)最后再将employee员工的年龄是大于平均年龄的员工名字和年龄筛选。
    
    
    
    mysql> select t1.name,t1.age from employee as t1
                 inner join
                (select dep_id,avg(age) as avg_age from employee group by dep_id) as t2
                on t1.dep_id = t2.dep_id
                where t1.age > t2.avg_age;
    +------+------+
    | name | age  |
    +------+------+
    | b    |   48 |

      (3) 带EXISTS关键字的子查询

    #EXISTS关字键字表示存在。在使用EXISTS关键字时,内层查询语句不返回查询的记录。而是返回一个真假值。True或False
    #当返回True时,外层查询语句将进行查询;当返回值为False时,外层查询语句不进行查询
    #department表中存在dept_id=203,Ture
    mysql> select * from employee  where exists (select id from department where id=200);
    +----+----------+--------+------+--------+
    | id | name     | sex    | age  | dep_id |
    +----+----------+--------+------+--------+
    |  1 | a        | male   |   18 |    200 |
    |  2 | b        | female |   48 |    201 |
    |  3 | c        | male   |   38 |    201 |
    |  4 | d        | female |   28 |    202 |
    |  5 | e        | male   |   18 |    200 |
    |  6 | f        | female |   18 |    204 |
    +----+----------+--------+------+--------+
    #department表中存在dept_id=205,False
    mysql> select * from employee  where exists (select id from department where id=204);
    Empty set (0.00 sec)

    八. 索引

    1. 索引

      数据库中专门用于帮助用户快速查找数据的一种数据结构. 类似于字典中的目录, 查找字典内容时可以根据目录查找到数据的存放位置, 然后直接获取. 索引的作用是约束和查找.

      (1) 建索引的目的:

    a.额外的文件保存特殊的数据结构
    b.查询快,但是插入更新删除依然慢
    c.创建索引之后,必须命中索引才能有效

      (2) 索引的种类

    hash索引和BTree索引
    (1)hash类型的索引:查询单条快,范围查询慢
    (2)btree类型的索引:b+树,层数越多,数据量指数级增长(我们就用它,因为innodb默认支持它)

    2. 常见的索引

    - 普通索引
    - 唯一索引
    - 主键索引
    - 联合索引(多列)
       - 联合主键索引 
      - 联合唯一索引   
       - 联合普通索引
    

    3. 普通索引 

      作用:仅有一个加速查找 

    创建表
    create table userinfo(
                       nid int not null auto_increment primary key,
                       name varchar(32) not null,
                       email varchar(64) not null,
                       index ix_name(name)  # 创建普通索引
                   );
    
    创建普通索引
    create index 索引的名字 on 表名(列名)
    删除索引
    drop index 索引的名字 on 表名
    查看索引
    show index from 表名

    4. 唯一索引

      唯一索引有两个功能:加速查找和唯一约束(可含null)

    创建表+唯一索引
    create table userinfo(
                       id int not null auto_increment primary key,
                       name varchar(32) not null,
                       email varchar(64) not null,
                       unique  index  ix_name(name)
                   );
    创建唯一索引
    create unique index 索引名 on 表名(列名)
    删除唯一索引
    drop index 索引名 on 表名;

    5. 主键索引

      主键索引有两个功能: 加速查找和唯一约束(不含null)

    3 创建表+主键索引
    create table userinfo(
    
                       id int not null auto_increment primary key,
                       name varchar(32) not null,
                       email varchar(64) not null,
                       unique  index  ix_name(name)
               )
              or
    
               create table userinfo(
    
                       id int not null auto_increment,
                       name varchar(32) not null,
                       email varchar(64) not null,
                       primary key(nid),
                       unique  index  ix_name(name)
             )
    
    创建主键索引
    alter table 表名 add primary key(列名);
    删除主键索引
    alter table 表名 drop primary key;
    alter table 表名  modify  列名 int, drop primary key;

    6. 组合索引

      组合索引是将n个列组合成一个索引, 其应用场景为:频繁的同时使用n列来进行查询,

    创建组合索引
    create index 索引名 on 表名(列名1,列名2);

    7. 索引的注意事项

    (1)避免使用select *
    (2)count(1)或count(列) 代替count(*)
    (3)创建表时尽量使用char代替varchar
    (4)表的字段顺序固定长度的字段优先
    (5)组合索引代替多个单列索引(经常使用多个条件查询时)
    (6)尽量使用短索引 (create index ix_title on tb(title(16));特殊的数据类型 text类型)
    (7)使用连接(join)来代替子查询
    (8)连表时注意条件类型需一致
    (9)索引散列(重复少)不适用于建索引,例如:性别不合适
  • 相关阅读:
    WinCE数据库开发时整出来的一个致命的BUG
    WinCE下读取注册表获得SD卡路径
    Cookie的创建、读写和删除
    Http Module 介绍[转]
    贴几个从Dnt论坛代码里边扣出来的函数
    SqlServer判断数据库、表、存储过程、函数是否存在
    WinCE中C#WinForm利用Web Service查询数据库
    关于WinCE和PC中同一字符串的GetHashCode()结果不同的理解
    DataTable中数据记录的统计
    C#读取XML时自动过滤掉注释部分
  • 原文地址:https://www.cnblogs.com/huangqihui/p/9664552.html
Copyright © 2011-2022 走看看