• mySQL基础入门


    mySQL

    安装

    windows

    windows https://www.runoob.com/mysql/mysql-install.html

    mysqld --initialize --console 报错 -- 出现Failed to find valid data directory.
    https://blog.csdn.net/github_38832708/article/details/83037241
    mysqld --initialize --console初始化数据库:

    mysqld --initialize-insecure
    程序会在动MySQL文件夹下创建data文件夹以及对应的文件

    登录

    mysql -h 主机名 -u 用户名 -p
    mysql -u root -p
    
    -h : 指定客户端所要登录的 MySQL 主机名, 登录本机(localhost 或 127.0.0.1)该参数可以省略;
    -u : 登录的用户名;
    -p : 告诉服务器将会使用一个密码来登录, 如果所要登录的用户名密码为空, 可以忽略此选项。
    
    输入 exit 或 quit 退出登录
    

    启动 mysqld --console
    关闭 mysqladmin -uroot shutdown

    mysql服务
    移除 mysqld -remove MySQL
    关闭 net stop MySQL
    开启 net start MySQL

    图形界面下载
    https://downloads.mysql.com/archives/workbench/
    mysql workBench, 最新版好像和win10不兼容

    ubuntu

    安装

    sudo apt-get install mysql-server / 密码:123
    sudo apt-get install mysql-client
    sudo apt-get install libmysqlclient-dev

    启动

    mysql -uroot -p / 123

    设置远程访问

    参考 https://blog.csdn.net/james_nan/article/details/82053430

    sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf
    修改bind-address
    
    mysql> grant all privileges on *.* to root@"%" identified by "password" with grant option;
    
    *.*,表示数据库.表,也就是指所有数据库下的所有表。%表示任意的ip地址。password为root账号的密码。
    
    service mysql restart
    

    192.168.157.139
    ip addr

    关闭

    关闭目前运行的 MySQL 服务器, 你可以执行以下命令:

    root@host# cd /usr/bin
    ./mysqladmin -u root -p shutdown
    Enter password: ******
    

    用户设置

    需要添加 MySQL 用户,你只需要在 mysql 数据库中的 user 表添加新用户即可。

    root@host# mysql -u root -p
    Enter password:*******
    mysql> use mysql;
    Database changed
    
    mysql> INSERT INTO user 
              (host, user, password, 
               select_priv, insert_priv, update_priv) 
               VALUES ('localhost', 'guest', 
               PASSWORD('guest123'), 'Y', 'Y', 'Y');
    Query OK, 1 row affected (0.20 sec)
    
    mysql> FLUSH PRIVILEGES;
    Query OK, 1 row affected (0.01 sec)
    
    mysql> SELECT host, user, password FROM user WHERE user = 'guest';
    +-----------+---------+------------------+
    | host      | user    | password         |
    +-----------+---------+------------------+
    | localhost | guest | 6f8c114b58f2ce9e |
    +-----------+---------+------------------+
    1 row in set (0.00 sec)
    

    在添加用户时,请注意使用MySQL提供的 PASSWORD() 函数来对密码进行加密。 你可以在以上实例看到用户密码加密后为: 6f8c114b58f2ce9e.

    注意:在 MySQL5.7 中 user 表的 password 已换成了authentication_string

    注意:password() 加密函数已经在 8.0.11 中移除了,可以使用 MD5() 函数代替。

    注意:在注意需要执行 FLUSH PRIVILEGES 语句。 这个命令执行后会重新载入授权表。

    如果你不使用该命令,你就无法使用新创建的用户来连接mysql服务器,除非你重启mysql服务器。

    你可以在创建用户时,为用户指定权限,在对应的权限列中,在插入语句中设置为 'Y' 即可

    管理MySQL

    USE 数据库名 :
    选择要操作的Mysql数据库,使用该命令后所有Mysql命令都只针对该数据库。

    SHOW DATABASES:
    列出 MySQL 数据库管理系统的数据库列表。(所有数据库

    SHOW TABLES:
    显示指定数据库的所有表(所有关系,即所有表格),使用该命令前需要使用 use 命令来选择要操作的数据库。

    SHOW COLUMNS FROM 数据表:
    显示数据表的属性,属性类型,主键信息 ,是否为 NULL,默认值等其他信息。

    SHOW INDEX FROM 数据表:
    显示数据表的详细索引信息,包括PRIMARY KEY(主键)。

    SHOW TABLE STATUS [FROM db_name] [LIKE 'pattern'] G:
    该命令将输出Mysql数据库管理系统的性能及统计信息。

    mysql> SHOW TABLE STATUS  FROM RUNOOB;   # 显示数据库 RUNOOB 中所有表的信息
    
    mysql> SHOW TABLE STATUS from RUNOOB LIKE 'runoob%';     # 表名以runoob开头的表的信息
    mysql> SHOW TABLE STATUS from RUNOOB LIKE 'runoob%'G;   # 加上 G,查询结果按列打印
    

    数据库的增删

    CREATE DATABASE 数据库名;
    
    drop database <数据库名>;
    

    数据类型

    数值类型

    MySQL支持所有标准SQL数值数据类型。这些类型包括严格数值数据类型(INTEGER、SMALLINT、DECIMAL和NUMERIC),以及近似数值数据类型(FLOAT、REAL和DOUBLE PRECISION)。

    关键字INT是INTEGER的同义词,关键字DEC是DECIMAL的同义词。BIT数据类型保存位字段值,并且支持MyISAM、MEMORY、InnoDB和BDB表。

    作为SQL标准的扩展,MySQL也支持整数类型TINYINT、MEDIUMINT和BIGINT。下面的表显示了需要的每个整数类型的存储和范围。

    类型 大小 范围(有符号) 范围(无符号) 用途
    TINYINT 1 byte (-128,127) (0,255) 小整数值
    SMALLINT 2 bytes (-32 768,32 767) (0,65 535) 大整数值
    MEDIUMINT 3 bytes (-8 388 608,8 388 607) (0,16 777 215) 大整数值
    INT或INTEGER 4 bytes (-2 147 483 648,2 147 483 647) (0,4 294 967 295) 大整数值
    BIGINT 8 bytes (-9,223,372,036,854,775,808,9 223 372 036 854 775 807) (0,18 446 744 073 709 551 615) 极大整数值
    FLOAT 4 bytes (-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 bytes (-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) 双精度 浮点数值
    DECIMAL 对DECIMAL(M,D) ,如果M>D,为M+2否则为D+2 依赖于M和D的值。DECIMAL数据类型用于在数据库中存储精确的数值。 依赖于M和D的值 小数值

    对于decimal, 整数的位数必须小于等于m-d,不然报错。小数的位数可以大于d位。多出d位时会做四舍五入,截取到d位

    日期和时间类型

    表示时间值的日期和时间类型为DATETIME、DATE、TIMESTAMP、TIME和YEAR。

    每个时间类型有一个有效值范围和一个"零"值,当指定不合法的MySQL不能表示的值时使用"零"值。

    TIMESTAMP类型有专有的自动更新特性,将在后面描述。

    类型 大小 ( bytes) 范围 格式 用途
    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 混合日期和时间值,时间戳

    字符串类型

    字符串类型指CHAR、VARCHAR、BINARY、VARBINARY、BLOB、TEXT、ENUM和SET。该节描述了这些类型如何工作以及如何在查询中使用这些类型。

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

    注意:char(n) 和 varchar(n) 中括号中 n 代表字符的个数,并不代表字节个数,比如 CHAR(30) 就可以存储 30 个字符。

    CHAR 和 VARCHAR 类型类似,但它们保存和检索的方式不同。它们的最大长度和是否尾部空格被保留等方面也不同。在存储或检索过程中不进行大小写转换。

    BINARY 和 VARBINARY 类似于 CHAR 和 VARCHAR,不同的是它们包含二进制字符串而不要非二进制字符串。也就是说,它们包含字节字符串而不是字符字符串。这说明它们没有字符集,并且排序和比较基于列值字节的数值值。

    BLOB 是一个二进制大对象,可以容纳可变数量的数据。有 4 种 BLOB 类型:TINYBLOB、BLOB、MEDIUMBLOB 和 LONGBLOB。它们区别在于可容纳存储范围不同。

    有 4 种 TEXT 类型:TINYTEXT、TEXT、MEDIUMTEXT 和 LONGTEXT。对应的这 4 种 BLOB 类型,可存储的最大长度不同,可根据实际情况选择。

    注意

    MySQL 5.0 以上的版本:

    • 1、一个汉字占多少长度与编码有关:
      UTF-8:一个汉字=3个字节
      GBK:一个汉字=2个字节

    • 2、varchar(n) 表示 n 个字符,无论汉字和英文,Mysql 都能存入 n 个字符,仅是实际字节长度有所区别

    char、varchar 与 text

    关于 char、varchar 与 text 平时没有太在意,一般来说,可能现在大家都是用 varchar。但是当要存储的内容比较大时,究竟是选择 varchar 还是 text 呢?

    这三种类型比较:

    • (1)char: char 不用多说了,它是定长格式的,但是长度范围是 0~255. 当你想要储存一个长度不足 255 的字符时,Mysql 会用空格来填充剩下的字符。因此在读取数据时,char 类型的数据要进行处理,把后面的空格去除。
    • (2)varchar: 关于 varchar,有的说最大长度是 255,也有的说是 65535,查阅很多资料后发现是这样的:varchar 类型在 5.0.3 以下的版本中的最大长度限制为 255,而在 5.0.3 及以上的版本中,varchar 数据类型的长度支持到了 65535,也就是说可以存放 65532 个字节(注意是字节而不是字符!!!)的数据(起始位和结束位占去了3个字节),也就是说,在 5.0.3 以下版本中需要使用固定的 TEXT 或 BLOB 格式存放的数据可以在高版本中使用可变长的 varchar 来存放,这样就能有效的减少数据库文件的大小。
    • (3)text: 与 char 和 varchar 不同的是,text 不可以有默认值,其最大长度是 2 的 16 次方-1

    总结起来,有几点:

    • 经常变化的字段用 varchar
    • 知道固定长度的用 char
    • 尽量用 varchar
    • 超过 255 字符的只能用 varchar 或者 text
    • 能用 varchar 的地方不用 text

    按照查询速度: char最快, varchar次之,text最慢。

    数据表

    创建数据表

    以下为创建MySQL数据表的SQL通用语法:

    CREATE TABLE table_name (column_name column_type);
    
    CREATE TABLE IF NOT EXISTS `runoob_tbl`(
       `runoob_id` INT UNSIGNED AUTO_INCREMENT,
       `runoob_title` VARCHAR(100) NOT NULL,
       `runoob_author` VARCHAR(40) NOT NULL,
       `submission_date` DATE,
       PRIMARY KEY ( `runoob_id` )
    )ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    • 如果你不想字段为 NULL 可以设置字段的属性为 NOT NULL, 在操作数据库时如果输入该字段的数据为NULL ,就会报错。
    • AUTO_INCREMENT定义列为自增的属性,一般用于主键,数值会自动加1。
    • PRIMARY KEY关键字用于定义列为主键。 您可以使用多列来定义主键,列间以逗号分隔。
    • ENGINE 设置存储引擎,CHARSET 设置编码。

    查看数据表

    desc 数据表名称;

    MySQL 字段属性应该尽量设置为 NOT NULL

    除非你有一个很特别的原因去使用 NULL 值,你应该总是让你的字段保持 NOT NULL。

    1、首先,我们要搞清楚空值 ""NULL 的概念:

    • 1)空值是不占用空间的
    • 2)MySQL中的NULL其实是占用空间的

    所谓的 NULL 就是什么都没有,连 都没有, 在字符串中是结束符,但是在物理内存是占空间的,等于一个字节,而 NULL 就是连这一个字节都没有。

    2、其次,在数据库里是严格区分的,任何数跟 NULL 进行运算都是 NULL, 判断值是否等于 NULL,不能简单用 =,而要用 IS NULL关键字

    3、数据库的字段 col1 设为 NOT NULL, 仅仅说明该字段不能为 NULL, 也就是说只有在:

    INSERT INTO table1(col1) VALUES(NULL);
    

    这种情况下数据库会报错,而:

    INSERT INTO table1(col1) VALUES('');
    

    不会报错。

    (如果字段是自增ID,第一句不会报错,这不能说明是可以为NULL,而是 数据库系统会根据ID设的缺省值填充,或者如果是自增字段就自动加一等缺省操作。)

    4、 含有空值的列很难进行查询优化,而且对表索引时不会存储 NULL 值的,所以如果索引的字段可以为 NULL,索引的效率会下降很多。因为它们使得索引、索引的统计信息以及比较运算更加复杂。你应该用 0、一个特殊的值或者一个空串代替空值。

    5、联表查询的时候,例如 LEFT JOIN table2,若没有记录,则查找出的 table2 字段都是 null。假如 table2 有些字段本身可以是 null,那么除非把 table2 中 not null 的字段查出来,否则就难以区分到底是没有关联记录还是其他情况。

    删除数据表

    针对 表结构,innodb 和 MyISAM有4种级别的删除。

    DROP TABLE table_name;
    删除表全部数据和表结构,立刻释放磁盘空间,不管是 Innodb 和 MyISAM;
    
    
    truncate table table_name;
    删除表全部数据,保留表结构,立刻释放磁盘空间 ,不管是 Innodb 和 MyISAM;
    
    
    delete from table_name;
    删除表全部数据,表结构不变,对于 MyISAM 会立刻释放磁盘空间,InnoDB 不会释放磁盘空间;
    
    
    delete from table_name where xxx : 带条件的删除,表结构不变,不管是 innodb 还是 MyISAM 都不会释放磁盘空间;
    实例,删除学生表中姓名为 "张三" 的数据:
    delete from student where T_name = "张三";
    delete 操作以后,使用 optimize table table_name 会立刻释放磁盘空间,不管是 innodb 还是 myisam;
    
    

    MySQL 数据库删除数据的三种方式:

    delete from table where

    直接删除表中的某一行数据,并且同时将该行的删除操作作为事务记录在日志中保存以便进行进行回滚操作。所以 delete 相比较 truncate 更加占用资源,数据空间不释放,因为需回滚。对 table 和 view 都能操作。

    truncate table

    一次性地从表中删除所有的数据(释放存储表数据所用的数据页来删除数据)并不把单独的删除操作记录记入日志保存(只在事务日志中记录 页的释放),因此也不能回滚,不能恢复数据,在删除的过程中不会激活与表有关的删除触发器,占用资源更加少,速度更快。数据空间会释放,这个表和索引所占用的空间会恢复到初始大小。只能操作没有关联视图的 table。

    truncate table 不能用于参与了索引视图的表。

    drop table

    删除的是整个表,包括表的结构,数据,定义。永久抹去,空间释放。对 table 和 view 都能操作。由于 TRUNCATE TABLE 不记录在日志中,所以它不能激活触发器,对于外键(foreignkey )约束引用的表,不能使用 truncate table,而应使用不带 where 子句的 delete 语句。

    增删改查

    以下为向MySQL数据表插入数据通用的 INSERT INTO SQL语法:

    INSERT INTO table_name ( field1, field2,...fieldN )
                           VALUES
                           ( value1, value2,...valueN );
                           
    INSERT INTO table_name  (field1, field2,...fieldN)  VALUES  (valueA1,valueA2,...valueAN),(valueB1,valueB2,...valueBN),(valueC1,valueC2,...valueCN)......;
    

    如果所有的列都要添加数据可以不规定列进行添加数据
    如果数据是字符型,必须使用单引号或者双引号,如:"value"。

    mysql> INSERT INTO runoob_tbl 
        -> (runoob_title, runoob_author, submission_date)
        -> VALUES
        -> ("学习 PHP", "菜鸟教程", NOW());
    

    我们并没有提供 runoob_id 的数据,因为该字段我们在创建表的时候已经设置它为 AUTO_INCREMENT(自动增加) 属性。 所以,该字段会自动递增而不需要我们去设置。实例中 NOW() 是一个 MySQL 函数,该函数返回日期和时间。

    读取表的数据

    select * from runoob_tbl;

    以下为在MySQL数据库中查询数据通用的 SELECT 语法:

    SELECT column_name,column_name
    FROM table_name
    [WHERE Clause]
    [LIMIT N][ OFFSET M]
    
    • 查询语句中你可以使用一个或者多个表,表之间使用逗号(,)分割,并使用WHERE语句来设定查询条件
    • SELECT 命令可以读取一条或者多条记录。
    • 你可以使用星号(*)来代替其他字段,SELECT语句会返回表的所有字段数据
    • 你可以使用 WHERE 语句来包含任何条件。
    • 你可以使用 LIMIT 属性来设定返回的记录数limit N,M : 相当于 limit M offset N , 从第 N 条记录开始, 返回 M 条记录 (-1表最后)
    • 你可以通过OFFSET指定SELECT语句开始查询的数据偏移量。默认情况下偏移量为0。

    where

    SELECT field1, field2,...fieldN FROM table_name1, table_name2...
    [WHERE condition1 [AND [OR]] condition2.....
    
    • 查询语句中你可以使用一个或者多个表,表之间使用逗号, 分割,并使用WHERE语句来设定查询条件。
    • 你可以在 WHERE 子句中指定任何条件。
    • 你可以使用 AND 或者 OR 指定一个或多个条件。
    • WHERE 子句也可以运用于 SQL 的 DELETE 或者 UPDATE 命令。
    • WHERE 子句类似于程序语言中的 if 条件,根据 MySQL 表中的字段值来读取指定的数据。

    使用主键来作为 WHERE 子句的条件查询是非常快速的。
    如果给定的条件在表中没有任何匹配的记录,那么查询不会返回任何数据。

    MySQL 的 WHERE 子句的字符串比较是不区分大小写的。 你可以使用 BINARY 关键字来设定 WHERE 子句的字符串比较是区分大小写的。

    mysql> SELECT * from runoob_tbl WHERE BINARY runoob_author='runoob.com';

    like

    类似正则匹配

    LIKE 子句中使用百分号 %字符来表示任意字符,类似于UNIX或正则表达式中的星号 *****。

    SELECT field1, field2,...fieldN 
    FROM table_name
    WHERE field1 LIKE condition1 [AND [OR]] filed2 = 'somevalue'
    

    like 匹配/模糊匹配,会与 %_ 结合使用。

    '%a'     //以a结尾的数据
    'a%'     //以a开头的数据
    '%a%'    //含有a的数据
    '_a_'    //三位且中间字母是a的
    '_a'     //两位且结尾字母是a的
    'a_'     //两位且开头字母是a的
    

    在 where like 的条件查询中,SQL 提供了四种匹配方式。

    1. %:表示任意 0 个或多个字符。可匹配任意类型和长度的字符,有些情况下若是中文,请使用两个百分号(%%)表示。
    2. _:表示任意单个字符。匹配单个任意字符,它常用来限制表达式的字符长度语句。
    3. []:表示括号内所列字符中的一个(类似正则表达式)。指定一个字符、字符串或范围,要求所匹配对象为它们中的任一个。
    4. [^] :表示不在括号所列之内的单个字符。其取值和 [] 相同,但它要求所匹配对象为指定字符以外的任一个字符。
    5. 查询内容包含通配符时,由于通配符的缘故,导致我们查询特殊字符 “%”、“_”、“[” 的语句无法正常实现,而把特殊字符用 “[ ]” 括起便可正常查询。

    正则

    模式 描述
    ^ 匹配输入字符串的开始位置。如果设置了 RegExp 对象的 Multiline 属性,^ 也匹配 ' ' 或 ' ' 之后的位置。
    $ 匹配输入字符串的结束位置。如果设置了RegExp 对象的 Multiline 属性,$ 也匹配 ' ' 或 ' ' 之前的位置。
    . 匹配除 " " 之外的任何单个字符。要匹配包括 ' ' 在内的任何字符,请使用象 '[. ]' 的模式。
    [...] 字符集合。匹配所包含的任意一个字符。例如, '[abc]' 可以匹配 "plain" 中的 'a'。
    [^...] 负值字符集合。匹配未包含的任意字符。例如, '[^abc]' 可以匹配 "plain" 中的'p'。
    p1|p2|p3 匹配 p1 或 p2 或 p3。例如,'z|food' 能匹配 "z" 或 "food"。'(z|f)ood' 则匹配 "zood" 或 "food"。
    * 匹配前面的子表达式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等价于{0,}。
    + 匹配前面的子表达式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。
    {n} n 是一个非负整数。匹配确定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个 o。
    {n,m} m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。

    查找name字段中以元音字符开头或以'ok'字符串结尾的所有数据:

    mysql> SELECT name FROM person_tbl WHERE name REGEXP '^[aeiou]|ok$';
    

    UPDATE table_name SET field1=new-value1, field2=new-value2
    [WHERE Clause]
    
    • 你可以同时更新一个或多个字段。
    • 你可以在 WHERE 子句中指定任何条件。
    • 你可以在一个单独表中同时更新数据。

    当我们需要将字段中的特定字符串批量修改为其他字符串时,可已使用以下操作:

    UPDATE table_name SET field=REPLACE(field, 'old-string', 'new-string') 
    [WHERE Clause]
    

    DELETE FROM table_name [WHERE Clause]
    
    • 如果没有指定 WHERE 子句,MySQL 表中的所有记录将被删除。
    • 你可以在 WHERE 子句中指定任何条件
    • 您可以在单个表中一次性删除记录。

    执行的速度上,drop>truncate>delete

    union

    SELECT expression1, expression2, ... expression_n
    FROM tables
    [WHERE conditions]
    UNION [ALL | DISTINCT]
    SELECT expression1, expression2, ... expression_n
    FROM tables
    [WHERE conditions];
    

    有点自然连接的意思,但是select的属性必须相同

    参数

    • expression1, expression2, ... expression_n: 要检索的列。
    • tables: 要检索的数据表。
    • WHERE conditions: 可选, 检索条件。
    • DISTINCT: 可选,删除结果集中重复的数据。默认情况下 UNION 操作符已经删除了重复数据,所以 DISTINCT 修饰符对结果没啥影响。
    • ALL: 可选,返回所有结果集,包含重复数据。

    实例

    下面的 SQL 语句从 "Websites" 和 "apps" 表中选取所有不同的country(只有不同的值):

    SELECT country FROM Websites
    UNION
    SELECT country FROM apps
    ORDER BY country;
    

    排序

    SELECT field1, field2,...fieldN FROM table_name1, table_name2...
    ORDER BY field1 [ASC [DESC][默认 ASC]], [field2...] [ASC [DESC][默认 ASC]]
    
    • 你可以使用任何字段来作为排序的条件,从而返回排序后的查询结果。
    • 你可以设定多个字段来排序。
    • 你可以使用 ASC 或 DESC 关键字来设置查询结果是按升序或降序排列。 默认情况下,它是按升序排列。
    • 你可以添加 WHERE...LIKE 子句来设置条件。

    MySQL 拼音排序

    如果字符集采用的是 gbk(汉字编码字符集),直接在查询语句后边添加 ORDER BY:

    SELECT * 
    FROM runoob_tbl
    ORDER BY runoob_title;
    

    如果字符集采用的是 utf8(万国码),需要先对字段进行转码convert然后排序:

    SELECT * 
    FROM runoob_tbl
    ORDER BY CONVERT(runoob_title using gbk);
    

    分组

    GROUP BY 语句根据一个或多个列对结果集进行分组。相同的分一组

    在分组的列上我们可以使用 COUNT, SUM, AVG,等函数。

    SELECT column_name, function(column_name)
    FROM table_name
    WHERE column_name operator value
    GROUP BY column_name;
    

    使用 GROUP BY 语句 将数据表按名字进行分组,并统计每个人有多少条记录:

    mysql> SELECT name, COUNT(*) FROM   employee_tbl GROUP BY name;
    

    WITH ROLLUP

    WITH ROLLUP 可以实现在分组统计数据基础上再进行相同的统计(SUM,AVG,COUNT…)。

    例如我们将以上的数据表按名字进行分组,再统计每个人登录的次数:

    mysql> SELECT name, SUM(singin) as singin_count FROM  employee_tbl GROUP BY name WITH ROLLUP;
    +--------+--------------+
    | name   | singin_count |
    +--------+--------------+
    | 小丽 |            2 |
    | 小明 |            7 |
    | 小王 |            7 |
    | NULL   |           16 |
    +--------+--------------+
    4 rows in set (0.00 sec)
    

    其中记录 NULL 表示所有人的登录次数。

    我们可以使用 coalesce 来设置一个可以取代 NUll 的名称,coalesce 语法:

    select coalesce(a,b,c);
    

    参数说明:如果a=null,则选择b;如果b=null,则选择c;如果a!=null,则选择a;如果a b c 都为null ,则返回为null(没意义)。

    以下实例中如果名字为空我们使用总数代替:

    mysql> SELECT coalesce(name, '总数'), SUM(singin) as singin_count FROM  employee_tbl GROUP BY name WITH ROLLUP;
    +--------------------------+--------------+
    | coalesce(name, '总数') | singin_count |
    +--------------------------+--------------+
    | 小丽                   |            2 |
    | 小明                   |            7 |
    | 小王                   |            7 |
    | 总数                   |           16 |
    +--------------------------+--------------+
    4 rows in set (0.01 sec)
    
    SELECT c.*
    FROM (
        SELECT IFNULL(b.城市,"总计") AS 城市,SUM(IF(b.年月=201607,b.金额,NULL)) AS 7月金额,SUM(IF(b.年月=201608,b.金额,NULL)) AS 8月金额,SUM(IF(b.年月=201609,b.金额,NULL)) AS 9月金额
        FROM (
            SELECT IFNULL(city,'空城市') AS 城市,DATE_FORMAT(order_time,"%Y%m") AS 年月,SUM(pay_money) AS 金额
            FROM test_a03order AS a
            GROUP BY city,DATE_FORMAT(order_time,"%Y%m")
        ) AS b
        GROUP BY b.城市 WITH ROLLUP
    ) AS c
    ORDER BY FIELD(城市,'总计'),c.9月金额 DESC
    

    连接

    你可以在 SELECT, UPDATE 和 DELETE 语句中使用 Mysql 的 JOIN 来联合多表查询。

    JOIN 按照功能大致分为如下三类:

    • INNER JOIN(内连接,或等值连接):获取两个表中字段匹配关系的记录。
    • LEFT JOIN(左连接):获取左表所有记录,即使右表没有对应匹配的记录。
    • RIGHT JOIN(右连接): 与 LEFT JOIN 相反,用于获取右表所有记录,即使左表没有对应匹配的记录。
    mysql> SELECT a.runoob_id, a.runoob_author, b.runoob_count FROM runoob_tbl a INNER JOIN tcount_tbl b ON a.runoob_author = b.runoob_author;
    
    mysql> SELECT a.runoob_id, a.runoob_author, b.runoob_count FROM runoob_tbl a, tcount_tbl b WHERE a.runoob_author = b.runoob_author;
    

    left join 与 join 有所不同。 MySQL LEFT JOIN 会读取左边数据表的全部数据,即便右边表无对应数据。

    尝试以下实例,以 runoob_tbl 为左表,tcount_tbl 为右表,理解 MySQL LEFT JOIN 的应用:

    mysql> SELECT a.runoob_id, a.runoob_author, b.runoob_count FROM runoob_tbl a LEFT JOIN tcount_tbl b ON a.runoob_author = b.runoob_author;
    

    用集合去理解

    NULL

    MySQL 使用 SQL SELECT 命令及 WHERE 子句来读取数据表中的数据,但是当提供的查询条件字段为 NULL 时,该命令可能就无法正常工作。

    为了处理这种情况,MySQL提供了三大运算符:

    • IS NULL: 当列的值是 NULL,此运算符返回 true。
    • IS NOT NULL: 当列的值不为 NULL, 运算符返回 true。
    • <=>: 比较操作符(不同于 = 运算符),当比较的的两个值相等或者都为 NULL 时返回 true。

    关于 NULL 的条件比较运算是比较特殊的。你不能使用 = NULL 或 != NULL 在列中查找 NULL 值 。在 MySQL 中,NULL 值与任何其它值的比较(即使是 NULL)永远返回 NULL,即 NULL = NULL 返回 NULL 。

    MySQL 中处理 NULL 使用 IS NULL 和 IS NOT NULL 运算符。

    select * , columnName1+ifnull(columnName2,0) from tableName;
    

    columnName1,columnName2 为 int 型,当 columnName2 中,有值为 null 时,columnName1+columnName2=null, ifnull(columnName2,0) 把 columnName2 中 null 值转为 0。

    mysql> SELECT * from runoob_test_tbl WHERE runoob_count IS NOT NULL;

    事务

    MySQL 事务主要用于处理操作量大,复杂度高的数据。比如说,在人员管理系统中,你删除一个人员,你既需要删除人员的基本资料,也要删除和该人员相关的信息,如信箱,文章等等,这样,这些数据库操作语句就构成一个事务!

    • 在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务。
    • 事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行。
    • 事务用来管理 insert,update,delete 语句

    一般来说,事务是必须满足4个条件(ACID)::原子性(Atomicity,或称不可分割性)、一致性(Consistency)、隔离性(Isolation,又称独立性)、持久性(Durability)。

    • 原子性:一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
    • 一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
    • 隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
    • 持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

    在 MySQL 命令行的默认设置下,事务都是自动提交的,即执行 SQL 语句后就会马上执行 COMMIT 操作。因此要显式地开启一个事务务须使用命令 BEGIN 或 START TRANSACTION,或者执行命令 SET AUTOCOMMIT=0,用来禁止使用当前会话的自动提交。

    事务控制语句

    • BEGIN 或 START TRANSACTION 显式地开启一个事务;
    • COMMIT 也可以使用 COMMIT WORK,不过二者是等价的。COMMIT 会提交事务,并使已对数据库进行的所有修改成为永久性的;
    • ROLLBACK 也可以使用 ROLLBACK WORK,不过二者是等价的。回滚会结束用户的事务,并撤销正在进行的所有未提交的修改;
    • SAVEPOINT identifier,SAVEPOINT 允许在事务中创建一个保存点,一个事务中可以有多个 SAVEPOINT;
    • RELEASE SAVEPOINT identifier 删除一个事务的保存点,当没有指定的保存点时,执行该语句会抛出一个异常;
    • ROLLBACK TO identifier 把事务回滚到标记点;
    • SET TRANSACTION 用来设置事务的隔离级别。InnoDB 存储引擎提供事务的隔离级别有READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ 和 SERIALIZABLE。

    MYSQL 事务处理

    1、用 BEGIN, ROLLBACK, COMMIT来实现

    • BEGIN 开始一个事务
    • ROLLBACK 事务回滚
    • COMMIT 事务确认

    2、直接用 SET 来改变 MySQL 的自动提交模式:

    • SET AUTOCOMMIT=0 禁止自动提交
    • SET AUTOCOMMIT=1 开启自动提交

    表的修改

    alter

    当我们需要修改数据表名或者修改数据表字段时,就需要使用到MySQL ALTER命令。

    如下命令使用了 ALTER 命令及 DROP 子句来删除以上创建表的 i 字段:

    mysql> ALTER TABLE testalter_tbl  DROP i;
    

    如果数据表中只剩余一个字段则无法使用DROP来删除字段。

    MySQL 中使用 ADD 子句来向数据表中添加列,如下实例在表 testalter_tbl 中添加 i 字段,并定义数据类型:

    mysql> ALTER TABLE testalter_tbl ADD i INT;
    

    执行以上命令后,i 字段会自动添加到数据表字段的末尾。

    移位

    如果你需要指定新增字段的位置,可以使用MySQL提供的关键字 FIRST (设定位第一列), AFTER 字段名(设定位于某个字段之后)。

    尝试以下 ALTER TABLE 语句, 在执行成功后,使用 SHOW COLUMNS 查看表结构的变化:

    ALTER TABLE testalter_tbl DROP i;
    ALTER TABLE testalter_tbl ADD i INT FIRST;
    ALTER TABLE testalter_tbl DROP i;
    ALTER TABLE testalter_tbl ADD i INT AFTER c;
    

    FIRST 和 AFTER 关键字可用于 ADD 与 MODIFY 子句,所以如果你想重置数据表字段的位置就需要先使用 DROP 删除字段然后使用 ADD 来添加字段并设置位置。

    删除外键约束

    keyName是外键别名

    alter table tableName drop foreign key keyName;
    

    修改名称和类型

    如果需要修改字段类型及名称, 你可以在ALTER命令中使用 MODIFY 或 CHANGE 子句 。

    例如,把字段 c 的类型从 CHAR(1) 改为 CHAR(10),可以执行以下命令:

    mysql> ALTER TABLE testalter_tbl MODIFY c CHAR(10);
    

    使用 CHANGE 子句, 语法有很大的不同。 在 CHANGE 关键字之后,紧跟着的是你要修改的字段名,然后指定新字段名及类型。尝试如下实例:

    mysql> ALTER TABLE testalter_tbl CHANGE i j BIGINT;
    mysql> ALTER TABLE testalter_tbl CHANGE j j INT;
    

    Null 值和默认值的影响

    当你修改字段时,你可以指定是否包含值或者是否设置默认值。

    以下实例,指定字段 j 为 NOT NULL 且默认值为100 。

    mysql> ALTER TABLE testalter_tbl 
        -> MODIFY j BIGINT NOT NULL DEFAULT 100;
    

    如果你不设置默认值,MySQL会自动设置该字段默认为 NULL。

    使用 ALTER 来修改字段的默认值,尝试以下实例:

    mysql> ALTER TABLE testalter_tbl ALTER i SET DEFAULT 1000;
    

    使用 ALTER 命令及 DROP子句来删除字段的默认值,如下实例:

    mysql> ALTER TABLE testalter_tbl ALTER i DROP DEFAULT;
    

    数据表类型

    修改数据表类型,可以使用 ALTER 命令及 TYPE 子句来完成。尝试以下实例,我们将表 testalter_tbl 的类型修改为 MYISAM :

    注意:查看数据表类型可以使用 SHOW TABLE STATUS 语句。

    mysql> ALTER TABLE testalter_tbl ENGINE = MYISAM;
    mysql>  SHOW TABLE STATUS LIKE 'testalter_tbl'G
    

    修改表名

    如果需要修改数据表的名称,可以在 ALTER TABLE 语句中使用 RENAME 子句来实现。

    尝试以下实例将数据表 testalter_tbl 重命名为 alter_tbl:

    mysql> ALTER TABLE testalter_tbl RENAME TO alter_tbl;
    

    索引

    索引分单列索引和组合索引。单列索引,即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引。组合索引,即一个索引包含多个列。

    创建索引时,你需要确保该索引是应用在 SQL 查询语句的条件(一般作为 WHERE 子句的条件)。

    实际上,索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录。

    上面都在说使用索引的好处,但过多的使用索引将会造成滥用。因此索引也会有它的缺点:虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。建立索引会占用磁盘空间的索引文件。


    普通索引

    创建

    CREATE INDEX indexName ON mytable(username(length)); 
    

    如果是CHAR,VARCHAR类型,length可以小于字段实际长度;如果是BLOB和TEXT类型,必须指定 length。

    创建表的时候直接指定

    CREATE TABLE mytable(  
    ID INT NOT NULL,   
    username VARCHAR(16) NOT NULL,  
    INDEX [indexName] (username(length))  
    );  
    

    添加

    ALTER table tableName ADD INDEX indexName(columnName)
    

    删除

    DROP INDEX [indexName] ON mytable; 
    

    唯一索引

    它与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。

    创建索引

    CREATE UNIQUE INDEX indexName ON mytable(username(length)) 
    

    修改表结构

    ALTER table mytable ADD UNIQUE [indexName] (username(length))
    

    创建表的时候直接指定

    CREATE TABLE mytable(  
     
    ID INT NOT NULL,   
     
    username VARCHAR(16) NOT NULL,  
     
    UNIQUE [indexName] (username(length))  
     
    );  
    

    使用ALTER 命令添加和删除索引

    有四种方式来添加数据表的索引:

    • ALTER TABLE tbl_name ADD PRIMARY KEY (column_list):该语句添加一个主键,这意味着索引值必须是唯一的,且不能为NULL。
    • ALTER TABLE tbl_name ADD UNIQUE index_name (column_list): 这条语句创建索引的值必须是唯一的(除了NULL外,NULL可能会出现多次)。
    • ALTER TABLE tbl_name ADD INDEX index_name (column_list): 添加普通索引,索引值可出现多次。
    • ALTER TABLE tbl_name ADD FULLTEXT index_name (column_list):该语句指定了索引为 FULLTEXT ,用于全文索引。

    以下实例为在表中添加索引。

    mysql> ALTER TABLE testalter_tbl ADD INDEX (c);
    

    你还可以在 ALTER 命令中使用 DROP 子句来删除索引。尝试以下实例删除索引:

    mysql> ALTER TABLE testalter_tbl DROP INDEX c;
    

    使用 ALTER 命令添加和删除主键

    主键只能作用于一个列上,添加主键索引时,你需要确保该主键默认不为空(NOT NULL)。实例如下:

    mysql> ALTER TABLE testalter_tbl MODIFY i INT NOT NULL;
    mysql> ALTER TABLE testalter_tbl ADD PRIMARY KEY (i);
    

    你也可以使用 ALTER 命令删除主键:

    mysql> ALTER TABLE testalter_tbl DROP PRIMARY KEY;
    

    删除主键时只需指定PRIMARY KEY,但在删除索引时,你必须知道索引名。

    显示索引

    mysql> SHOW INDEX FROM table_name; G
    

    表操作

    临时表

    MySQL 临时表在我们需要保存一些临时数据时是非常有用的。临时表只在当前连接可见,当关闭连接时,Mysql会自动删除表并释放所有空间。

    如果你使用了其他MySQL客户端程序连接MySQL数据库服务器来创建临时表,那么只有在关闭客户端程序时才会销毁临时表,当然你也可以手动销毁。

    mysql> CREATE TEMPORARY TABLE SalesSummary (
        -> product_name VARCHAR(50) NOT NULL
        -> , total_sales DECIMAL(12,2) NOT NULL DEFAULT 0.00
        -> , avg_unit_price DECIMAL(7,2) NOT NULL DEFAULT 0.00
        -> , total_units_sold INT UNSIGNED NOT NULL DEFAULT 0
    );
    

    当你使用 SHOW TABLES命令显示数据表列表时,你将无法看到 SalesSummary表。

    如果你退出当前MySQL会话,再使用 SELECT命令来读取原先创建的临时表数据,那你会发现数据库中没有该表的存在,因为在你退出时该临时表已经被销毁了。

    DROP TABLE 命令来手动删除临时表。

    用查询直接创建临时表的方式:

    CREATE TEMPORARY TABLE 临时表名 AS
    (
        SELECT *  FROM 旧的表名
        LIMIT 0,10000
    );
    

    复制表

    • 使用 SHOW CREATE TABLE 命令获取创建数据表(CREATE TABLE) 语句,该语句包含了原数据表的结构,索引等。
    • 复制以下命令显示的SQL语句,修改数据表名,并执行SQL语句,通过以上命令 将完全的复制数据表结构。
    • 如果你想复制表的内容,你就可以使用 INSERT INTO ... SELECT 语句来实现。
    mysql> SHOW CREATE TABLE runoob_tbl G;
    *************************** 1. row ***************************
           Table: runoob_tbl
    Create Table: CREATE TABLE `runoob_tbl` (
      `runoob_id` int(11) NOT NULL auto_increment,
      `runoob_title` varchar(100) NOT NULL default '',
      `runoob_author` varchar(40) NOT NULL default '',
      `submission_date` date default NULL,
      PRIMARY KEY  (`runoob_id`),
      UNIQUE KEY `AUTHOR_INDEX` (`runoob_author`)
    ) ENGINE=InnoDB 
    1 row in set (0.00 sec)
    
    ERROR:
    No query specified
    
    
    
    mysql> CREATE TABLE `clone_tbl` (
      -> `runoob_id` int(11) NOT NULL auto_increment,
      -> `runoob_title` varchar(100) NOT NULL default '',
      -> `runoob_author` varchar(40) NOT NULL default '',
      -> `submission_date` date default NULL,
      -> PRIMARY KEY  (`runoob_id`),
      -> UNIQUE KEY `AUTHOR_INDEX` (`runoob_author`)
    -> ) ENGINE=InnoDB;
    Query OK, 0 rows affected (1.80 sec)
    
    
    
    mysql> INSERT INTO clone_tbl (runoob_id,
        ->                        runoob_title,
        ->                        runoob_author,
        ->                        submission_date)
        -> SELECT runoob_id,runoob_title,
        ->        runoob_author,submission_date
        -> FROM runoob_tbl;
    Query OK, 3 rows affected (0.07 sec)
    Records: 3  Duplicates: 0  Warnings: 0
    

    另一种完整复制表的方法:

    CREATE TABLE targetTable LIKE sourceTable;  
    只复制表结构到新表
    
    INSERT INTO targetTable SELECT * FROM sourceTable;
    
    复制表结构及数据到新表
    create table 新表 select * from 旧表 
    # 有*号没AS
    

    可以拷贝一个表中其中的一些字段:

    CREATE TABLE newadmin AS
    (
        SELECT username, password FROM admin
    )
    

    可以将新建的表的字段改名:

    CREATE TABLE newadmin AS
    (  
        SELECT id, username AS uname, password AS pass FROM admin
    )
    

    可以在创建表的同时定义表中的字段信息:

    CREATE TABLE newadmin
    (
        id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY
    )
    AS
    (
        SELECT * FROM admin
    )  
    

    序列

    AUTO_INCREMENT

    MySQL 序列是一组整数:1, 2, 3, ...,由于一张数据表只能有一个字段自增主键, 如果你想实现其他字段也实现自动增加,就可以使用MySQL序列来实现。

    MySQL 中最简单使用序列的方法就是使用 MySQL AUTO_INCREMENT 来定义列。

    在MySQL的客户端中你可以使用 SQL中的LAST_INSERT_ID( ) 函数来获取最后的插入表中的自增列的值。

    UUID

    在mysql5.0之前,如果是多个master复制的环境,无法用自增主键,因为可能重复。在5.0以及之后的版本通过配置自增偏移量解决了整个问题。

    uuid全球唯一。

    什么情况下我们希望用uuid

    1. 避免重复,便于scale,这就是我们做cloud service的时候选择uuid的主要原因
    2. 入库之前可以知道id
    3. 相对安全,不能简单的从uuid获取信息,但是如果自增,则容易暴露信息,如果一个客户id是123456,很容易猜到有客户id是123456.

    在我们实际到项目中会碰到问题,历史数据表的主键id会与数据表的id重复,两张自增id做主键的表合并时,id一定会有冲突,但如果各自的id还关联了其他表,这就很不好操作。

    如果使用UUID,生成的ID不仅是表独立的,而且是库独立的。对以后的数据操作很有好处,可以说一劳永逸。

    UUID有什么问题

    1.uuid有16个字节,比int(4 byte)和bigint(8 byte)占用更多存储空间

    2.由于size和无序性,可能引起性能问题

    缺点:

    1. 影响插入速度, 并且造成硬盘使用率低
    2. uuid之间比较大小相对数字慢不少, 影响查询速度
    3. uuid占空间大, 如果你建的索引越多, 影响越严重

    优点:出现数据拆分、合并存储的时候,能达到全局的唯一性

    uuid 与 自增主键

    InnoDB主索引:叶节点包含了完整的数据记录。这种索引叫做聚集索引。InnoDB 的索引能提供一种非常快速的主键查找性能。不过,它的辅助索引也会包含主键列,所以,如果主键定义的比较大,其他索引也将很大。如果想在表上定义 、很多索引,则争取尽量把主键定义得小一些。InnoDB 不会压缩索引

    聚集索引这种实现方式使得按主键的搜索十分高效,但是辅助索引搜索需要检索两遍索引:首先检索辅助索引获得主键,然后用主键到主索引中检索获得记录。

    (1).如果InnoDB表的数据写入顺序能和B+树索引的叶子节点顺序一致的话,这时候存取效率是最高的。为了存储和查询性能应该使用自增长id做主键。 (如果自增索引作为主键构造B+树,那B+树的创建过程将会很“均匀”,每层铺满才会下一层)

    (2).对于InnoDB的主索引,数据会按照主键进行排序,由于UUID的无序性,InnoDB会产生巨大的IO压力,此时不适合使用UUID做物理主键,可以把它作为逻辑主键,物理主键依然使用自增ID。为了全局的唯一性,应该用uuid做索引关联其他表或做外键。

    如果是uuid的形式,频繁的插入会使innodb频繁地移动磁盘块,写入性能就比较低了。

    重置序列

    如果你删除了数据表中的多条记录,并希望对剩下数据的AUTO_INCREMENT列进行重新排列,那么你可以通过删除自增的列,然后重新添加来实现。 不过该操作要非常小心,如果在删除的同时又有新记录添加,有可能会出现数据混乱

    mysql> ALTER TABLE insect DROP id;
    mysql> ALTER TABLE insect
        -> ADD id INT UNSIGNED NOT NULL AUTO_INCREMENT FIRST,
        -> ADD PRIMARY KEY (id);
    

    设置序列的开始值

    一般情况下序列的开始值为1,但如果你需要指定一个开始值100,那我们可以通过以下语句来实现:

    mysql> CREATE TABLE insect
        -> (
        -> id INT UNSIGNED NOT NULL AUTO_INCREMENT,
        -> PRIMARY KEY (id),
        -> name VARCHAR(30) NOT NULL, 
        -> date DATE NOT NULL,
        -> origin VARCHAR(30) NOT NULL
    )engine=innodb auto_increment=100 charset=utf8;
    

    或者你也可以在表创建成功后,通过以下语句来实现:

    mysql> ALTER TABLE t AUTO_INCREMENT = 100;
    

    处理重复数据

    防止表中出现重复数据

    你可以在 MySQL 数据表中设置指定的字段为 PRIMARY KEY(主键) 或者 UNIQUE(唯一) 索引来保证数据的唯一性。

    如果你设置了双主键,那么那个键的默认值不能为 NULL,可设置为 NOT NULL。如下所示:

    CREATE TABLE person_tbl
    (
       first_name CHAR(20) NOT NULL,
       last_name CHAR(20) NOT NULL,
       sex CHAR(10),
       PRIMARY KEY (last_name, first_name)
    );
    

    INSERT IGNORE INTO 与 INSERT INTO 的区别就是 INSERT IGNORE 会忽略数据库中已经存在的数据,如果数据库没有数据,就插入新的数据,如果有数据的话就跳过这条数据。这样就可以保留数据库中已经存在数据,达到在间隙中插入数据的目的。

    以下实例使用了 INSERT IGNORE INTO,执行后不会出错,也不会向数据表中插入重复数据:

    mysql> INSERT IGNORE INTO person_tbl (last_name, first_name)
        -> VALUES( 'Jay', 'Thomas');
    Query OK, 1 row affected (0.00 sec)
    mysql> INSERT IGNORE INTO person_tbl (last_name, first_name)
        -> VALUES( 'Jay', 'Thomas');
    Query OK, 0 rows affected (0.00 sec)
    

    INSERT IGNORE INTO 当插入数据时,在设置了记录的唯一性后,如果插入重复数据,将不返回错误,只以警告形式返回。 而 REPLACE INTO 如果存在 primary 或 unique 相同的记录,则先删除掉。再插入新记录。

    另一种设置数据的唯一性方法是添加一个 UNIQUE 索引,如下所示:

    CREATE TABLE person_tbl
    (
       first_name CHAR(20) NOT NULL,
       last_name CHAR(20) NOT NULL,
       sex CHAR(10),
       UNIQUE (last_name, first_name)
    );
    

    统计重复数据

    以下我们将统计表中 first_name 和 last_name的重复记录数:

    mysql> SELECT COUNT(*) as repetitions, last_name, first_name
        -> FROM person_tbl
        -> GROUP BY last_name, first_name
        -> HAVING repetitions > 1;
    

    以上查询语句将返回 person_tbl 表中重复的记录数。 一般情况下,查询重复的值,请执行以下操作:

    • 确定哪一列包含的值可能会重复。
    • 在列选择列表使用COUNT(*)列出的那些列。
    • 在GROUP BY子句中列出的列。
    • HAVING子句设置重复数大于1。

    过滤重复数据

    如果你需要读取不重复的数据可以在 SELECT 语句中使用 DISTINCT 关键字来过滤重复数据。

    mysql> SELECT DISTINCT last_name, first_name
        -> FROM person_tbl;
    

    你也可以使用 GROUP BY 来读取数据表中不重复的数据:

    mysql> SELECT last_name, first_name
        -> FROM person_tbl
        -> GROUP BY (last_name, first_name);
    

    删除重复数据

    如果你想删除数据表中的重复数据,你可以使用以下的SQL语句:

    mysql> CREATE TABLE tmp SELECT last_name, first_name, sex FROM person_tbl  GROUP BY (last_name, first_name, sex);
    mysql> DROP TABLE person_tbl;
    mysql> ALTER TABLE tmp RENAME TO person_tbl;
    

    当然你也可以在数据表中添加 INDEX(索引) 和 PRIMAY KEY(主键)这种简单的方法来删除表中的重复记录。方法如下:

    mysql> ALTER IGNORE TABLE person_tbl
        -> ADD PRIMARY KEY (last_name, first_name);
    

    导出/入数据

    SELECT ... INTO OUTFILE 语句导出数据

    以下实例中我们将数据表 runoob_tbl 数据导出到 /tmp/runoob.txt 文件中:

    mysql> SELECT * FROM runoob_tbl 
        -> INTO OUTFILE '/tmp/runoob.txt';
    

    你可以通过命令选项来设置数据输出的指定格式,以下实例为导出 CSV 格式:

    mysql> SELECT * FROM passwd INTO OUTFILE '/tmp/runoob.txt'
        -> FIELDS TERMINATED BY ',' ENCLOSED BY '"'
        -> LINES TERMINATED BY '
    ';
    

    在下面的例子中,生成一个文件,各值用逗号隔开。这种格式可以被许多程序使用。

    SELECT a,b,a+b INTO OUTFILE '/tmp/result.text'
    FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
    LINES TERMINATED BY '
    '
    FROM test_table;
    

    mysqldump导出表

    mysqldump 是 mysql 用于转存储数据库的实用程序。它主要产生一个 SQL 脚本,其中包含从头重新创建数据库所必需的命令 CREATE TABLE INSERT 等。

    使用 mysqldump 导出数据需要使用 --tab 选项来指定导出文件指定的目录,该目标必须是可写的。

    以下实例将数据表 runoob_tbl 导出到 /tmp 目录中
    $ mysqldump -u root -p --no-create-info 
                --tab=/tmp RUNOOB runoob_tbl
    password ******
    
    
    导出 SQL 格式的数据到指定文件
    $ mysqldump -u root -p RUNOOB runoob_tbl > dump.txt
    password ******
    
    
    需要备份所有数据库,可以使用以下命令:
    $ mysqldump -u root -p --all-databases > database_dump.txt
    password ******
    

    导入表

    如果你需要将备份的数据库导入到MySQL服务器中,可以使用以下命令,使用以下命令你需要确认数据库已经创建:

    $ mysql -u root -p database_name < dump.txt
    password *****
    

    使用 mysql 命令导入语法格式为:

    mysql -u用户名    -p密码    <  要导入的数据库数据(runoob.sql)
    

    MySQL 中提供了LOAD DATA INFILE语句来插入数据。 以下实例中将从当前目录中读取文件 dump.txt ,将该文件中的数据插入到当前数据库的 mytbl 表中。

    mysql> LOAD DATA LOCAL INFILE 'dump.txt' INTO TABLE mytbl;
    

     如果指定LOCAL关键词,则表明从客户主机上按路径读取文件。如果没有指定,则文件在服务器上按路径读取文件。

    如果用户指定一个 FIELDS 子句,它的子句 (TERMINATED BY、[OPTIONALLY] ENCLOSED BY 和 ESCAPED BY) 也是可选的,不过,用户必须至少指定它们中的一个。

    mysql> LOAD DATA LOCAL INFILE 'dump.txt' INTO TABLE mytbl
      -> FIELDS TERMINATED BY ':'
      -> LINES TERMINATED BY '
    ';
      
      
    mysql> LOAD DATA LOCAL INFILE 'dump.txt' 
      -> INTO TABLE mytbl (b, c, a);
    

    mysqlimport

    函数

    含义:一组预先编译好的SQL语句的集合,理解成批处理语句

    函数:有且仅有1 个返回,合适做处理数据后返回一个结果 做查询一个值

    注意:
    1.参数列表包含两部分:参数名 参数类型
    2.函数体:肯定会有return语句,如果没有会报错
    如果return语句放在函数的最后也不报错,但不建议
    3.函数题中仅有一句话,则可以省略begin end
    4.使用 delimter语句设置结束标记
    
    
    
    
    
    
    #二、调用语法
    SELECT 函数名(参数列表)
    执行函数中所有语句 函数中有显示的语句他也能显示 有插入修改也能做,执行完把显示值返回出来
    CREATE FUNCTION myf1() RETURNS INT
    BEGIN
    	DECLARE c INT DEFAULT 0;#定义局部变量
    	SELECT COUNT(*) INTO c #赋值与c
    	FROM employees;    
    	RETURN c;
    END$
  • 相关阅读:
    编程的发展史及Python简介
    计算机的主要部件和组成
    编程二连
    数据库中的数据类型
    数据库概念和基本操作(mysql的操作)
    并发编程之协程
    并发编程之多线程
    网络编程之socket编程
    并发编程之多进程
    网络编程之网络协议
  • 原文地址:https://www.cnblogs.com/friedCoder/p/12677592.html
Copyright © 2020-2023  润新知