zoukankan      html  css  js  c++  java
  • MySQL笔记整理

    MySql

    A. SQL语句

    数据库的基本操作

    -- 选择要操作的数据库
    -- world:数据库名
    use world;
    
    -- 显示已存在的数据库列表
    show databases;
    
    -- 显示指定数据库下的表的信息
    show tables;
    
    -- 显示指定表的列的信息
    -- world.country:数据库名.表名
    show columns from world.country;
    
    -- 显示指定表的索引信息
    -- world.country:数据库名.表名
    show index from world.country;
    
    -- 显示指定数据库下的表的详细信息
    -- world:数据库名
    show table status from world;
    
    -- 显示指定数据库下的表名称以字母'c'开头的表的详细信息
    -- world:数据库名
    show table status from world like 'c%';
    
    -- 显示数据库表的结构,如:字段名,字段类型等
    -- world.country:数据库名.表名
    describe world.country;
    
    -- 查看创建表的SQL语句
    -- demo.test:数据库名.表名
    show create table demo.test;
    
    -- 查看创建存储过程的SQL语句
    -- demo.test_proc:数据库名.存储过程名
    show create procedure demo.test_proc;
    
    -- 查看创建视图的SQL语句
    -- demo.test_view:数据库名.视图名
    show create view demo.test_view;
    
    -- 查看创建函数的SQL语句
    -- demo.test_fun:数据库名.函数名
    show create function demo.test_fun;
    
    -- 查看当前用户的数据库权限
    show grants;
    
    -- 查看指定用户的数据库权限
    -- admin@localhost:用户名@访问主机
    show grants for 'admin'@'localhost';        
    
    -- 查询数据库用户信息
    select * from mysql.user;
    
    -- 获取服务器版本信息
    SELECT VERSION();
    
    -- 获取当前数据库名 (或者返回空)
    SELECT DATABASE();
    
    -- 获取当前用户名
    SELECT USER();
    
    -- 获取服务器状态
    SHOW STATUS;
    
    -- 获取服务器配置变量
    SHOW VARIABLES;
    例如:
    -- 查询自增长值的步长,即每次增加多少,默认为1。
    show variables like '%auto_increment%';
    -- 设置自增长值每次增加的数值,会影响所有数据表。
    set auto_increment_increment=3;
    -- 设置自增长值的起始值,会影响所有数据表。
    set auto_increment_offset=100;
    
    -- mysql运行在安全模式下时,非主键条件下是无法执行update或者delete命令的
    -- 查看安全模式状态
    show variables like '%sql_safe_updates%';
    -- 设置安全模式为关闭
    set sql_safe_updates=off;
    
    -- 获取最近一次向具有identity属性(即自增列)的表插入数据时对应的自增列的值,@@identity是系统定义的全局变量。
    select @@identity;
    
    -- LAST_INSERT_ID函数将返回当前连接自增列最新的 insert or update 操作生成的第一个记录的ID。因为其基于Connection的,所以也是线程安全的。
    select LAST_INSERT_ID();
    

    DDL:数据定义

    a) 数据类型

    数值型

    类型 大小 范围(有符号) 范围(无符号) 用途
    TINYINT 1 字节 (-128,127) (0,255) 小整数值
    SMALLINT 2 字节 (-32 768,32 767) (0,65 535) 大整数值
    MEDIUMINT 3 字节 (-8 388 608,8 388 607) (0,16 777 215) 大整数值
    INT或INTEGER 4 字节 (-2 147 483 648,2 147 483 647) (0,4 294 967 295) 大整数值
    BIGINT 8 字节 (-9 233 372 036 854 775 808,9 223 372 036 854 775 807) (0,18 446 744 073 709 551 615) 极大整数值
    FLOAT 4 字节 (-3.402 823 466 E+38,-1.175 494 351 E-38),0,(1.175 494 351 E-38,3.402 823 466 351 E+38) 0,(1.175 494 351 E-38,3.402 823 466 E+38) 单精度 浮点数值
    DOUBLE 8 字节 (-1.797 693 134 862 315 7 E+308,-2.225 073 858 507 201 4 E-308),0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) 0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) 双精度 浮点数值

    字符串类型

    类型 大小 用途
    CHAR 0-255字节 定长字符串
    VARCHAR 0-65535 字节 变长字符串
    TINYBLOB 0-255字节 不超过 255 个字符的二进制字符串
    TINYTEXT 0-255字节 短文本字符串
    BLOB 0-65 535字节 二进制形式的长文本数据
    TEXT 0-65 535字节 长文本数据
    MEDIUMBLOB 0-16 777 215字节 二进制形式的中等长度文本数据
    MEDIUMTEXT 0-16 777 215字节 中等长度文本数据
    LONGBLOB 0-4 294 967 295字节 二进制形式的极大文本数据
    LONGTEXT 0-4 294 967 295字节 极大文本数据

    日和期时间类型

    类型 大小 范围 格式 用途
    DATE 3字节 1000-01-01/9999-12-31 YYYY-MM-DD 日期值
    TIME 3字节 '-838:59:59'/'838:59:59' HH:MM:SS 时间值或持续时间
    YEAR 1字节 1901/2155 YYYY 年份值
    DATETIME 8字节 1000-01-01 00:00:00/9999-12-31 23:59:59 YYYY-MM-DD HH:MM:SS 混合日期和时间值
    TIMESTAMP 4字节 1970-01-01 00:00:00/2038结束时间是第 2147483647 秒,北京时间 2038-1-19 11:14:07,格林尼治时间 2038年1月19日 凌晨 03:14:07 YYYYMMDD HHMMSS 混合日期和时间值,时间戳

    b) 创建、删除数据库和表

    -- 创建一个名为'test'的数据库
    create database test;
    
    -- 创建一个名为'test'的数据库,如果该数据库已存在则不创建,否则再创建
    -- 并指定默认字符集为'utf8',字符校对集为'utf8_general_ci'
    create database if not exists test default charset utf8 collate utf8_general_ci;
    
    -- 删除名为'test'的数据库
    drop database test;
    
    -- 查询所有数据库
    Show databases;
    
    -- 使用数据库
    Use 数据库名;
    
    -- 更新数据库:
    ALTER DATABASE  数据库名 CHARATER SET=UTF8;(修改数据库编码)
    
    -- 创建一个名为'Student'的数据表,如果该数据表已存在则不创建,否则再创建
    -- engine:指定数据库引擎为'InnoDB'
    -- auto_increment:指定自增列的起始值为1
    create table if not exists Student
    (
        ID        int        not null    auto_increment,        #自动增长列
        StuNo    varchar(32)     not null,
        StuName    varchar(8)        not null,
        StuSex        varchar(8)        null,
        StuBirthday        tinyint     null,
        CreateTime        datetime     null,
        primary key (ID)    #指定主键列
    )
    engine=InnoDB auto_increment=1 default charset=utf8 collate=utf8_general_ci;
    
    -- 删除数据表 student,该操作会删除所有数据包括表结构、视图、索引、约束等。
    drop table test.student;
    
    -- 删除数据表中的所有数据,该操作会删除表中所有的数据,但是会保留表结构、视图、索引、约束等。
    truncate table test.student;
    
    
    -- 创建一个临时表,临时表的创建与数据表的创建类似,只不过需要添加关键字 temporary。
    -- 临时表的作用域为当前会话,即当前连接可见,当断开当前连接时会自动销毁,当然也可以手动删除,删除方式与数据表一样。
    create temporary table Product
    (
        ProName     varchar(32)     not null,
        Price        decimal(10,3)    not null     default 0.000
    );
    
    -- 复制指定数据表的表结构到创建的新表。
    create table test.StudentBak like test.student;
    
    -- 复制指定数据表的表结构及所有数据到创建的新表。
    create table test.StudentBak select * from test.student;
    

    c) 表的操作

    -- 创建表:
    CREATE TABLE [IF EXISTS] 表名(列名 类型,列名 类型);
    
    -- 查看表结构:
    DESC 表名;
    
    -- 查看当前数据库所有的表:
    SHOW TABLES;
    
    -- 删除表:
    DROP TABLE 表名;
    
    -- 查看指定表的创建语句:
    SHOW CREATE TABLE 表名; (了解)
    
    -- 修改表:
    前缀:ALTER TABLE 表名
    
    -- 添加列:
    ALTER TABLE 表名 ADD (
      列名 列类型,
      列名 列类型,
      ...
    );
    
    -- 修改列类型(如果被修改的列已存在数据,那么新的类型可能会影响到已存在数据):
    ALTER TABLE 表名 MODIFY 列名 列类型;
    
    -- 修改列名:
    ALTER TABLE 表名 CHANGE 原列名 新列名 列类型;
    
    -- 删除列:
    ALTER TABLE 表名 DROP 列名;
    
    -- 修改表名称:
    ALTER TABLE 原表名 RENAME TO 新表名;
    
    -- 向指定数据表添加一列,默认添加到数据表字段的末尾。
    alter table test.student add column1 varchar(10) null;
    
    -- 向指定数据表添加一列,并设置默认值为:0
    alter table demo.chinesecharinfo add column IsUseful tinyint unsigned not null default 0;
    
    -- first关键字用于把添加的列设置为第一列。
    alter table test.student add column1 varchar(10) null first;
    
    -- after关键字用于把添加的列设置在指定列的后面,StuSex为指定列的列名。
    alter table test.student add column1 varchar(10) null after StuSex;
    
    -- 删除指定列名的列,当数据表仅剩一个字段时,无法进行删除。
    alter table test.student drop column1;
    
    -- 修改指定列的数据类型,并设置该列位于指定列名的列之后。
    alter table test.student modify column1 char(10) null after CreateTime;        -- 关键字column可省略
    alter table test.student modify column column1 char(10) null after CreateTime;
    
    -- 修改指定列的列名和数据类型,并设置该列位于指定列名的列之后。
    -- column1:为原列名
    -- column2:为新的列名
    alter table test.student change column1 column2 varchar(10) null after CreateTime;
    
    -- 修改指定列的默认值。
    alter table test.student alter column2 set default '123';
    
    -- 删除指定列的默认值。
    alter table test.student alter column2 drop default;
    
    -- 修改数据表的存储引擎。
    alter table test.student engine = myisam;
    alter table test.student engine = InnoDB;
    
    -- 修改数据表的自增长值的起始值。
    alter table test.student auto_increment=10;
    
    -- 重建自增长列,当删除数据过多,自增长列的值比较混乱时可以使用,但是重建时如果有新的数据插入,有可能会出现混乱。
    alter table test.student drop ID;
    alter table test.student add ID int not null auto_increment first;
    alter table test.student add primary key(ID);
    
    -- 修改数据表的表名称。
    alter table test.student rename to test.StudentBak;
    

    DML:数据管理

    a) 事务

    b) 插入数据

    INTERT INTO 表名(列名1,列名2, ...) VALUES(列值1, 列值2, ...);
    在表名后给出要插入的列名,其他没有指定的列等同与插入null值。所以插入记录总是插入一行,不可能是半行。
    在VALUES后给出列值,值的顺序和个数必须与前面指定的列对应
    
    INTERT INTO 表名 VALUES(列值1, 列值2)
    没有给出要插入的列,那么表示插入所有列。
    值的个数必须是该表列的个数。
    值的顺序,必须与表创建时给出的列的顺序相同。
    
    // 插入所有列
    在数据库中所有的字符串类型,必须使用单引,不能使用双引!
    日期类型也要使用单引!
    INSERT INTO stu(
    number, name, age, gender
    )
    VALUES(
    'ITCAST_0001', 'zhangSan', 28, 'male'
    );
    
    // 插入部分列,没有指定的列默认为NULL值
    INSERT INTO stu(
    number, name
    ) VAKLUES(
    'ITCAST_0002', 'liSi'
    )
    
    // 不给出插入列,那么默认为插入所有列!值的顺序要与创建表时列的顺序相同
    INSERT INTO stu VALUES(
    'ITCAST_0003', 'wangWu', 82, 'female'
    );
    
    -- 向数据表中插入数据
    insert into student(StuNo,StuName,StuSex,Stubirthday,CreateTime)
    select 'A001','小张','男',str_to_date('1988-06-09','%Y-%m-%d'),current_timestamp() union all 
    select 'A002','小红','女',str_to_date('1990-08-10','%Y-%m-%d'),current_timestamp() 
    
    -- 在插入重复的数据时,会直接跳过重复数据的插入。在有自增列或主键的数据表中不起作用,因为自增列和主键都具有唯一性。
    insert ignore into test.student(stuno,stuname,stusex,stubirthday,createtime)
    values ('A003','小鱼','女','1991-07-07',current_timestamp());
    
    

    c) 修改数据

    • UPDATE 表名 SET 列名1=列值1, 列名2=列值2, ... [WHERE 条件]
    • 条件(条件可选的):
      条件必须是一个boolean类型的值或表达式:
    UPDATE t_person SET gender='男', age=age+1 WHERE sid='1';
    运算符:=、!=、<>、>、<、>=、<=、BETWEEN...AND、IN(...)、IS NULL、NOT、OR、AND
    UPDATE stu SET name='xxx', age=102
    WHERE age >= 18 AND age <= 80
    WHERE age BETWEEN 18 AND 80
    WHERE name='zhangSan' OR name='liSi'
    WHERE name IN ('zhangSan', 'liSi')
    WHERE age IS NULL, 不能使用等号
    WHERE age IS NOT NULL
    

    d) 删除数据

    DELETE FROM 表名 [WHERE 条件];
    TRUNCATE TABLE 表名:TRUNCATE是DDL语句,它是先删除drop该表,再create该表,而且无法回滚!
    

    DCL:数据控制

    • 一个项目创建一个用户!一个项目对应的数据库只有一个!
    • 这个用户只能对这个数据库有权限,其他数据库你就操作不了了!

    a) root用户密码修改

    修改root用户的密码:
    /*登录mysql*/
    mysql -uroot -p123
    /*切换数据库*/
    use mysql
    /*修改root用户的密码*/
    update user set password=password('1234') where user='root';
    

    如果你忘记了root用户的密码,那么你就无法登录mysql,也就不能修改密码了。这时登录mysql就比较麻烦:
    打开一个窗口,执行:mysqld --skip-grant-tables;
    这时再开一个窗口来登录mysql:mysql -u root;
    然后使用上面相同的方式来修改root用户的密码。


    格式:mysqladmin -u用户名 -p旧密码 password 新密码
    1、给root加个密码ab12。
    首先在DOS下进入目录mysqlin,然后键入以下命令
    mysqladmin -u root -password ab12
    注:因为开始时root没有密码,所以-p旧密码一项就可以省略了。
    2、再将root的密码改为djg345。
    mysqladmin -u root -p ab12 password djg345

    b) 创建、删除用户及授权

    -- 创建用户
    CREATE USER 用户名@IP地址 IDENTIFIED BY '密码'; -- 用户只能在指定的IP地址上登录
    CREATE USER 用户名@'%' IDENTIFIED BY '密码'; -- 用户可以在任意IP地址上登录
    
    -- 创建一个新的用户,并设置登录密码
    -- test:用户名;localhost:本地主机访问(如果需要其他任意主机访问,请使用通配符'%');123456:用户密码;
    create user 'test'@'localhost' identified by '123456';
    
    -- 创建一个新的用户,不指定登录密码,即不需要登录密码
    create user 'test01'@'localhost';
    
    -- 查看指定用户的权限
    SHOW GRANTS FOR 用户名@IP地址
    
    -- 删除指定的用户
    drop user 'test01'@'localhost';
    
    -- 修改用户名
    -- test@localhost:要修改的用户名和访问主机
    -- test@%:修改为的用户名和访问主机
    rename user 'test'@'localhost' to 'test'@'%';
    
    -- 修改用户密码
    -- test@localhost:要修改的用户名和访问主机
    -- 123456:新的用户密码
    set password for 'test'@'localhost' = Password('123456');-- 授予指定用户'test'对于'world'数据库下'country'表的查询权限
    
    -- select:查询权限;world.country:数据库名.表名;'test'@'localhost':用户名@访问主机;
    grant select on world.country to 'test'@'localhost';
    -- 立即启用修改(默认再次登录才会生效)
    flush privileges;
    
    -- 撤销指定用户'test'对于'world'数据库下'country'表的查询权限
    -- select:查询权限;world.country:数据库名.表名;'test'@'localhost':用户名@访问主机;
    revoke select on world.country from 'test'@'localhost';
    -- 立即启用修改(默认再次登录才会生效)
    flush privileges;
    
    -- 授予指定用户'test'对于'world'数据库下所有表的查询、新增、修改、删除权限
    grant select,insert,update,delete on world.* to 'test'@'localhost';
    
    -- 撤销指定用户'test'对于'world'数据库下所有表的查询、新增、修改、删除权限
    revoke select,insert,update,delete on world.* from 'test'@'localhost';
    
    -- 授予指定用户'test'对于'world'数据库下所有表的表结构进行创建、修改、删除权限
    grant create,alter,drop on world.* to 'test'@'localhost';
    
    -- 撤销指定用户'test'对于'world'数据库下所有表的表结构进行创建、修改、删除权限
    revoke create,alter,drop on world.* from 'test'@'localhost';
    
    -- 授予指定用户'test'对于'world'数据库下所有存储过程的执行权限,并且该用户有权限转授予其他用户
    grant execute on world.* to 'test'@'localhost' with grant option;
    
    -- 撤销指定用户'test'对于'world'数据库下所有存储过程的执行权限,转授予权限一并撤销
    revoke execute on world.* from 'test'@'localhost';
    
    -- 给用户分派指定数据库上的所有权限
    GRANT ALL ON 数据库.* TO 用户名@IP地址;
    

    DQL:数据查询

    查询不会修改数据库表记录!

    a) 基本查询

    1. 字段(列)控制
      i. 查询所有列
    SELECT * FROM 表名;
    SELECT * FROM emp;
    --其中“*”表示查询所有列
    
    -- MySQL的WHERE子句默认是不区分大小写的,如果需要区分大小写,就要在字段前加上关键字 binary
    select * from student where stuno='a001';    #'1', 'A001', '小张', '男', '1988-06-09', '2018-01-12 12:17:00'
    select * from student where binary stuno='a001';    #null
    
    

    ii. 查询指定列

    SELECT 列1 [, 列2, ... 列N] FROM 表名;
    SELECT empno, ename, sal, comm FROM 表名;
    

    iii. 完全重复的记录只一次

    当查询结果中的多行记录一模一样时,只显示一行。一般查询所有列时很少会有这种情况,但只查询一列(或几列)时,这总可能就大了!
    SELECT DISTINCT * | 列1 [, 列2, ... 列N] FROM 表名;
    SELECT DISTINCT sal FROM emp;
    -- 保查询员工表的工资,如果存在相同的工资只显示一次!
    

    iv. 列运算

    数量类型的列可以做加、减、乘、除运算
    SELECT sal*1.5 FROM emp;
    SELECT sal+comm FROM emp;
    
    字符串类型可以做连续运算
    SELECT CONCAT('$', sal) FROM emp;
    
    转换NULL值
    有时需要把NULL转换成其它值,例如com+1000时,如果com列存在NULL值,那么NULL+1000还是NULL,而我们这时希望把NULL当前0来运算。
    SELECT IFNULL(comm, 0)+1000 FROM emp;
    --> IFNULL(comm, 0):如果comm中存在NULL值,那么当成0来运算。
    
    给列起别名
    你也许已经注意到了,当使用列运算后,查询出的结果集中的列名称很不好看,这时我们需要给列名起个别名,这样在结果集中列名就显示别名了
    SELECT IFNULL(comm, 0)+1000 AS 奖金 FROM emp;
    --> 其中AS可以省略
    
    1. 条件控制
      i. 条件查询
    与前面介绍的UPDATE和DELETE语句一样,SELECT语句也可以使用WHERE子句来控制记录。
    
    * SELECT empno,ename,sal,comm FROM emp WHERE sal > 10000 AND comm IS NOT NULL;
    * SELECT empno,ename,sal FROM emp WHERE sal BETWEEN 20000 AND 30000;(between:在……之间)
    * SELECT empno,ename,job FROM emp WHERE job IN ('经理', '董事长');
    

    ii. 模糊查询

    当你想查询姓张,并且姓名一共两个字的员工时,这时就可以使用模糊查询
    
    * SELECT * FROM emp WHERE ename LIKE '张_';
    --> 模糊查询需要使用运算符:LIKE,其中_匹配一个任意字符,注意,只匹配一个字符而不是多个。
    --> 上面语句查询的是姓张,名字由两个字组成的员工。
    * SELECT * FROM emp WHERE ename LIKE '___'; /*姓名由3个字组成的员工*/
    
    如果我们想查询姓张,名字几个字可以的员工时就要使用“%”了。
    SELECT * FROM emp WHERE ename LIKE '张%';
    --> 其中%匹配0~N个任意字符,所以上面语句查询的是姓张的所有员工。
    
    SELECT * FROM emp WHERE ename LIKE '%阿%';
    --> 千万不要认为上面语句是在查询姓名中间带有阿字的员工,因为%匹配0~N个字符,所以姓名以阿开头和结尾的员工也都会查询到。
    
    SELECT * FROM emp WHERE ename LIKE '%';
    --> 这个条件等同与不存在,但如果姓名为NULL的查询不出来!
    

    iii. 正则表达式

    -- regexp:用于设置正则表达式匹配项,类似于模糊匹配like。
    -- 表示查询名称以字符 'A'(不区分大小写)开头的记录。
    select * from world.city where Name regexp '^A';
    
    -- 表示查询名称中包含字符串 'mer' 的记录。
    select * from world.city where Name regexp 'mer';
    
    -- 表示查询名称以字符 'a' 或字符 'b' 开头的记录或者以字符 'r' 结尾的记录。
    select * from world.city where Name regexp '^[ab]|r$';
    

    b) 排序

    1. 升序
    SELECT * FROM WHERE emp ORDER BY sal ASC;
    --> 按sal排序,升序!
    --> 其中ASC是可以省略的
    
    1. 降序
    SELECT * FROM WHERE emp ORDER BY comm DESC;
    --> 按comm排序,降序!
    --> 其中DESC不能省略
    
    1. 使用多列作为排序条件
    SELECT * FROM WHERE emp ORDER BY sal ASC, comm DESC;
    --> 使用sal升序排,如果sal相同时,使用comm的降序排
    

    c) 聚合函数

    聚合函数用来做某列的纵向运算。

    1. COUNT
    SELECT COUNT(*) FROM emp;
    --> 计算emp表中所有列都不为NULL的记录的行数
    SELECT COUNT(comm) FROM emp;
    --> 云计算emp表中comm列不为NULL的记录的行数
    
    1. MAX
    SELECT MAX(sal) FROM emp;
    --> 查询最高工资
    
    1. MIN
    SELECT MIN(sal) FROM emp;
    --> 查询最低工资
    
    1. SUM
    SELECT SUM(sal) FROM emp;
    --> 查询工资合
    
    1. AVG
    SELECT AVG(sal) FROM emp;
    --> 查询平均工资
    

    d) 分组查询

    分组查询是把记录使用某一列进行分组,然后查询组信息。
    例如:查看所有部门的记录数。
    SELECT deptno, COUNT(*) FROM emp GROUP BY deptno;
    --> 使用deptno分组,查询部门编号和每个部门的记录数
    SELECT job, MAX(SAL) FROM emp GROUP BY job;
    --> 使用job分组,查询每种工作的最高工资
    
    组条件
    以部门分组,查询每组记录数。条件为记录数大于3
    SELECT deptno, COUNT(*) FROM emp GROUP BY deptno HAVING COUNT(*) > 3;
    

    e) Limit子句(方言)

    -- limit:用于设置返回的记录数。
    -- offset:用于设置select语句开始查询的数据偏移量,默认为零。
    -- 表示只取前10条数据
    select * from world.city limit 10;
    
    -- 表示跃过5条,从第6条数据开始取10条数据。
    select * from world.city limit 10 offset 5;
    
    -- 表示从第10条开始取5条数据。
    select * from world.city limit 10,5;
    
    --limit取值: (当前页-1) * 每页记录数
    

    B. 完整性约束

    主键约束(唯一标识)

    *非空
    *唯一
    被引用(学习外键时)

    • 当表的某一列被指定为主键后,该列就不能为空,不能有重复值出现。
    • 创建表时指定主键的两种方式:
    CREATE TABLE stu(
    sid	    CHAR(6) PRIMARY KEY,
    sname	VARCHAR(20),
    age		INT,
    gender	VARCHAR(10) 
    );
    

    指定sid列为主键列,即为sid列添加主键约束

    CREATE TABLE stu(
    sid	    CHAR(6),
    sname	VARCHAR(20),
    age		INT,
    gender	VARCHAR(10),
    PRIMARY KEY(sid)
    );
    
    

    指定sid列为主键列,即为sid列添加主键约束

    -- 修改表时指定主键:
    ALTER TABLE stu ADD PRIMARY KEY(sid);
    
    -- 删除主键:
    ALTER TABLE stu DROP PRIMARY KEY;
    

    主键自增长

    • 因为主键列的特性是:必须唯一、不能为空,所以我们通常会指定主键类为整型,然后设置其自动增长,这样可以保证在插入数据时主键列的唯一和非空特性。
    • 创建表时指定主键自增长
    CREATE TABLE stu(
    	sid INT PRIMARY KEY AUTO_INCREMENT,
    	sname	VARCHAR(20),
    	age		INT,
    	gender	VARCHAR(10)
    );
    
    • 修改表时设置主键自增长:ALTER TABLE stu CHANGE sid sid INT AUTO_INCREMENT;
    • 修改表时删除主键自增长:ALTER TABLE stu CHANGE sid sid INT;
    • 测试主键自增长:
    INSERT INTO stu VALUES(NULL, 'zhangSan',23,'male');
    INSERT INTO stu(sname,age,gender) VALUES('zhangSan',23,'male');
    

    非空约束

    • 因为某些列不能设置为NULL值,所以可以对列添加非空约束。
    • 例如:
    CREATE TABLE stu(
    	sid INT PRIMARY KEY AUTO_INCREMENT,
    	sname	VARCHAR(20) NOT NULL,
    	age		INT,
    	gender	VARCHAR(10)
    );
    

    对sname列设置了非空约束

    唯一约束

    • 车库某些列不能设置重复的值,所以可以对列添加唯一约束。
    • 例如:
    CREATE TABLE stu(
    	sid INT PRIMARY KEY AUTO_INCREMENT,
    	sname	VARCHAR(20) NOT NULL UNIQUE,
    	age		INT,
    	gender	VARCHAR(10)
    );
    

    对sname列设置了非空约束

    概念模型

    对象模型:可以双向关联,而且引用的是对象,而不是一个主键!
    关系模型:只能多方引用一方,而且引用的只是主键,而不是一整行记录。
    对象模型:在java中是domain!!!例如:User、Student
    is a
    has a(关联)

    1对1
    1对多
    多对多
    use a

    关系模型:在数据库中表!!!

    当我们要完成一个软件系统时,需要把系统中的实体抽取出来,形成概念模型。
    例如部门、员工都是系统中的实体。概念模型中的实体最终会成为Java中的类、数据库中表。
    实体之间还存在着关系,关系有三种:

    • 1对多:例如每个员工都从属一个部门,而一个部门可以有多个员工,其中员工是多方,而部门是一方。
    • 1对1:例如老公和老婆就是一对一的关系,一个老公只能有一个老婆,而一个老婆只能有一个老公。
    • 多对多:老师与学生的关系就是多对多,一个老师可以有多个学生,一个学生可以有多个老师。

    概念模型在Java中成为实体类(javaBean)
    类就使用成员变量来完成关系,一般都是双向关联!
    多对一双向中关联,即员工关联部门,部门也关联员工

    class Employee {//多方关联一方
     ...
     private Department department;
    }
    class Department {//一方关联多方
     ...
     private List<Employee> employees;
    }
    
    class Husband {
     ...
     private Wife wife;
    }
    class Wife {
     ...
     private Husband
    }
    
    class Student {
     ...
     private List<Teacher> teachers
    }
    class Teacher {
     ...
     private List<Student> students;
    }
    

    外键约束

    • 外键必须是另一表的主键的值(外键要引用主键!)
    • 外键可以重复
    • 外键可以为空
    • 一张表中可以有多个外键!

    概念模型在数据库中成为表
    数据库表中的多对一关系,只需要在多方使用一个独立的列来引用1方的主键即可

    /*员工表*/
    create talbe emp (
    empno int primary key,/*员工编号*/
    ...
    deptno int/*所属部门的编号*/
    );
    
    /*部门表*/
    create table dept (
    deptno int  primary key,/*部门编号*/
    ...
    );
    

    emp表中的deptno列的值表示当前员工所从属的部门编号。也就是说emp.deptno必须在dept表中是真实存在!
    但是我们必须要去对它进行约束,不然可能会出现员工所属的部门编号是不存在的。这种约束就是外键约束。
    我们需要给emp.deptno添加外键约束,约束它的值必须在dept.deptno中存在。外键必须是另一个表的主键!

    语法:CONSTRAINT 约束名称 FOREIGN KEY(外键列名) REFERENCES 关联表(关联表的主键)
    创建表时指定外键约束

    create talbe emp (
    empno int primary key,
    ...
    deptno int,
    CONSTRAINT fk_emp FOREIGN KEY(mgr) REFERENCES emp(empno)  
    );
    

    修改表时添加外键约束

    ALERT TABLE emp
    ADD CONSTRAINT fk_emp_deptno FOREIGN KEY(deptno) REFERENCES dept(deptno);
    

    修改表时删除外键约束

    ALTER TABLE emp
    DROP FOREIGN KEY fk_emp_deptno;/*约束名称*/
    

    数据库一对一关系

    在表中建立一对一关系比较特殊,需要让其中一张表的主键,即是主键又是外键。

    create table husband(
    hid int PRIMARY KEY,
    ...
    );
    create table wife(
    wid int PRIMARY KEY,
    ...
    ADD CONSTRAINT fk_wife_wid FOREIGN KEY(wid) REFERENCES husband(hid)
    );
    

    其中wife表的wid即是主键,又是相对husband表的外键!
    husband.hid是主键,不能重复!
    wife.wid是主键,不能重复,又是外键,必须来自husband.hid。
    所以如果在wife表中有一条记录的wid为1,那么wife表中的其他记录的wid就不能再是1了,因为它是主键。
    同时在husband.hid中必须存在1这个值,因为wid是外键。这就完成了一对一关系。

    *****从表的主键即是外键!

    数据库多对多关系

    在表中建立多对多关系需要使用中间表,即需要三张表,在中间表中使用两个外键,分别引用其他两个表的主键。

    create table student(
    sid int PRIMARY KEY,
    ...
    );
    create table teacher(
    tid int PRIMARY KEY,
    ...
    );
    
    create table stu_tea(
    sid int,
    tid int,
    ADD CONSTRAINT fk_stu_tea_sid FOREIGN KEY(sid) REFERENCES student(sid),
    ADD CONSTRAINT fk_stu_tea_tid FOREIGN KEY(tid) REFERENCES teacher(tid)
    );
    

    这时在stu_tea这个中间表中的每条记录都是来说明student和teacher表的关系
    例如在stu_tea表中的记录:sid为1001,tid为2001,这说明编号为1001的学生有一个编号为2001的老师
    sid tid
    101 201 /编号为101的学生有一个编号为201的老师/
    101 202 /编号为101的学生有一个编号为202的老师/
    101 203 /编号为101的学生有一个编号为203的老师/
    102 201 /编号为102的学生有一个编号为201的老师/
    102 204 /编号为102的学生有一个编号为204的老师/

    C. 乱码问题

    查看MySQL数据库编码

    • SHOW VARIABLES LIKE 'char%';

    编码解释

    • character_set_client:MySQL使用该编码来解读客户端发送过来的数据,例如该编码为UTF8,那么如果客户端发送过来的数据不是UTF8,那么就会出现乱码
    • character_set_results:MySQL会把数据转换成该编码后,再发送给客户端,例如该编码为UTF8,那么如果客户端不使用UTF8来解读,那么就会出现乱码
      其它编码只要支持中文即可,也就是说不能使用latin1

    控制台乱码问题

    • 插入或修改时出现乱码:

    这时因为cmd下默认使用GBK,而character_set_client不是GBK的原因。我们只需让这两个编码相同即可。
    因为修改cmd的编码不方便,所以我们去设置character_set_client为GBK即可。

    • 查询出的数据为乱码:

    这是因为character_set_results不是GBK,而cmd默认使用GBK的原因。我们只需让这两个编码相同即可。
    因为修改cmd的编码不方便,所以我们去设置character_set_results为GBK即可。

    • 设置变量的语句:

    set character_set_client=gbk;
    set character_set_results=gbk;

    注意,设置变量只对当前连接有效,当退出窗口后,再次登录mysql,还需要再次设置变量。
    为了一劳永逸,可以在my.ini中设置:
    设置default-character-set=gbk即可。

    指定默认编码

    我们在安装MySQL时已经指定了默认编码为UTF8,所以我们在创建数据库、创建表时,都无需再次指定编码。
    为了一劳永逸,可以在my.ini中设置:
    设置character-set-server=utf8即可。

    character_set_client | utf8 --> mysql把我们客户端传递的数据都当成是utf8!一是给它传递utf8,二是如果我们传递的是gbk,那么需要修改这个变量为gbk
    character_set_connection | utf8
    character_set_database | utf8
    character_set_results | utf8 --> mysql发送给客户端的数据都是utf8的。一是客户端用utf8编码,二是如果客户端使用gbk来编码,那么需要修改这个变量为gbk的。
    character_set_server | utf8
    character_set_system | utf8


    character_set_client=utf8,无论客户端发送的是什么编码的数据,mysql都当成是utf8的数据!

    若客户端发送的是GBK
    服务器会当成utf8对待
    总结:必然乱码!

    处理问题的手段有两种;

    让客户端发送utf8的数据(行不通)
    把character_set_client修改为gbk
    set character_set_client=gbk; --> 只在当前窗口内有效,也就是说,关闭窗口后,再打开,又回到utf8了。

    character_set_results=utf8,把数据用什么编码发送给客户端!

    若服务器发送给客户端的是utf8的数据
    客户端会把它当成gbk,因为我们的小黑屏,只能显示gbk
    总结:必然乱码!

    处理问题的手段有两种:

    让服务器发送gbk的数据:set character_set_results=gbk
    让小黑屏使用utf8来解读(行不通)

    my.ini
    在总配置文件中进行配置,可以一劳永逸

    [client]
    port=3306
    [mysql]
    default-character-set=gbk /*它可以一劳永逸!它可以修改三个变量:client、results、connection*/
    

    目前使用字符串设置:

    [client]
    default-character-set=utf8 
    [mysql]
    default-character-set=utf8
    [mysqld]
    character-set-server=utf8
    

    D. 数据库字符校对集

    字符校对集,即排序规则,在某个字符集的情况下,字符集的排列顺序应该是什么,称之为校对集。

    -- 查看所有的字符校对集
    -- 后缀为_bin:表示基于二进制编码的直接比较
    -- 后缀为_ci:表示对大小写不敏感的比较
    -- 后缀为_cs:表示对大小写敏感的比较
    show collation;
    

    E. 备份和恢复数据

    数据库 --> sql语句
    sql语句 --> 数据库

    1. 数据库导出SQL脚本(备份数据库内容,并不是备份数据库!)
    mysqldump –u用户名 –p密码 数据库名>生成的脚本文件路径
    例如:
    mysqldump -uroot -p123 mydb1>C:mydb1.sql  
    (与mysql.exe和mysqld.exe一样, 都在bin目录下)
    

    注意,不要打分号,不要登录mysql,直接在cmd下运行
    注意,生成的脚本文件中不包含create database语句

    1. 执行SQL脚本
      第一种方式
    mysql -u用户名 -p密码 数据库<脚本文件路径
    例如:先删除mydb1库,再重新创建mydb1库
    mysql -uroot -p123 mydb1<C:mydb1.sql
    

    注意,不要打分号,不要登录mysql,直接在cmd下运行

    第二种方式

    登录mysql
    source SQL脚本路径
    例如:
    先删除mydb1库,再重新创建mydb1库
    切换到mydb1库
    source c:mydb1.sql
    

    示例:
    数据库 --> sql:备份
    sql --> 数据库:恢复

    mysqldump -uroot -p123 mydb3>c:/a.sql --备份
    mysql -uroot -p123 mydb3<c:/a.sql --恢复
    source c:/a.sql --恢复
    

    F. 多表查询

    SQL语句指令顺序:

    select * 
    from emp, dept, (select * from emp)
    where
    group by
    having
    order by
    limit 
    

    合并结果集(了解)

    • 要求被合并的表中,列的类型和列数相同
    • UNION,去除重复行
    • UNION ALL,不去除重复行
      SELECT * FROM cd
      UNION ALL
      SELECT * FROM ab;

    连接查询

    a) 分类

    内连接
    外连接
       左外连接
       右外连接
       全外连接(MySQL不支持)
    自然连接(属于一种简化方式)
    

    b) 内连接

    -- 方言:
    SELECT * FROM 表1 别名1, 表2 别名2 WHERE 别名1.xx=别名2.xx
    -- 标准:SELECT * FROM 表1 别名1 INNER JOIN 表2 别名2 ON 别名1.xx=别名2.xx
    -- 自然:SELECT * FROM 表1 别名1 NATURAL JOIN 表2 别名2
    

    内连接查询出的所有记录都满足条件。

    c) 外连接

    -- 左外:
    SELECT * FROM 表1 别名1 LEFT OUTER JOIN 表2 别名2 ON 别名1.xx=别名2.xx
    -- 左表记录无论是否满足条件都会查询出来,而右表只有满足条件才能出来。左表中不满足条件的记录,右表部分都为NULL
    
    -- 左外自然:
    SELECT * FROM 表1 别名1 NATURAL LEFT OUTER JOIN 表2 别名2 ON 别名1.xx=别名2.xx
    
    -- 右外:
    SELECT * FROM 表1 别名1 RIGHT OUTER JOIN 表2 别名2 ON 别名1.xx=别名2.xx
    -- 右表记录无论是否满足条件都会查询出来,而左表只有满足条件才能出来。右表不满足条件的记录,其左表部分都为NULL
    
    -- 右外自然:
    SELECT * FROM 表1 别名1 NATURAL RIGHT OUTER JOIN 表2 别名2 ON 别名1.xx=别名2.xx
    
    -- 全链接:可以使用UNION来完成全链接
    

    子查询

    定义:查询中有查询(查看select关键字的个数!)

    1. 出现的位置:
    • where后作为条件存在
    • from后作为表存在(多行多列)
    1. 条件
    • 单行单列:SELECT * FROM 表1 别名1 WHERE 列1 [=、>、<、>=、<=、!=] (SELECT 列 FROM 表2 别名2 WHERE 条件)
    • 多行单列:SELECT * FROM 表1 别名1 WHERE 列1 [IN, ALL, ANY] (SELECT 列 FROM 表2 别名2 WHERE 条件)
    • 单行多列:SELECT * FROM 表1 别名1 WHERE (列1,列2) IN (SELECT 列1, 列2 FROM 表2 别名2 WHERE 条件)
    • 多行多列:SELECT * FROM 表1 别名1 , (SELECT ....) 别名2 WHERE 条件
  • 相关阅读:
    DNS服务器安全之通过ipset对DNS异常解析流量的源IP地址进行管控
    C# Windows Api的一些方法 封装 以及 常用参数
    Java基础—异常(1)
    Java基础——异常(2)
    vb6 wininet
    vb6转16进制
    Java 中与(&)短路与(&&)以及 或(|)短路或(||)的关系
    关于面向对象的简单总结
    javaScript的基本规范
    关于TCP传输的三次握手四次挥手策略
  • 原文地址:https://www.cnblogs.com/yhongyin/p/12040394.html
Copyright © 2011-2022 走看看