MySQL约束和多表查询


约束

  概念: 对表中的数据进行限定,保证数据的正确性、有效性和完整性。

  分类: 1. 主键约束:primary key 2. 非空约束:not null 3. 唯一约束:unique 4. 外键约束:foreign key 

  • 非空约束:not null,值不能为null

    • 创建表时添加约束 
      CREATE TABLE stu1( id INT, NAME VARCHAR(20) NOT NULL -- name为非空 );
    • 删除name的非空约束
      ALTER TABLE stu1 MODIFY NAME VARCHAR(20);
    • 创建表完后,添加非空约束
      ALTER TABLE stu1 MODIFY NAME VARCHAR(20) NOT NULL;
  •  唯一约束:unique,值不能重复

    • 创建表时,添加唯一约束 
      CREATE TABLE stu2( 
          id INT, 
          phone_number VARCHAR(20) UNIQUE -- 添加了唯一约束
           ); 
          desc stu2; -- 显示表 
          show index from stu2; -- 显示所有的索引,唯一约束也是索引之一 

      注意:mysql中,唯一约束限定的列的值可以有多个null

    • 删除唯一约束   alter table 表名称 drop INDEX 索引名称; 
      alter table stu2 drop INDEX phone_number;
    • 在创建表后,添加唯一约束 
      ALTER TABLE stu2 MODIFY phone_number VARCHAR(20) UNIQUE;
  • 主键约束:primary key

    • 注意:
      • 非空且唯一
      • 一张表只能有一个字段为主键
      • 主键就是表中记录的唯一标识
    • 在创建表时,添加主键约束 
      create table stu3( 
          id int primary key,-- 给id添加主键约束 
          name varchar(20)
      );
    • 删除主键 
      ALTER TABLE stu3 DROP PRIMARY KEY;
    • 创建完表后,添加主键 
      ALTER TABLE stu3 MODIFY id INT PRIMARY KEY;
    • 自动增长:
      • 概念:如果某一列是数值类型的,使用 auto_increment 可以来完成值得自动增长
      • 在创建表时,添加主键约束,并且完成主键自增长 
        create table stu4(
            id int primary key auto_increment,-- 给id添加主键约束 
            name varchar(20)
        );  
  • 外键约束:foreign key

  让表于表产生关系,从而保证数据的正确性。

    • 在创建表时,可以添加外键 
      create table 表名( 
          .... 外键列 
          constraint 外键名称 foreign key (外键列名称) references 主表名称(主表 列名称) 
      );
    • 删除外键 
      ALTER TABLE 表名 DROP FOREIGN KEY 外键名称;
    • 创建表之后,添加外键
      ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段名称) REFERENCES 主表名称(主表列名称);

多表查询

  • 查询语法

    select
        列名列表
     from
        表名列表
    where....
  • 准备sql

    #创建部门表
    CREATE TABLE dept(
        id INT PRIMARY KEY AUTO_INCREMENT,
        name VARCHAR(20),
        location varchar(20)
    );
    INSERT INTO dept (NAME,location) VALUES 
    ('开发部','北京'),('市场部','上海'),('财务部','天津'); # 创建员工表 CREATE TABLE emp ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(10), -- 姓名 gender CHAR(1), -- 性别 salary DOUBLE, -- 工资 join_date DATE, -- 入职日期 dept_id INT -- 部门id ); INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES
    ('孙悟空','',7200,'2013-02-24',1),

    ('猪八戒','',3600,'2010-12-02',2),
    ('唐僧','',9000,'2008-08-08',2),
    ('白骨精','',5000,'2015-10-07',3),
    ('蜘蛛精','',4500,'2011-03-14',1),
    ('小白龙','',3000,null,null);
  • 笛卡尔积 

    • 有两个集合A,B .取这两个集合的所有组成情况
    • 要完成多表查询,需要消除无用的数据
  • 多表查询的分类

    • 1、内连接查询

      • 隐式内连接

      • 使用where条件消除无用数据
        -- 查询所有员工信息和对应的部门信息
        SELECT * FROM emp,dept WHERE emp.`dept_id` = dept.`id`;
        -- 查询员工表的名称,性别。部门表的名称
        SELECT emp.name,emp.gender,dept.name FROM emp,dept WHERE emp.`dept_id` = dept.`id`;
        SELECT
            t1.name, -- 员工表的姓名
            t1.gender,-- 员工表的性别
            t2.name -- 部门表的名称
        FROM
            emp t1,
            dept t2
        WHERE
            t1.`dept_id` = t2.`id`;
      • 显式内连接

      • select 字段列表 from 表名1 [inner] join 表名2 on 条件
        SELECT * FROM emp INNER JOIN dept ON emp.`dept_id` = dept.`id`;
        SELECT * FROM emp JOIN dept ON emp.`dept_id` = dept.`id`;
      • 内连接查询
        • 从哪些表中查询数据;条件是什么;查询哪些字段
    • 2、外链接查询

      • 左外连接

        • 语法:select 字段列表 from 表1 left [outer] join 表2 on 条件;
        • 查询的是左表所有数据以及其交集部分。
          -- 查询所有员工信息,如果员工有部门,则查询部门名称,没有部门,则不显示部门名称
          SELECT t1.*,t2.`name` FROM emp t1 LEFT JOIN dept t2 ON t1.`dept_id` = t2.`id`;
      • 右外连接

        • 语法:select 字段列表 from 表1 right [outer] join 表2 on 条件;
        • 查询的是右表所有数据以及其交集部分。
          SELECT * FROM dept t2 RIGHT JOIN emp t1 ON t1.`dept_id` = t2.`id`;
      • 子查询

        • 概念:查询中嵌套查询,称嵌套查询为子查询。
          -- 查询工资最高的员工信息
          -- 1 、查询最高的工资是多少 9000
          SELECT MAX(salary) FROM emp;
          -- 2、查询员工信息,并且工资等于9000的
          SELECT * FROM emp WHERE emp.`salary` = 9000;
          
          -- 子查询
          SELECT * FROM emp WHERE emp.`salary` = (SELECT MAX(salary) FROM emp);
        • 1. 子查询的结果是单行单列的
        • 子查询可以作为条件,使用运算符去判断。 运算符: > >= < <= =
          -- 查询员工工资小于平均工资的人
          SELECT * FROM emp WHERE emp.salary < (SELECT AVG(salary) FROM emp);
        • 2. 子查询的结果是多行单列的:
        • 子查询可以作为条件,使用运算符in来判断
          -- 查询'财务部'和'市场部'所有的员工信息
          SELECT id FROM dept WHERE NAME = '财务部' OR NAME = '市场部';
          SELECT * FROM emp WHERE dept_id = 3 OR dept_id = 2;
          -- 子查询
          SELECT * FROM emp WHERE dept_id IN (SELECT id FROM dept WHERE NAME = '财务部' OR NAME = '市场部');
        • 3. 子查询的结果是多行多列的:
        • 子查询可以作为一张虚拟表参与查询
          -- 查询员工入职日期是2011-11-11日之后的员工信息和部门信息
          -- 子查询
          SELECT * FROM dept t1 inner join (
              SELECT * FROM emp WHERE emp.`join_date` > '2011-11-11')
               t2 on t1.id = t2.dept_id;
          -- 普通内连接
          SELECT * FROM emp t1
          inner join dept t2 on t1.`dept_id` = t2.`id`
          WHERE t1.`join_date` > '2011-11-11'