Go to comments

兄弟连 MySQL 创建数据表

一、了解MySQL数据库管理系统

1、为什么要选择 mysql 数据库

数据库服务器。是使用一定格式存储大量信息的软件(或程序),

使用数据库程序建立、更新、维护数据就变得极其容易


如果要快速安全的处理大量的数据,就必须使用数据库

系统,

而且不仅是 mysql,各种数据库系统比如 DB2、Oracle、sqlServer 等数据库系统,

都是通过标准的 sql 查询语言,在客户端管理服务器端数据库,可以说现在的网站几乎都是基于数据库的。


2、MySQL 的架构

MySQL 是 c / s 结构的,也就是客户端 client 与服务器 server

首先开启 mysql  程序,开启后 mysql 程序就有了一个端口(mysql 数据库端口  3306,Oracle 数据库端口 1521)


客户端通过 mysql 地址、mysql 允许的用户、端口连接到 mysql 数据库软件


3、启动

mysql 的启动关闭方式

我的电脑右键 - 管理 - 服务和应用程序 - 服务 - mysql(停止/启动)


window 命令行启动 mysql

net stop mysql  停止

net start mysql  启动


Linux 启动或停止

service mysql start    开启

service mysql stop    停止

service mysqld restart 重新启动


4、mysql 目录结构

mysql 目录下只需要了解三个文件


1. my.ini 配置文件

default-character-set=utf8mb4 修改字符集

basedir="D:/xampp/mysql" 修改根路径的位置


2. bin 该目录存的是 mysql 管理和运行客户端、服务器的一些命令

mysql.exe 客户端的命令

mysqladmin.exe 命令行管理的命令

ysqldump.exe 备份的命令


3. data 目录存的是数据库文件,里面每一个文件夹就是一个库,库里面是表。备份时选择相关的目录即可


5、设置 Mysql 的环境变量

1 .我的电脑 -> 右键属性 -> 高级 -> 环境变量

2. 选择用户,比如  summer

3. 选中 Path

4. 点击 编辑按钮

5. 点击 新建按钮,添加路径 D:\xampp\mysql\bin,然后在任意目录下都可以直接使用 bin 目录下的命令了


6、了解数据库的 SQL 语句操作 [重点]

对于数据库服务器里面的数据管理,

必须使用客户机程序成功链接以后,在通过必要的操作指令对其进行操作,这种数据操作指令通常成为 sql


SQL(Structured Query Language) 结构化查询语言


mysql 支持 sql 这种作为自己的数据库查询语言,

sql 是一种专门查询和修改数据库与数据,以及对数据库进行进行管理和维护的标准化语言。


sql 是高级的非过程化的编程语言,

它不要求用户指定对数据的存储方法,也不需要用户了解具体的数据存储方式,

所以具有完全不同底层结构的,不同的数据库系统,可以使用相同的 sql 作为数据库输入与管理的接口。


sql 语句以记录集合作为操作对象,所以 sql 语句接收集合作为输入,返回集合作为输出,

这种集合特性允许一条 sql 语句的输出,作为另一条 sql 语句的输入,所以 sql 语句可以嵌套。

这使 sql 具有极大的灵活性及强大的功能,在大多数情况下在其它语言中,需要一大段程序实现的功能,只需要一个条 sql 语句就可以达到目的,这意味 sql 语句可以写出一些非常复杂的语句来,有的 sql 语句要占好多行才能写出来。


sql 语句结构简洁功能强大,而且比较简单易学,

所以自 IBM 自 1981 年推出 sql 语句以来,sql 语句就得到了广泛的应用,

这些数据库 Oracle, DB2, SQL Server, Mysql...等,基本上都支持 sql 语句作为查询语言。


SQL 语句按照功能不同,又分为 DDL, DML, DQL, DCL


1. DDL

用来定义和管理数据对象,就是创建库,创建表这样的语句

create database 库名;

create table [库名.]表名;  -- 使用 use 库名 后就不用加库名了

drop database 库名;

drop table 表名;


2. DML

用来对数据的操作,

比如创建完数据库、创建完数据表了,表里面有数据了,对数据进行操作,比如插入、更新、删除有影响的语句,也叫数据操作语句

insert into users( id, name ) values ( '1', 'zhangsan' );

update users set name='aa', age='10' where id='1';

delete from 表名 where id = '2';


3. DQL

专门查询数据的语言,

用于查询数据库对象中所包含的数据,能够进行单表查询,链接查询,嵌套查询,以及集合查询等专门查询数据的语句

select * from 表名;


4. DCL

数据控制语句,是用来管理数据库的语言,包含管理权限以及数据的更改

\s  查看状态

show databases;  查看所有库

show tables; 查看所有表

desc 表名; 查看表结构

show variables -- 看配置文件中的变量和值


7、操作 sql 语句

下面简单操作一些这些语句

1. 要想执行 sql 语句,第一步先要连接到数据库服务器

2. 创建一个数据库

3. 选择一个库作为默认的数据库  use 数据库; 


第一步,连接到数据库服务器

 mysql -h域名 -P端口 -u用户名 -p密码 

-h 写远程连接的ip地址或域名

-u 用户名

-p 密码

mysql -hlocalhost -uroot -P3306 -p


查看状态命令

\s

Current database:   当前的数据库

Current user:  root@localhost ;   当前用户是本机的 root 用户

Using delimiter ;   sql 语句的分隔符用分号";"

Server version:        数据库版本

Server characterset: utf8mb4   服务字符集

Db     characterset: utf8mb4     数据库的字符集

Client characterset: gbk    客户端的字符集

Conn.  characterset: gbk   链接的字符集

TCP port:  3306       端口


查看所有的变量(默认配置

show variables;


单独查配置文件的某一个变量,比如时间变量

show variables like 'time_zone';


单独查端口

show variables like 'port';


退出数据库操作系统

 exit; 


下面执行 DDL语句

创建一个数据库 xsdb,然后删除这个数据库

show databases; -- 先看所有库

create database xsdb; -- 创建数据库

drop database xsdb; -- 删除数据库


加上 not exists 创建数据库,如果数据库不存在再创建,这样写在 PHP 程序里不会报错

加上 exists 删除数据库,如果库存在删除,数据库不存在 php 程序中不会报错

create database if not exists xsdb;

drop database if exists xsdb;


创建完数据,在这个库里创建表 users

xsdb.users 意思是在 xsdb 库里创建用户表 users

id int,   字段 id 类型是整形 int

name char(30),   名字字段 name 的类型是字符串型,字符长度是 30 个

age tinyint,   年龄字段是 tinyint 整形的

sex cha(3)r,  性别字段

create table xsdb.users( -- 指定在namedb库里创建用户表users
  id int,
  name char(30),
  age tinyint,
  sex char(3)
);


 use 数据库名 

选择一个数据库作为默认的数据库,然后操作这个库下面所有表的时候,sql 语句里都不用加数据库的名

use xsdb; -- 选择数据库

\s -- 查看 Current database

show tables; -- 查看xsdb库下所有表

desc users;  -- 查看users表的结构

drop table if exists users; -- 如果users表存在,在删除,这样不会报错误信息


创建表的时候加上 not exists,意思是表不存在,在创建表

create table if not exists users( -- users表不存在,在创建表
  id int,
  name char(30),
  age tinyint,
  sex char(3)
);


DML 数据操作语句

数据插入、更新、删除


如果在 PHP 程序里写 sql 语句,

插入值的时候,所有字段都按照"字符串"插入,不管什么类型的,都按单引号写

insert into users values('1', 'lin', '40', '男');


id 字段和 age 字段是整形,为什么还要按照字符串操作呢?

mysql 会自动把他转成列对应的类型,这样在 PHP 程序里不容易出错,

所以 mysql 操作的时候,所有的数据都按照"字符串"处理,mysql 会自动根据字段的类型,是整形或者是字符串类型,自动的去转换。


最好指定插入的字段,

这样不仅可以只插入一部分字段,还可以不考虑插入的顺序

insert into users (id, name, age, sex)values('2', 'lili', '20', '女');


查看插入的数据(属于DQL语句)

select * from users;


更新(修改)数据

update users set name='QiQi' where id = '2';


同时修改两个字段,字段之间用逗号隔开

update users set name='Qi', age='30' where id = '1';


删除数据(注意,必须写where 条件,不然整个表都会被清空)

delete from users where id = '2';


8、查看帮助

如果有些 sql 语句不会写,可以看帮助的使用,按照层次来看帮助


如果不知道帮助能给我们提供什么内容,可以使用命令  ? contents 

categories:

Account Management

Administration

Compound Statements

Data Definition

Data Manipulation

Data Types                   数据类型

Functions

Functions and Modifiers for Use with GROUP BY

Geographic Features

Help Metadata

Language Structure      语言结构

Optimization and Indexes

Plugins

Procedures

Sequences

Storage Engines

Table Maintenance

Transactions

User-Defined Functions

Utility


对应上面的分类,使用问号加类别名字方式,比如  ? Data Types  查看msyql中支持那些数据类型 

For more information, type 'help <item>', where <item> is one of the following

topics:

AUTO_INCREMENT

BIGINT

BINARY

BIT

BLOB

BLOB DATA TYPE

BOOLEAN

CHAR

CHAR BYTE

DATE

DATETIME

DEC

DECIMAL

DOUBLE

DOUBLE PRECISION

ENUM

FLOAT

INT

INTEGER

……


查出了支持的类型后,可以列出的类型里面的 int 类型

 ? int    查看 int 的具体介绍

Name: 'INT'

Description:

INT[(M)] [UNSIGNED] [ZEROFILL]


如果需要快速查到某些项的语法,

可以使用 ? + 关键字 的方法,

比如 show 命令相关  ? show      

创建表结构不会了,查找 create 命令  ? create    

查看更新语句语法  ?update  



MySQL创建数据表(上)

创建数据表的SQL语句模型

数据值和列类型

数据字段属性

创建索引

创建表类型及存储位置

数据l默认字符集

修改表


二. 创建数据表的SQL语句模型

创建数据表,先创建数据库

show databases; -- 查看所有的的库

create database IF NOT EXISTS summerdb charset utf8; -- 创建summerdb库

use summerdb; -- 选择summerdb进入该数据库


 \s  命令

……

Current database   查看一下当前使用的数据库是 summerdb

Current user           当前使用的用户

TCP port                 链接的端口

……


删除数据库

DROP DATABASE IF EXISTS summerdb;


 ? create table   查看创建表的帮助文件


创建数据表的模型都需要什么?

创建表使用的是 DDL,数据对象定义语句,sql 语句虽然不区分大小写,但所有的关键字尽量大写,显着专业吧


1. 一张表必须有字段名(列名),每个列必须有列类型(是整形还是字符串),表可以有多个字段,这是创建表的最基本结构


CREATE TABLE [IF NOT EXISTS] 表名称 (

    字段名1 列类型,

    字段名2 列类型,

    ...

    字段名n 列类型,

);


2. 但是为了确保数据的完整性和一致性,

在创建表的时候,除了必须指定字段名称字段类型([ 中括号] 的意思是可选的部分),为了完整性和一致性最好加上

还需要指定一些 [属性] 

以及一些约束的 [索引] ,比如主键、外键等一些功能


CREATE TABLE [IF NOT EXISTS] 表名称 (

    字段名1  列类型  [属性]  [索引],

    字段名2  列类型  [属性]  [索引],

    ...

    字段名n  列类型  [属性]  [索引],

) ;


3. 表里面的列(字段)有类型,

mysql 表也是分类型的,所以也可以指定 [表类型],当然不指定 [表类型] 会选用默认的类型


CREATE TABLE [IF NOT EXISTS] 表名称 (

    字段名1  列类型  [属性]  [索引],

    字段名2  列类型  [属性]  [索引],

    ...

    字段名n  列类型  [属性]  [索引],

) [表类型]  [表字符集];


4. 然后表可以指定用什么 [字符集] 来存储(除了表可以指定字符集,每个列也可以指定字符集),这就是创建表需要的、必须的几部分


一些建议事项

1. 表名称 和 字段名需要我们自己定义名称,

比如 users 用户表、articles 文章表(因为表里面要存多个记录,所以加 s 是表示复数的意思)


2. 首先 SQL 是不区分大小写的,

但是表名和字段名的命名要有意义,表名和字段名一定要有意义,用英文、英文组合或多个单词的缩写都可以



3. 自己定义的名称最好都是小写的,

创建的表名就是一个文件名,在 mysql/data 文件下,表名转化文件名,库名转换化目录名,

所以不同的操作系统不一样,比如 windows 不区分大小写,Linux 和 UNIX 是区分大小写,大小写有可能使项目运行不了


4. SQL 语句的关键字最好都大写,自己定义的名称最好都小写,这样一看就知道那些是sql语句,那些是自己定义的名称


sql 语句不写分号时可以写多行,如果写到一半想退出,直接用 \c 退出(c小写)

mysql>CREATE TABLE IF NOT EXISTS users(

        ->id INT,

        ->\c


如果写到一半写错了,前面写了一个单引号,'\c' 是退出不了的,怎么怎么办呢?

mysql>CREATE TABLE IF NOT EXISTS users(

        ->id INT'

        '> \c

        '> \c

        '> \c


补上一个单引号后,出现 -> 再 \c 才能退出

mysql> CREATE TABLE IF NOT EXISTS users(

        -> id INT'

        '> \c

        '> \c

        '> '

        '> \c


 USE 数据库名   选择一个数据库,创建一个数据表,表名users

CREATE TABLE IF NOT EXISTS users(
  id INT,
  name CHAR(40)
)CHARSET UTF8;

SHOW TABLES; -- 查看数据表

DESC users; -- 查看表结构


三、列类型(数据值和列类型)

Mysql 数据值和列类型有四种

1. 数值型

2. 字符型

3. 日期型

4. NULL 空型


PHP、JAVA、c 等这些开发语言都可以处理数据库,

PHP里面有八种数据类型,JAVA里面也有八种数据类型,

那 Mysql 应该比这些编程语言里的数据类型还多啊,为什么 mysql 只有四种数据类型?


这四种只是大的分类,每种类型还可以分为更细致的一些分类,

只要是编程语言里有的类型,数据表就能把他的数据存到数据表里面,所以 Mysql 表类型和一般的编程语言的数据分类都差不多。


另外 Mysql 数据库的表是一个二维表,由一个或多个数据列构成的,

每个数据列都有他特定的类型,这个类型就决定了 Mysql 如何看待该列的数据,

我们可以把整形数值存放到字符类型列中,Mysql 则会把整形看成字符串来处理。


Mysql 中的列类型通常有三种(NULL 空是一个值就不看了),每一种列类型还可以细分,下面开始详细学习

1. 数值型

2. 字符型

3. 日期时间型


1、数值型

数值型分为“整形 ”和“浮点型”两种

1. 整形(存整数用的)

    TINYINT          非常小的整型

    SMALLINT       较小的整型

    MEDIUMINT   中等大小的整型

    INT                  标准整型

    BIGINT            大整数型

2. 浮点型(存浮点数)

    float

    double

    decimal


整型(整数)


整型名称说明占用空间存储范围(有符号)存储范围(无符号)
TINYINT非常小的整型1字节(八位的0或1)-128 ~ 1270 ~ 255
SMALLINT较小的整型2字节-32768 ~ 327670 ~ 65535
MEDIUMINT中等大小的整型3字节-8388608 ~ 83886070 ~ 16777215
INT标准的整数型4字节-2147483648 ~ 21474836470 ~ 4294967295
BIGINT大整数型8字节
2^64(2的64次方)


为什么数值型可以分这么细呢?

所有的数据类型往细分,都是按空间大小来区分的,可以存下就可以,

比如,非常小整形 TINYINT,占用一个字节空间,一个字节是八位的二进制 0000 0000 八个0或1,范围在 -128 ~ 127 或者 0 ~ 255 之间

存一个人的年龄有可能就够了(当然年龄很少有往数据库字段里存的,通常存出生日期),

或者存用户权限,1代表有权限,0代表没有权限,就没有必要用4个字节存,用一个字节的就够了


TINYINT 类型

CREATE TABLE IF NOT EXISTS tab1(
  id TINYINT
);

insert into tab1(id) values (100);
insert into tab1(id) values (200);
insert into tab1(id) values (-200);

SELECT id FROM tab1;

+------+

 |   id    |

+------+

 |  100  |    插入100正确的

 |  127  |    200超过了最大值127,就以最大值127显示

 | -128  |    -200低过了最小值-128,就以负的最大值-128显示 

+------+


加一个属性 UNSIGNED,创建一个无符号字段

CREATE TABLE IF NOT EXISTS tab2(
  id TINYINT UNSIGNED
);

insert into tab2(id)values(90);
insert into tab2(id)values(900);
insert into tab2(id)values(-900);

SELECT id FROM tab2;

+------+

 |   id    |

+------+

 |  90    |    90是正确的值是可以的

 |  255  |

 |    0    |

+------+

注意,

Mysql 5.7.18下,超过存储范围,插入是不成功的,并返回错误信息

ERROR 1264 (22003): Out of range value for column 'id' at row 1


浮点数(小数)


小数除了浮点数,还有一个定点数

类型名称占用空间
float(M, D)浮点型4字节
double(M, D)浮点型8字节
decimal(M, D)定点型M+2字节


什么是浮点数,什么是定点数?

浮点数一般用于表示含有小数部分的数值


当一个字段被定义成浮点数类型后,如果插入数据的精度,超过了该列定义的实际精度

1. 那么插入的数值则会被“四舍五入”到实际定义的精度值,然后在插入

2. 四舍五入的过程中不会报错


定点数不同于浮点数

定点数实际上是以字符串形式存放的,所以定点数可以更精确的保存数据

如果实际插入的数值精度,大于字段定义的精度,则 mysql 会发出一些警告,但是 MySQL 会按照实的精度进行插入


下面看浮点数和定点数的区别


float(5, 2)   定义浮点数类型,一共是五位

1. 包括小数一共五位

2. 保留小数点后两位

CREATE TABLE IF NOT EXISTS tab3(
  price FLOAT(5, 2)
);


插入超过范围的数值 1234567.123

insert into tab3 (price)values(1234567.123); -- 插入超过范围的数值

select price from tab3;

+--------+

 |  price   |

+--------+

 |  999.99|   定义的范围一共是五位,五位的最大值是 999.99

+--------+

注意,

Mysql5.7.18版本下,超过存储范围,插入是不成功的,并返回错误信息

ERROR 1264 (22003): Out of range value for column 'price' at row 1


插入 5 位之内的数 123.123,

实际插入的数值精度 大于 实际定义的精度,Mysql 会发出一些警告,然后按照实际定义的精度进行插入

insert into tab3 (price)values(123.123);

select price from tab3;

插入在五位范围之内的小数,存储成功

+--------+

 |  price   |

+--------+

 | 999.99 |

 | 123.12 |

+--------+


浮点数会四舍五入,但是插入 123.125 没有四舍五入

insert into tab3 (price)values(123.125);

select price from tab3;

+--------+

 |  price   |

+--------+

 | 999.99 |

 | 123.12 |

 | 123.12 |   没有四舍五入

+--------+


调整一下,插入大一点的值 123.126

insert into tab3 (price)values(123.126);

select price from tab3;

+--------+

 |  price   |

+--------+

 | 999.99 |

 | 123.12 |

 | 123.12 |

 | 123.13 |   四舍五入了

+--------+


这是因为浮点数存在着误差,

因为浮点数是一个近似数,比如 8.0 其实不是 8,它是 7.99999……

所以浮点数不能用于等号去比较,

比如在 JAVA 和 PHP 里面,如果非要用浮点数比较,最好用使用范围比较,而不是使用等号比较


flaot 类型和 double 类型它两的用法是一样的,下面看定点数 decimal 的例子


decimal 定点类型


用 decimal 定点型 double 浮点类型创建一个表,比较一下两个类型

CREATE TABLE tab4(
  one double(8, 1),
  two decimal(8, 1)
);

DESC tab4;

查看表结构

+-------+--------------+------+-----+---------+-------+

 | Field   | Type             | Null   | Key  | Default  |  Extra  |

+-------+--------------+------+-----+---------+-------+

 | one     | double(8,1)  | YES   |         | NULL     |            |

 | two     | decimal(8,1) | YES   |         | NULL     |            |

+-------+--------------+------+-----+---------+-------+


先插入正确范围内的值 12.3,没有出现任何 warning 警告

insert into tab4(one, two) values (12.3, 12.3);

select one, two from tab4;

插入正确范围的值,是没有问题的

+------+------+

 | one   | two   |

+------+------+

 | 12.3  | 12.3  |

+------+------+


在插入一个 12.38 出现一个警告,

这个警告是定点数字段发出的 Query OK, 1 row affected, 1 warning (0.00 sec) 。上面的 float 类型四舍五入的时候 warning 没有警告

insert into tab4(one, two) values (12.38, 12.38);

select one, two from tab4;

两个字段都四舍五入了

+------+------+

 | one   | two   |

+------+------+

 | 12.3  | 12.3   |

 | 12.4  | 12.4   |   定点数的小数点也四舍五入了(高老师的意思是,定点数不应该四舍五入!

+------+------+


在来换一个12.21,又产生了一个警告 Query OK, 1 row affected, 1 warning (0.00 sec)

insert into tab4(one, two) values (12.21, 12.21);

select one, two from tab4;

+------+------+

 | one   | two  |

+------+------+

 | 12.3  | 12.3  |

 | 12.4  | 12.4  |

 | 12.2  | 12.2  |

+------+------+


以字符串形式插入看看,mysql 会自动转换成"列"对应的类型,插入 12.36 还是产生了一次 warning 警告

insert into tab4(one, two) values ('12.36', '12.36');

select one, two from tab4;

+------+------+

 | one   | two  |

+------+------+

 | 12.3  | 12.3 |

 | 12.4  | 12.4 |

 | 12.2  | 12.2 |

 | 12.4  | 12.4 |  两个存储结果都是 12.4,都四舍五入了,定点数不应该四舍五入啊

+------+------+


下面插入 12.211111,依然产生了一次 warning 警告

insert into tab4(one, two) values (12.211111, 12.211111);

select one, two from tab4;

+------+------+

 | one   | two   |

+------+------+

 | 12.3  | 12.3  |

 | 12.4  | 12.4  |

 | 12.2  | 12.2  |

 | 12.4  | 12.4  |

 | 12.2  | 12.2  |

+------+------+


高老师说这个有点问题,总之浮点数会出现一些误差,

在对浮动数进行操作的时候,它会经常发生一些误差,所以在使用浮点数的时候要特别的小心。


浮动数存在误差的问题,

所以对货币等、对精度铭感的数据应该用定点型(decimal)来表示和存储


在编程中如果用到浮点数,要特别注意误差的问题,并尽量避免做浮点数的比较,

所以要注意浮动数中的一些特殊值的处理,

具体那些特殊值,高老师忘记了什么是特殊值


浮点数跟定点数的区别

1. 浮点数类型数据会因为四舍五入产生误差,所以不适合用于精度要求比较高的运算

2. 定点数 CPU 不能直接对其进行运算,会影响到一些存储效率,

     所以定点数优点就是精确,但是会影响到一些效率,因为存储格式是以字符串形式存的,不能直接进行运算,它要转换一下。


自己总结,

上面插入出现的一系列 warning,是定点数引起的。

定点数要求比较严格,如果超出设置的位数范围,会出 warning 警告信息

decimal(8, 1) 类型只设置了一位小数,只存储一位小数的数就不会出现 warning 警告了

CREATE TABLE dnum(
  num decimal(8, 1)
);

insert into dnum values (12.3);
insert into dnum values (12.2);
insert into dnum values (12.3);
insert into dnum values (12.1);

select * from dnum;


2、字符型

字符串可以用来表示任何一种数据类型,

包括整数、浮点数也可以用字符串类型来存储,

我们可以用字符串类型存储图像或者声音之类的二进制数据,也可以存储压缩的数据


mysql 支持单引号或双引号的字符串,

1. 比如存数据的时候,双引号 "mysql" 或者是单引号 'mysql' 都是可以的

2. mysql 能识别 PHP 程序字符串中的转义字符 \


char 和 varchar


char 和 varchar 它两最大存储空间都 255 个字符,超过 255 个字符会被截断,

我们也可以指定长度,char(m) 只要指定一个 m 长度,指定多长就可以存储多长


注意:

网上查了 varchar 最大长度

MySQL 4.1 以下的版本中的最大长度限制为 255

MySQL 5.0 以上的版本中, varchar 数据类型的长度支持到了65535, 也就是说可以存放 65532 个字节的数据

https://www.cnblogs.com/M-D-Luffy/p/4125900.html


创建数据表,

name 名字列,指定 10 个字符,

description 介绍列,也用 10 个字符

CREATE TABLE IF NOT EXISTS tab5(
  name char(10),
  description varchar(10)
);


插入 3 个字符,长度在 10 个以内的字符串是没有问题的

insert into tab5 (name, description)values('abc', 'abc');

select name, description from tab5;

+------+-------------+

 | name| description |

+------+-------------+

 | abc   | abc              |

+------+-------------+


如果插入超过 10 个字符的范围,会出现两个 warnings 警告 Query OK, 1 row affected, 2 warnings (0.00 sec)

insert into tab5 (name, description)values('abcdefghigkmln', 'abcdefghigkmln');

select name, description from tab5;

+------------+-------------+

 | name         | description |

+------------+-------------+

 | abc            | abc              |

 | abcdefghig| abcdefghig |  超过 10 字符只会储存 10 个字符

+------------+-------------+


char 和 varchar 都是存储字符串的,不同的是它们保存和解锁的方式不同

char 属于固定长度字符串

varchar 属于可变长度字符串


什么是固定长度和可变长度呢?

比如 char(4) 和 varchar(4) 都设置 4 个字节

1. 储存 '' 空字符串

    char(4) 占4字节

    varchar(4) 占1字节

2. 存储 'ab' 2个字符

    char(4) 还是占4字节

    varchar(4) 占3字节

3. 储存 'abcd' 正好范围 4 个字符

    char(4) 还是占4字节

    而 varchar(4) 占5字节,它永远比字符多一个字节

4. 'abcdefg' 超过储存范围,超过范围会被截断 

    char(4) 还是占 4 字节

    varchar(4) 占 5 字节


总结

varchar 类型根据内容不同,永远是内容加一个字节,永远多占一个字节

char 永远是固定长度字节,不管是不存,还是存储都是这样的


另外

varchar 和 char 解锁的值并不总是相同的,

就算存相同的值也不是总相同的,因为解锁时 char 类型的列会删除尾部的空格


看一下 char 类型删除尾部的空格

tab6 表中的列都设置 4 个字符长度,插入的  "ab "  后面有空格,长度是 3 个字符

create table tab6(
  v varchar(4),
  c char(4)
);

insert into tab6 (v, c)values('ab ', 'ab '); -- 插入"ab "后面有空格,长度是3个字符

select v, c from tab6;

存储的都是 ab,看不出什么不同,但是他们的解锁方式不同

+------+------+

 | v       |    c    |

+------+------+

 | ab     |   ab   |

+------+------+


下面用一下系统里面提供的函数,链接用函数  concat() ,给两个字段都链接一个 # 号

select concat(v,"#"), concat(c,"#") from tab6;

会看到解锁的方式不同

1. v 字段声明的是 varchar 类型,不会删除空格

2. 而 c 字段的 char 类型删除了空格,这就是解锁方式的不同

+---------------+---------------+

 | concat(v,"#") | concat(c,"#")  |

+---------------+---------------+

 | ab #               | ab#                |

+---------------+---------------+


什么时候用 char?

1. char 是固定长度,所以处理速度要比 varchar 要快的多

2. 如果字段长度是固定的,比如性别字段,长度不是变化的就用 char 声明,速度会比 varchar 快的多

3. char 的缺点是浪费存储空间,对于长度变化不大的,并对查询速度有要求的数据用 char 类型


什么时候用 varchar?

1. 变化比较大,比如文章标题变化比较大,有的标题是 2个字,有的是 20个字,用 varchar 类型,但是速度不如 char 快

2. 另外随着 mysql 版本的不断升级,varchar 性能也不断的改进在提高,所以在许多应用中 varchar 类型都被更多的使用


字符类型的 char 和 varchar 的长度才 255 个(varchar 类型 mysql5 以上,存储长度不是255了),下面看另外几种字符串类型


text 和 blob 类型


一般报存少量字符串的时候,我们选择用 var 和 varchar,而保存较文本的时候采用 text 和 blob 类型


text 和 blob的区别

blob 类型,用来保存二进制数据,比如照片、电影、压缩包等…

text 类型,保存文本数据,比如文章、日记、评论、商品介绍等…


text 文本数据

类型长度
text2^16 - 1文本
MEDIUMTEXT2^24 - 1中型文本
LONGTEXT2^32 - 1长文本

 

blob  二进制数据

类型长度
blob2^16 - 1
MEDIUMBLOB2^24 - 1
LONGBLOB2^32 - 1大概可以存几个g


创建一个存照片的表,存图片的二进制的内容

create table tab7(
  img blob
);


字符串还有 ENUM 和 SET 这两种类型


ENUM 和 SET 占用的空间是很少的

ENUM 是枚举类型

SET 是集合类型


为什么字符串用 ENUM 枚举类型会占这么少的空间呢?

1. 因为枚举就相当一个标号一样,比如枚举类型列    ENUM("one", "two", "three", "four")   列举出这四个值

2. 某个列设置了这个枚举类型,只能有这四个值

3. 为什么能占一个字节呢?就像数组一样,通过下标去取里面的某一个值


ENUM 枚举类型和 SET 集合类型区别是什么?

ENUM 枚举,占用 1 或 2 字节,一次只能存一个值,最多有 65535 个成员

SET 集合,1,2,3,4,8 字节,因为可以存多个值,最多有 64 个成员


创建枚举和集合类型的表

one 字段枚举类型,里面只能存 a, b, c, d

flag 字段集合类型,里面也是 a, b, c, d

create table tab7(
  one ENUM("a", "b", "c", "d"),
  flag set('a', 'b', 'c', 'd') 
);

insert into tab7 values('a', 'a');

select * from tab7;

插入的 'a' 都是可以的,因为 'a' 的值在枚举和集合之中

+------+------+

 | one   |  flag  |

+------+------+

 | a       |  a      |

+------+------+


但是插入 'w',出现两个警告 Query OK, 1 row affected, 2 warnings (0.00 sec)

insert into tab7 values('w', 'w');

select * from tab7;

数据表存储是空的,因为 'w' 不在枚举和集合中

+------+------+

 | one   | flag   |

+------+------+

 | a       | a       |

 |          |          |

+------+------+


枚举和集合什么区别呢?

比如插入 'a, b' 两个值,出现一个警告 Query OK, 1 row affected, 1 warning (0.00 sec)

insert into tab7 values('a,b', 'a,b');

select * from tab7;

集合字段 flag 插入进去了,

而枚举 one 字段没有插入进去是空的

+------+------+

 | one   | flag   |

+------+------+

 | a       | a       |

 |          |          |

 |          | a,b    |

+------+------+


也就说枚举和集合区别是

ENUM("a", "b", "c", "d")  枚举一次只能使用的一个值

set('a', 'b', 'c', 'd')  集合一次可以用多个集合里面的值,插入时多个值,中间使用逗号分开


枚举和集合占用空间少,在设计表的时候,如果是固定的几个值,

比如性别,就 "男、女、保密" 两个值或三个值,可以用枚举,

存星期,一共就七天也可以用枚举类型,

如果想存枚举里面的多个值就用集合,多个值用 "," 分开就可以了,所以集合占用的字节不固定的(1,2,3,4,8字节),要看存多少个值


3、日期型

有这么几个日期类型

类型格式

DATEYYYY-MM-DD年-月-日专门存日期的
TIMEhh:mm:ss时:分:秒专门存时间的
DATETIMEYYYY-MM-DD hh:mm:ss
专门存期和时间
TIMESTAMPYYYYMMDDhhmmss
存时间邮戳
YEARYYYY
四位的年


创建表

create table if not exists tab8(
  id tinyint unsigned primary key auto_increment,
  one date,
  two time,
  three datetime,
  four timestamp,
  five year
)charset utf8;


插入字符串形式的 '2010-12-03' mysql 会自动的转成日期类型

insert into tab8 (one) values ('2010-12-03');

select * from tab8;

one 字段是 date 类型,four 是默认的先不看

+----+------------+------+------+---------------------+------+

 |   id |      one        | two  | three |        four                  |  five  |

+----+------------+------+------+---------------------+------+

 |   1  |2010-12-03 |NULL | NULL |2021-08-20 11:50:08 | NULL |

+----+------------+------+------+---------------------+------+


还可以这样 '20101203' 存,只要位数够了也可以

insert into tab8 (d) values ('20101203');

select * from tab8;

+----+------------+------+------+---------------------+------+

 |   id |      one         | two | three |        four                  |  five  |

+----+------------+------+------+---------------------+------+

 |  1   | 2010-12-03| NULL| NULL | 2021-08-20 11:50:08 | NULL |

 |  2   | 2010-12-03| NULL| NULL | 2021-08-20 11:53:06 | NULL |

+----+------------+------+------+---------------------+------+


two 字段 TIME 类型存储时间,插入 '11:55:52'

insert into tab8 (d, t) values ('20101203', '11:55:52');

select * from tab8;

+----+------------+----------+------+---------------------+------+

  |   id |      one       |     two    | three |        four                  |  five  |

+----+------------+----------+------+---------------------+------+

 |  1   | 2010-12-03 | NULL     | NULL | 2021-08-20 11:50:08 | NULL |

 |  2   | 2010-12-03 | NULL     | NULL | 2021-08-20 11:53:06 | NULL |

 |  3   | 2010-12-03 | 11:55:52| NULL | 2021-08-20 11:56:12 | NULL |

+----+------------+----------+------+---------------------+------+


时间也可以连写 '115707',只要位数够了就行

insert into tab8 (d, t) values ('20101203', '115707');

select * from tab8;

+----+------------+----------+------+---------------------+------+

 |   id |      one       |     two     | three |        four                  |  five  |

+----+------------+----------+------+---------------------+------+

 |  1   | 2010-12-03 | NULL     | NULL | 2021-08-20 11:50:08 | NULL |

 |  2   | 2010-12-03 | NULL     | NULL | 2021-08-20 11:53:06 | NULL |

 |  3   | 2010-12-03 | 11:55:52 | NULL | 2021-08-20 11:56:12 | NULL |

 |  4   | 2010-12-03 | 11:57:07 | NULL | 2021-08-20 11:57:29 | NULL |

+----+------------+----------+------+---------------------+------+


而且时间还可以默认写两位,比如 '1158' 只有分钟和秒,不写小时

insert into tab8 (d, t) values ('20101203', '1158');

select * from tab8;

+----+------------+----------+------+---------------------+------+

 |   id |      one       |      two    | three |        four                  |  five  |

+----+------------+----------+------+---------------------+------+

 |  1 | 2010-12-03 | NULL     | NULL | 2021-08-20 11:50:08 | NULL |

 |  2 | 2010-12-03 | NULL     | NULL | 2021-08-20 11:53:06 | NULL |

 |  3 | 2010-12-03 | 11:55:52 | NULL | 2021-08-20 11:56:12 | NULL |

 |  4 | 2010-12-03 | 11:57:07 | NULL | 2021-08-20 11:57:29 | NULL |

 |  5 | 2010-12-03 | 00:11:58 | NULL | 2021-08-20 11:58:19 | NULL |

+----+------------+----------+------+---------------------+------+


three 字段是 datetime 类型是 年月日时分秒,插入'2010-12-03 12:01:21'

insert into tab8 (d, t, dt) values ('20101203', '120121', '2010-12-03 12:01:21');

select * from tab8;

+----+------------+----------+---------------------+---------------------+------+

 |   id |      one       |     two     |              three          |        four                  |  five  |

+----+------------+----------+---------------------+---------------------+------+

 |  1  | 2010-12-03 | NULL      |       NULL                | 2021-08-20 11:50:08 | NULL |

 |  2  | 2010-12-03 | NULL      |       NULL                | 2021-08-20 11:53:06 | NULL |

 |  3  | 2010-12-03 | 11:55:52 |       NULL                | 2021-08-20 11:56:12 | NULL |

 |  4  | 2010-12-03 | 11:57:07 |       NULL                | 2021-08-20 11:57:29 | NULL |

 |  5  | 2010-12-03 | 00:11:58 |       NULL                | 2021-08-20 11:58:19 | NULL |

 |  6  | 2010-12-03 | 12:01:21 | 2010-12-03 12:01:21| 2021-08-20 12:02:38 | NULL|

+----+------------+----------+---------------------+---------------------+------+


four 字段 TIMESTAMP 类型,默认的就是当前时间

five 字段 YEAR 类型,就存四位的年就可以了


创建表时最好不要使用这些类型中的时间格式,虽然有一个时间邮戳,但是不是 PHP 中时间邮戳

PHP 中时间戳是从 1970-1-1 0:0:0 到现在的秒数,是一整数,整数特别容易参与运算,

实际应用中用整数 int 类型保存时间 time() 时间戳


4、下一章预告

MySQL 创建数据表(中)

上面是 mysql 数据库创建表的上的部分,为确保数据的完整性和一致性,在创建表的时候

除了指定字段名称、字段类型之外,还需要为字段指定一些属性,

而且需要使用一些约束条件,比如索引,主键索引、唯一索引等等,

还需要设置表的表类型,字符集等等


上半部分重点主要是创建表的列类型,除了列类型还有一些可选部分,这部分内容主要有

1. 数据字段属性

2. 创建索引

3. 数据表类型及存储位置

4. Mysql 默认字符集

5. 修改表


四、字段属性

指定了数据的字段和数据类型是不够的,还要指定一些附加的属性


数据字段的属性

1. 无符号 unsigned

2. 前导 0  zerofill

3. 自动增长 AUTO_INCREMENT

4. 非空 not null

5. 缺省值 default


1. unsigned 属性


该属性 unsigned 作用设置无符号,也就是不允许这个数据列出现负数,可以让空间增加一倍


怎么让空间增加一倍的呢?

比如 tinyint 类型 的范围是 -128 ~ 127 之间,增加一倍没有负数了,就变成了 0 ~ 255

无符号属性只能用在数值型字段,数值型字符分整数和浮点数(字符串和日期没有符号)


创建 t1 表,id 字段 是 int 整数类型,用无符号设置该字段,id 就不能插入负数了

create table if not exists t1(
  id int unsigned
);

insert into t1 values(100);

select id from t1;

插入 100 是正常

+------+

 |   id    |

+------+

 |  100  |

+------+


如果插入 -100 负一百呢?

1. 出现一个警告 Query OK, 1 row affected, 1 warning (0.00 sec)

2. 会按照字段的极限值存储,极限值的最小值就是 0

insert into t1 values(-100);

select id from t1;

+------+

 |   id    |

+------+

 |  100  |

 |    0    |

+------+


如果不需要插入负数,就用 unsigend 属性来修饰改字段,另外只有数值型能用


Ps:

超出储存范围,有些 Mysql 数据库插入不进去并且会报错,可能与 Mysql 配置或者版本有关

ERROR 1264 (22003): Out of range value for column 'id' at row 1


2. zerofill


zerofill 直接翻译是“零填充”

1. 该属性只能用在数值型字段

2. 作用是“前导0”,前导0 的意思是在数值之前,自动用 0 补齐不足的位置

3. 加上前导零 zerofill 属性,该字段自动应用 UNSIGNED 属性


例子,

float(7,2)  浮点类型的意思是长度总限制7位,小数点后面有2位

varchar(10)  字符类型括号里写 10,意思是最多不能超过 10 个字符


float(7,2) 和 varchar(10) 这两个里面的参数,都是限制长度的

int(5) 只有整数的括号里面的参数 5 是限制不了长度的,不要看括号里面写了 5,只要不超过 int 整数的存储范围就可以


int 类型和 float 类型都加了前导零属性 zerofill

create table t2(
  num int(5) zerofill,
  price float(7, 2) zerofill,
  name varchar(10)
);

desc t2;

查看表结构

因为有符号的是不能加"前导零"属性的,

加"前导零"属性该字段,自动应用 UNSIGNED 无符号属性,有了无符号 unsigned、前导零 zerofill 两个属性

+-------+------------------------------+------+-----+---------+-------+

 | Field   | Type                                    | Null   | Key   | Default |  Extra  |

+-------+------------------------------+------+-----+---------+-------+

 | num    | int(5) unsigned zerofill       | YES    |         | NULL    |            | 

 | price   | float(7,2) unsigned zerofill  | YES    |         | NULL    |            | 

 | name  | varchar(10)                          | YES    |         | NULL    |            |

+-------+------------------------------+------+-----+---------+-------+


下面插入数据都超过设置的值,插入操作返回两个警告 Query OK, 1 row affected, 2 warnings (0.009 sec)

num 字段插入八位 '88888888'

price 字段插入 '1234567.123'

name 字段插入"黄图霸业谈笑中,不负人生一场醉"

insert into t2(num, price, name)values('88888888', '1234567.123', '黄图霸业谈笑中,不负人生一场醉');

select * from t2;

可以看到整数 num 字段插入的'88888888' 八位是可以的,因为 int(5) 括号里面的 5 是限制不住长度的

price 字段和 name 字段都被限制住了

+----------+----------+----------------------+

 | num        |    price    | name                       |

+----------+----------+----------------------+

 | 88888888| 99999.99| 黄图霸业谈笑中,不负 |

+----------+----------+----------------------+


Ps:

有些版本 Mysql 插入不成功,并且报出错误信息

ERROR 1264 (22003): Out of range value for column 'price' at row 1


 int(5) 加了前导零 zerofill 属性有什么作用呢?

就插入 num、price 两个字段,

num 字段插入小于 5 位,price 字段小于 7 位数会怎么样


num 字段写两位 '88'

price 字段写两位 '12.123'

insert into t2 (num, price, name) values ('88', '12.123', '这个没有关系了');

select * from t2;

整数 和 浮点数字段前面都加了 0,

整数保证是有 5 位,

浮动数前加了两个 0,这就是前导 0 的作用

+----------+----------+----------------------+

 | num       | price        | name                       |

+----------+----------+----------------------+

 | 88888888| 99999.99| 黄图霸业谈笑中,不负|

 |    00088  |  0012.12  | 这个没有关系了        |

+----------+----------+----------------------+


3. AUTO_INCREMENT 自动增长


AUTO_INCREMENT 是设置字段自动增产的属性

1. 设置这个属性,也只能是整数类型

2. 数据每增加一条,就会在原有的字段值自动增加 1

3. 而且这个字段的值是不充许重复


使用 auto_increment 属性修饰的字段,在插入新数据的时候,

1. 当自动添加为 NULL、0、留空,这三种情况都会在此字段上自动加 1,作为此次字段的值

2. 插入的时候,也可以指定某一非 0 的数值,

     这时如果表中已存在此值将会出错,

     否则使用指定的值,作为自动的值,而且下次插入时,下一个字段的值就在此字段基础上加 1

3. 所以想作为自动增长,还要加上 primary key 唯一索引属性,因为字段值不能重复


下面是有自动增加字段的表,能创建成功吗?

create table t3(
  id int auto_increment,
  name char(10)
);

没有创建成功 ERROR 1075 (42000): Incorrect table definition; there can be only one auto column and it must be defined as a key


为什么没有创建成功?

因为这么直接创建自增长列是不行的,列的值必须不能重复,加上不重复的键索引 primary key 就可以了

create table t3(
  id int auto_increment primary key,
  name char(10)
);


所以加 primary key 索引的目的,

是让这个列的值不能重复,下面看看是怎么自动增长


id 字段插入一个空值 null,

null 空是一个值,表示没有的意思

insert into t3 (id, name)values(null, '淡淡');
insert into t3 (id, name)values(null, '轻轻');
insert into t3 (id, name)values(null, '余温');

select id, name from t3;

连续插入三次,id 字段自动增长了

+----+------+

 | id   | name |

+----+------+

 |  1   | 淡淡   |

 |  2   | 轻轻   |

 |  3   | 余温   |

+----+------+


或者 id 字段插入 0

insert into t3 (id, name)values(0, '岁月');
insert into t3 (id, name)values(0, '积攒');
insert into t3 (id, name)values(0, '干枯');

select id, name from t3;

d 字段也是可以自动增长的

+----+------+

 | id   | name |

+----+------+

 |  1   | 淡淡  |

 |  2   | 轻轻  |

 |  3   | 余温  |

 |  4   | 岁月  |

 |  5   | 积攒  |

 |  6   | 干枯  |

+----+------+


或者 id 字段留空,怎么留空呢?

id 字段不插入,只插入一个 name 字段

insert into t3 (name)values('雕琢');
insert into t3 (name)values('一席');
insert into t3 (name)values('交织');

select id, name from t3;

id 字段也会自动增长

+----+------+

 | id   | name |

+----+------+

 |  1   | 淡淡  |

 |  2   | 轻轻  |

 |  3   | 余温  |

 |  4   | 岁月  |

 |  5   | 积攒  |

 |  6   | 干枯  |

 |  7   | 雕琢  |

 |  8   | 一席  |

 |  9   | 交织  |

+----+------+


如果删除了一些数据,有空缺了,

在插入是把删除的空缺的补上,还是在最大值上加 1 呢?分两种情况来说,


第一种,

先删除一部分,比如把 id 大于1,小于 10 的都删掉了

delete from t3 where id > 1 and id < 9;

select id, name from t3;

删除后剩下两条数据

+----+------+

 | id   | name |

+----+------+

 |  1   | 淡淡   |

 |  9   | 交织   |

+----+------+


在插入

insert into t3 (id, name)values(0, '岁月');
insert into t3 (id, name)values(0, '积攒');
insert into t3 (id, name)values(0, '干枯');

select id, name from t3 order by id; -- 按排序查看

+----+------+

 | id   | name |

+----+------+

 |  1   | 淡淡  |

 |  9   | 交织  |

 | 10  | 岁月  |

 | 11  | 积攒  |

 | 12  | 干枯  |

+----+------+


第二种,

删除表里的全部数据

全部删除,一条记录都没有了,表里 id 最大值是 12

delete from t3; -- Query OK, 5 rows affected (0.003 sec) 受影响的五条数据 

select id, name from t3; -- Empty set (0.001 sec) 查询表是空的


再插入

insert into t3 (name)values('雕琢');
insert into t3 (name)values('一席');
insert into t3 (name)values('交织');
insert into t3 (name)values('积攒');
insert into t3 (name)values('干枯');

select id, name from t3;

id 值是从最大值 12 的基础上增加

+----+------+

 | id   | name |

+----+------+

 | 13  | 雕琢   |

 | 14  | 一席   |

 | 15  | 交织   |

 | 16  | 积攒   |

 | 17  | 干枯   |

+----+------+

永远是从插入过的最大值增加


那可以不可以指定一个数值,插入到自增长字段呢?

比如,id 字段插入一个 100 的数值,在插入一个条数据,结果是什么样呢

insert into t3 (id, name)values(100, '淡淡');

insert into t3 (name)values('余温');

select id, name from t3;

+-----+------+

 | id     | name|

+-----+------+

 |  13   | 雕琢  |

 |  14   | 一席  |

 |  15   | 交织  |

 |  16   | 积攒  |

 |  17   | 干枯  |

 | 100  | 淡淡  |  如果手动的插入一个最大值,

 | 101  | 余温  |  它会从最大值后面加 1,这就是自动增长的属性

+-----+------+


建议,每张表都最好有一个ID字段,设置为自动增长 auto_increment


4. NULL 和 NOT NULL


如果表里面不指定空 NULL 和非空 NOT NULL,那么默认值就是空值 NULL

空 NULL 是一个值,它不是没有也不是空,它相当于是一种单独的类型,就是空数据


将来将这个表的数据转为 PHP 程序的数据时

1. 整数列里面有 NULL值,能转成 PHP 的 0 吗?

2. 字符串列里面有 NULL 值,能转成 PHP 的这种 '' 空字符串吗?

3. double 类型的空置,能转成 PHP 的 0.00 吗?

这些都不一定,所以建议在创建表时,每个字段都不要插入空值 NULL

因为 NULL 值读取的数据,转成 PHP 变量的时候不一定转成我们想要的值,我们不好处理,所以创建表的时候使用飞空 not null 属性,这样就插入不了空值了


每个字段都加上 not null(非空)

create table t4(
  id int not null,
  name varchar(30) not null,
  price double not null
);

insert into t4 values(null, null, null);

这样插入空值 NULL 的时候,

返回错误 ERROR 1048 (23000): Column 'id' cannot be null,告诉我们 id 列不能为空,空值就不能插入,

这样就必须插入数据


如果就想留空或者不插入值的时候怎么办呢?

比如就插入 name 列,

其它 id、price 列不插入值的时候,返回两个警告 Query OK, 1 row affected, 2 warnings (0.002 sec)

insert into t4 (name)values('aaa');

select * from t4;

id 列和 price 自动转成默认 0,不是之前的空值了 null

+----+------+-------+

 |  id  | name | price  |

+----+------+-------+

 |  0   | aaa    |     0     |

+----+------+-------+

如果 id 列、price 列不设置 not null,这两个列都会是空 null,

但是价钱字段 price 默认 0 也不太好,所以用 default 属性和 NOT NULL 配合用


5. default 属性是缺省值


id 列,非空缺省值用的是 0

name 列,缺省值用的是 '' 字符串的空,这种空值转成 PHP 程序的的时候,就会直接转成空字符串,因为 name 字段是字符串类型的

price 列(价钱),不传值用的缺省值是 0.00

create table t5(
  id int not null default 0,
  name varchar(30) not null default '',
  price double not null default '0.00'
);

insert into t5 (name)values('aaa'); -- 插入时没有警告了

select * from t5;

+----+------+-------+

 |  id  | name| price   |

+----+------+-------+

 |  0   | aaa    |     0     |

+----+------+-------+


这次只插入 price 字段

insert into t5 (price) value (12.8);

select * from t5;

name 列默认的是 '' 字符串的空

+----+------+-------+

 |  id  | name| price   |

+----+------+-------+

 |  0   | aaa    |     0     |

 |  0   |           |  12.8   |

+----+------+-------+


下面创建一个完整的用户表,

把上面的这些属性全用上,创建一个用户表

id 字段,INT 类型、UNSIGNED 无符号(空间能增加一倍)、NOT NULL 非空、AUTO_INCREMENT 自动增长、PRIMARY KEY 主键

name 字段,VARCHAR(30) 长度30个、 NOT NULL 非空、DEFAULT '' 缺省值是空,这种空值转成PHP程序时候会直接转成空字符串

CREATE TABLE users(
  id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(30) NOT NULL DEFAULT '',
  height DOUBLE(10,2) NOT NULL DEFAULT 0.00,
  age INT NOT NULL DEFAULT 0,
  sex CHAR(4) NOT NULL DEFAULT '女'
);


五、创建索引

索引在数据库开发中起到非常重要的作用,

通常在表的字段中建立索引,

可以提高查询优化,确保数据的唯一性,

以及可以对任何全文索引字段中,大量文本的搜索进行优化


在 Mysql 中主要有四类索引

1. 主键索引 primary key

2. 唯一索引 unique

3. 常规索引

4. 全文索引


1、主键索引

主键索引(primary key)是关系型数据库中最常见的索引类型

1. 主要作用是确定数据库表里一条特定数据记录的位置

    数据表会根据我们创建主键的字段,来标识每一条记录的唯一性,

    主键索引这一列的数据,是完全不允许重复的,这样加快寻址定位时的速度    

2. 最好为每一张数据表定义一个主键,

3. 而且一张表只能指定一个主键,

4. 主键的值不能为空


创建 id 列为主键索引 primary key(id 字段这里没有设置自动增长属性,也可以设置自动增长属性)

create table t6(
  id int not null primary key,
  name varchar(30) not null default ''
);

desc t6;

查看表结构,id 字段设置成了 PRI 主键索引 

+-------+-------------+------+-----+---------+-------+

 | Field   | Type            | Null  | Key  | Default   | Extra  |

+-------+-------------+------+-----+---------+-------+

 | id       | int(11)         | NO    | PRI   | NULL     |            |

 | name | varchar(30)  | NO    |         |               |           |

+-------+-------------+------+-----+---------+-------+


这样 id 字段就不能存重复的值了,第一次 id 字段可以插入数值 1

insert into t6 (id, name)values(1, '一点');


第二次 id 字段在插入数值 1 就出错了,返回 ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY' 主键值重复

insert into t6 (id, name)values(1, '二点');

select * from t6;

没有插入进入,只有第一次插入的一条记录

+----+------+

 |  id  | name|

+----+------+

 |   1  | 一点  |

+----+------+


主键索引也可以在创建表时在字段的下面指定 

primary key( id )  不能写多个字段名,因为一个表里面只能一个字段可以指定主键

create table t7(
  id int not null auto_increment,
  name varchar(30) not null default '',
  age tinyint not null default 0,
  primary key(id) -- 可以在这指定主键
);

desc t7;

id 字段是 PRI,

Null 列 NO 的意思是不允许为 NULL 空(YES 是允许为 NUll 空)

+-------+-------------+------+-----+---------+----------------+

 | Field   | Type            | Null  | Key   | Default | Extra                |

+-------+-------------+------+-----+---------+----------------+

 | id       | int(11)          | NO   | PRI   | NULL     | auto_increment | 

 | name | varchar(30)  | NO   |          |              |                         |

 | age    | tinyint(4)      | NO   |          | 0           |                         |

+-------+-------------+------+-----+---------+----------------+

建议每张表都建立一个主键索引


2、唯一索引

1. 唯一索引的作用和主键索引一样,都可以防止创建重复的值,

2. 不同在于每一个数据表中只能有一个主键索引,但是可以有多个唯一索引

3. 唯一索引用关键字 unique 来创建


如果能确保某个数据列,只包含彼此各不同的值,在为这个数据库列创建索引的时候,就应该使用唯一索引 unique 来修饰,

这样在新记录插入的时候,就会自动检查新记录这个字段的值,是否已经在某个现有记录的字段里出现过了,如果出现过了 Mysql 将拒绝插入。

其实创建唯一索引的目的,往往不是为了提高访问速度,而只是为了避免数据出现重复。


比如创建用户表

1. 不想让用户名 name 列重复,使用属性 unique 来修饰

2. 字段 id 是自动增加的,所以设置主键索引 primary key(id)

create table users(
  id int not null auto_increment,
  name varchar(30) not null default '' unique,
  age tinyint unsigned not null default 0,
  primary key(id)
);


id 列自动增长不用插入,就插入 name 名字列和 age 年龄列,第一次插入成功

insert into users (name, age) values ('zhu', '40');


第二次再插入就拒绝了,返回 ERROR 1062 (23000): Duplicate entry 'zhu' for key 'name'

insert into users (name, age) values ('zhu', '40');


查看表结构

desc users;

name 字段是 UNI 唯一索引,不能插入重复的值

+-------+---------------------+------+-----+---------+----------------+ 

 | Field   | Type                       | Null   | Key  | Default  | Extra                |

+-------+---------------------+------+-----+---------+----------------+

 | id        | int(11)                    | NO    | PRI   | NULL     | auto_increment |

 | name  | varchar(30)             | NO   | UNI  |               |                         |

 | age     | tinyint(3) unsigned | NO   |         | 0            |                         |

+-------+---------------------+------+-----+---------+----------------+


name 列插入一不同的数据值 'zhu2' 是可以了

insert into users (name, age) values ('zhu2', '40');

select * from users;

+----+------+-----+

 | id   | name | age |

+----+------+-----+

 |  1   | zhu    |  40   |

 |  3   | zhu2  |  40   |

+----+------+-----+


一张表可以在多个字段设置唯一索引,

比如文章名字,个人介绍等等,都不让重复的字段,都设置唯一索引,而主键索引一张表只能设置一个列,

主键索引是标识唯一性的,每张表只能有一个,唯一索引一个张表可以给多个字段设置。


3、常规索引

作为程序员,常规索引是创建数据表最重要的技术,

为什么常规索引是最重要的技术?

因为他能提升数据库的性能,

索引优化,首先应该考虑的就是“常规索引”。


要查询数据库就需要进行全表扫描,

有索引的列表,是在一个索引列上排序的一个数据表,可以通过索引快速的定位到记录。


如果没有加索引呢?

假设有一万(10000)条记录,

如果要查询的数据恰巧在第一条,很快就能查出来,

如果要查询的数据表的最后面,也就是最后一条,就要先读过前边 9999 条才能找到这第一万条,效率是很低的。


比如,去中关村图书大厦找一本书《细说PHP》,

我们不知道书在哪,就要一本一本的找,要花很长时间,

而我们按 索引顺序,

1. 先看在那个楼层,第 5 层全是计算机的书(就直接排除掉了很多小说、文学等别的书),

2. 然后在 5 层的计算机的书里面找软件开发的书(其它的网络、数据库等书又过滤掉了),

3. 软件开发中就定位到 PHP 类的书,

4. PHP 类的书就在一个书架上了,然后就能找到《细说PHP》


数据表加索引也是这个意思,

按照索引的值很快就能找这条记录的位置,哪怕数据在表的最后一条,

比如一万条件记录,有可能就找十次左右或上百次左右就能找到了,不用一万条记录都遍历。


所以数据库里面有索引,就能得到最佳性能方面的提升,

如果是没有索引的数据表就是没有排序数据的集合,如果查询数据就需要进行全表扫描,

有索引只是在索引列上进行排序的表,可以很快定义到记录。


另外,

不同的表类型,索引也是不一样的


其实常规索引也是有缺点的,

例如多占用磁盘空间,

要好好设计一下,不然不仅不会提升性能,还会减少性能,怎么设计常规索引呢?

常规索引可以提高查找速度(因为访问网站主要是查找),但是会减慢这个数据列上插入、删除、修改的速度。


还是书店的例子,

在书店按照索引顺序很快找到《细说PHP》这本书了,

但是作为书店的工作人员,在新书上架时,

也是按照索引的顺序,比如把计算机的书搬到到五层,然后必须找到PHP的书架,然后把新书插入到书架上,这是插入的速度。


如果新书放错了,修改的速度,或者书下架了删除的速度,

都要按照这个索引的顺序,哪层放什么方面的书,哪层的书是怎么分类。


如果没有索引的话,就可以不按这个顺序,把书往仓库里面一放就可以,速度就可以很快,

因为有索引,在插入、删除、修改数据的时候,也会按照索引顺序去摆放数据,所以查询上提高了,但是插入、删除、修改上减慢了


虽然多个字段都可以建立常规索引,但是不要把表的每个字段都创建成常规索引

1. 关系型数据库可以把表分开,

     有索引的字段专门放到一张表里面,没有索引的放到另外一张表里面,

     然后两张表用一个字段关联就可以了,这是分表。

2. 不分表也要注意,在什么字段上创建常规索引,

     比如需要作为条件搜索的字段(where条件搜索的),

     需要作为条件排序的(order by),

     需要作为条件分组的(group by),

     涉及到这样的数据列上,最适合创建常规索引,

     当然索引也不要创建太多,索引会消耗系统资源适可而止。


怎么创建常规索引?

1. 常规索引和表一样是独立的数据对象,可以单独的增删改查

2. 也可在创建表时,直接就创建了


常规索引最主要的就是知道索引的原理,为什么要加索引,加索引就很简单了。比如上面创建的这张用户表 users,是没有常规索引的

create table users(
  id int not null auto_increment,
  name varchar(30) not null default '' unique,
  age tinyint unsigned not null default 0,
  primary key(id)
);


因为有两种创建索引方法

第一钟,创建表的时候创建

第二种,单独创建索引


下面用第二种单独创建

因为常规索引跟表一样是数据对象,可以这样创建,

语法   create index 索引名 on 表名( 字段名1, 字段名2 )  

index 是常规索引,然后起一个索引名,on 在用户表的那个字段上建立

create index ind1 on users(name, age);

desc users;

查询表结构,体现不出来常规索引,

但是按照 name 名字查询和 age 年龄查询,都会提高查询速度

+-------+---------------------+------+-----+---------+----------------+

 | Field   | Type                       | Null   | Key  | Default  | Extra                |

+-------+---------------------+------+-----+---------+----------------+

 | id        | int(11)                    | NO    | PRI   | NULL     | auto_increment|

 | name  | varchar(30)            | NO    | UNI  |               |                         |

 | age     | tinyint(3) unsigned| NO    |         | 0            |                         |

+-------+---------------------+------+-----+---------+----------------+


查看 users 中的索引

show index from users;

show index from users\G -- 竖着的形式查看

表比较长,截取一部分

+-------+--------------+-----------+---------------+------------

 | Table  | Non_unique | Key_name | Seq_in_index | Column_name

+-------+--------------+-----------+---------------+------------

 | users  |          0          | PRIMARY  |            1         | id

 | users  |          0          | name        |            1         | name

 | users  |          1          | ind1          |            1         | name

 | users  |          1          | ind1          |            2         | age

+-------+--------------+-----------+---------------+-----------

这样查询的时候,如果数据量比较多时,按照name名字查询或者age年龄查询,都会加快查询速度,所以索引是必须设置的。


既然常规索引,是单独管理,就可以删除这个索引,

语法   DROP INDEX 索引名 on 数据库名  

drop index ind1 on users;

这样这个表又没有索引了,这是后期的管理,增删改查都可以


怎么在创建表的时候加索引?

比如创建一个 carts 购物车

uid 用户id

sid 商品id

number 购物车数量


给 cuid 和 sid 加索引,

关键字 index 和 key 是同义词,所以使用 index 和 key 是同一个作用

语法   key 索引名(字段名)    最好索引名和字段名是一样的

create table carts(
  id int auto_increment not null,
  uid int not null,
  sid int not null,
  number int not null,
  primary key(id),
  key cuid(uid), -- 常规索引(索引名和字段名最好是一样的)
  index csid(sid) -- 常规索引
);


第一种方式创建索引,

写一个索引名字,括号里写两个字段名

create table carts1(
  id int,
  uid int,
  sid int,
  num int,
  key snid(sid, num)
);


索引写在一起用一个名字,删除索引时,两个字段的索引都删除了

语法   DROP INDEX 索引名 ON 数据表名 

drop index snid on carts1;


两个索引分别指定,有两个索引名字,

一次只能删除一个索引,

另外还有一个索引,要删除两次,才能把 carts 表里的索引都删除

drop index cuid on carts;

drop index csid on carts;


索引写在一起指定,当然也可以一个一个写索引名,可以单独管理,各有各的好处和优缺点


常规索引是创建表时候的优化,最主要的一分部分,

因为其它优化的是 sql 语句的优化(是增删改查中的优化),创建表的优化主要是在索引上


4、全文索引

mysql 版本从 3.23 开始就支持全文索引搜索了,

在不使用匹配模式的前提下,去搜索单词或者短语


全文索引在 Mysql 中是一个 fulltext 类型索引

1. 全文索引只能在 MyISAM 表类型上使用,

2. 并且只有在 varchar、char、text 这样的文本字符串上使用

3. 也可以在多个数据列使用


全文索引是一种特殊的索引(全文索引用的比较少),

它会把某个数据表中的某个数据列里出现过的所有单词生成一份清单


比如创建一个书的表

bookname 书的名称

price 书的价格

detail 书的介绍

然后,

1. 在书的名字 bookname、书的介绍 detail 这两个字符串类型的字段上加全文索引

2. 按价格查询的时候会用到索引,在书的价格 price 字段上加常规索引

3. 在 id 字段上加主键

create table books(
  id int auto_increment not null,
  bookname varchar(30) not null,
  price double not null,
  detail text not null,
  fulltext(detail, bookname), -- 全文索引
  index price(price),
  primary key(id)
)engine=MyISAM charset=utf8;


如果不设置全文索引,通常这样写 sql 语句

查看 bookname 书名中有没有包含 'php' 的字符,用 like 匹配的方式效率很低

select * from books where bookname like '%php%';


有了全文索引,

1. 在 where 条件后面,用系统的函数 MATCH() 去指定查询 detail 字段 MATCH(detail

2. 在 detail() 字段中查询什么单词,用 AGAINST('PHP')

3. 就是在 detail 字段中查找有 'PHP' 的单词,只要包含'PHP'这个片段的,书名和价格都查询出来,以相关性从高到低的顺序排序

select bookname ,price from books where MATCH(detail) AGAINST('PHP');

MATCH(detail) 查询字段

AGAINST('PHP') 查询字段中的字符片段


另外 match、against 这两个函数不光是做 where 条件,

比如除了在 where 子句中应用,还可以放在 where 查询体中

select match(detail) against('php') from books;


注意:

全文索引返回错误 ERROR 1191 (HY000): Can't find FULLTEXT index matching the column list

解决方法 match(detil, bakname) 里面要把全文索引的字段都写了

select * from books where MATCH(detail, bookname) AGAINST('PHP');

select match(detail, bookname) against('php') from books;

从下面的地址查到,报错解决方法

http://www.gaodaima.com/6124.html



MySQL 创建数据表(下)有三部分内容

1. 创建表的时候还需要指定[表类型]

CREATE TABLE [ IF NOT EXISTS ] 表名称(

    字段名1 列类型 [属性] [索引],

    字段名2 列类型 [属性] [索引],

    ...

    字段名n 列类型 [属性] [索引],

) [表类型] [表字符集];

2. 表字符集

3. 以及在运行过程中如何修改表


六、数据表类型及存储位置

MySQL 和大多数数据库不同,MySQL 有一个“存储引擎”的概念,

可以针对不同的存储需要,选择最优的存储引擎,这是 MySQL 的特点,是别的数据库是不具备的。


自从 mysql5.0 以上就开始支持这种存储引擎,

的存储引擎有很多,通常我们把这种支持的“存储引擎”也叫做“数据表类型”。


看一下当前 Mysql 支持的存储引擎

show engines;

支持这么多种存储引擎,目前版本 DEFAULT 缺省值默认的是 InnoDB(高老师的视频是MyISAM)

+--------------------+---------+-------

 | Engine                   | Support | Comment

+--------------------+---------+--------

 | MEMORY              | YES        | Hash based, stored in 

 | CSV                       | YES        | CSV storage engine

 | MyISAM                | YES        | MyISAM storage engine

 | BLACKHOLE          | YES        | /dev/null storage engine

 | InnoDB                  | DEFAULT | Supports transactions,  

 | MRG_MYISAM      | YES        | Collection of 

 | ARCHIVE               | YES        | Archive storage 

 | PERFORMANCE_SCHEMA | YES     | Performance 

 | FEDERATED          | NO         | Federated 

+--------------------+---------+----------

如果创建表的时候不设置,就使用默认的 InnoDB 表类型


因为默认的是配置文件指定的,所以还可以从配置文件里看默认的表类型

show variables like 'table_type'; -- MySQL5.5.3后这个被取消了,所以返回Empty set (0.012 sec)


这么多表类型,其中重要的是这两种(最常用的

1. MySIAM 

2. InnoDB 


不用默认的表类型,如何自己指定?

创建表的时候关键字 type 或者 engine 来指定表类型,type 和 engine 这两个是一个意思,或者是别名的意思

  create table 表名 () type = InnoDB;  

  create table 表名 () engine = InnoDB;  (MariaDB 只能用 engine)


MyISAM 还是 InnoDB 这两种存储引擎 之间是什么差别?


有一点需要注意,

在一个 Mysql 库中,创建表的时候,可以为每张表,指定不同的表类型,

也就是同一个库中可以有多种不同的表类型存在。


MyISAM 类型的特点

优点

成熟稳定,易于管理,它使用一种表格锁定的机制,用来优化多个并发的读写操作,

其代价是创建完表后,需要经常使用  OPTIMIZE TABLE 表名;   命令,来恢复和更新机制所浪费的空间。

也就是说 MyISAM 表类型在我们经常增添改查的时候会出现一些碎片,

用  OPTIMIZE TABLE 表名;  命令进行碎片整理,用来恢复被更新机制所浪费的空间。


这种表类型主要是强调快速读取操作,也就是读取速度非常快,而且是一种成熟的引擎,

PHP 操作网站的时候,大量的数据操作都是读取操作,所以很多空间提供商只允许使用这种格式。


缺点

但是 MyISAM 类型也有缺点,有一些功能不支持。

每种表类型(引擎)都有各自的优缺点,我们用的时候,就选择这种表类型的优点用就可以了。


InnoDB 类型的特点

可以把 InnoDB 类型看做是 MyISAM 更新换代产品

1. InnoDB 提供了具有事务的提交、回滚、还有崩溃恢复能力的这些事务安全的存储引擎

2. 它也支持外键的机制,MyISAM引擎不支持外键,所以一些开源的项目很少使用外键索引


InnoDB 这种类型的表可以与其它 Mysql 其它类型的表混合起来,甚至在同一查询中可以混合的使用


InnoDB 的缺点

1. InnoDB 引擎的表类型空间占用量,要比 MyISAM 表要大的多

2. InnoDB 引擎读写速度,没有 MyISAM 快

3. 不支持全文索引等内容


这两个引擎如何选择呢?

MySIAM 类型的表和 InnoDB 类型的数据表,可以同时出现在一个数据库里面,

这样可以根据每一个数据表的内容数据和具体的用途,选择一个最佳的数据表类型。

功能MyISAMInnoDB
事务处理不支持支持
数据行锁定不支持支持
外键约束不支持支持
表空间占用相对小相对大,最大2倍数
全文索引支持不支持(后来也支持了)


总结

1. 如果希望想节省空间和时间,想要速度快的方式来管理表 MyISAM 擎管是首选

2. 如果程序需要用到事务、使用外键、需要更高的安全性,以及需要允许很多用户同时修改某个数据表里的数据,InnoDB 的数据表就更值得考虑了


创建表并指定表引擎

t1 表指定 InnoDB 型

t2 表指定 MyISAM 型

t3 表不指定类型是用默认类型

create database engdome;

use engdome;

create table t1(
  id int
)engine=InnoDB;


create table t2(
  id int
)engine=MyISAM;


create table t3(
  id int
); -- 不指定使用默认的


表存储位置

mysql 数据库以记录形式记录在表中,而表则是以文件的形式存储在磁盘目录中,

\mysql\data 目录下有一个 engdome 库,engdome 文件就存储表的目录,每一种类型的表有不同的存储格式,

但是有一个共同的特点,每个表至少有一存放文件结构 .frm 的文件


MyISAM 类型的数据表有三个文件

t2.frm 是存储表结构的

t2.MYD 是存储表数据的

t2.MYI 是专门保存索引的文件(索引也是一个独立的数据对象


InnoDB 类型的表

只有 t1.frm 一个文件存表结构(目前这个地方有些变化,还有一个 t1.ibd 文件)


七、MySQL默认字符集

1、什么是字符集

从本质上来说,计算机只能识别二进制代码,

因此无论是计算机程序还是处理的数据,最终都会被转换成二进制码,计算机才能够认识


为了让计算机不仅能够进行科学运算,也能够处理文字信息,所以人们想出了给每个文字符号编码,以便于计算机识别处理,

这就是计算机字符集的由来


简单的说,

字符集就是一套文字符号以及编号的一套规则的集合

名称介绍
ACSII

20世纪60年代初,美国标准组织发布了第一套字符集,也就是 ACSII 码,

后来转变成国际的 IOS64 标准,这个字符集采用用七个字节,包括大小写字母、阿拉伯数字、标点符号、33 个通用字符等...,

虽然美式的字符集很简单,包括的符号很少,但是今天它是计算机里奠定基础的一个标准,其后的所有字符集都是兼容 ACSII 码的。


ACSII 码后,为了处理不同的文字,

先后发布了几百种字符集,比如 ISO-8859-1 系列、gb2312、gbk、big5等...

这些五花八门的字符集,从收录的字符,到编码规则各不同,也就给开发带来了困难

ISO-8859-1也称为 latin1 西欧字符集,八位的编码,经常被一些程序员用来转码


gb2312-80gb 是国标的缩写,80是八零年代,80年或81年发布的,双字编码的字符集,它是定长,收录了大概有6700多个常用的汉字,还有 600 多个图形符号
gb13000全称是“信息技术通用的八位编码字符集”,93年发布的,大概收录了 27400 多个汉字,以及一些偏旁部首等等,几乎没有得到业界的支持,用的很少
GBKgb 是国标,k 是扩展,95年发布的,是在 gb2312 的基础上进行的扩充……,是双字节字符
GB180302000 年发布的,占用空间两个字节或四个字节,数据库支持的比较少见


UTF-32四个字节字符集,很少使用
USC-2两个字节字符集,window2000 内部使用的就是这个字符集
UTF-16两个或四个字节的编码,java、winxp、winNT 内部使用的是这个字符集
UTF-8

一个字节到四个字节编码,

它是互联网、UNIX、LINUK 广泛支持的字符集,

mysql 服务器也是使用的它,所以强烈推荐使用,

一个汉字占三个字节,其他符号可能是 2-4 个字节,所以它变长的


mysql 可以支持多种字符集,

在同一台服务器,同一个数据库,甚至同一张表的不同字段,都可以指定不同的字符集


查看 mysql 支持的字符集  

show character set;

+----------+---------------------------------+------------------

 | Charset   | Description                              | Default collation

+----------+---------------------------------+------------------

 | big5        | Big5 Traditional Chinese         | big5_chinese_ci

 | latin1      | cp1252 West European           | latin1_swedish_ci 

 | gbk         | GBK Simplified Chinese          | gbk_chinese_ci

 | utf8        | UTF-8 Unicode                        | utf8_general_ci

 | utf32      | UTF-32 Unicode                      | utf32_general_ci

……


注意,

数据库中写的是 UTF-8,

我们在使用的时候要写成 utf8 没有中间的 - 杠,有些初学者中间加杠,所以字符集设置失败


查看默认的字符集和校对的字符集(这个老师说没体现出来),字符集有两个概念

desc information_schema.character_sets;

+----------------------+-------------

 | Field                         | Type

+----------------------+-------------

 | CHARACTER_SET_NAME     | varchar(32)

 | DEFAULT_COLLATE_NAME | varchar(32)

 | DESCRIPTION                     | varchar(60)

 | MAXLEN                             | bigint(3)

+----------------------+-------------


2、什么是校对规则

Mysql 的字符集包括“字符集”和“校对规则两个概念

1. 字符集:是用来定义 Mysql 存储字符串的方式

2. 校对规则:定义了比较字符串的方式


字符集和校对规则是一对多的关系,

也就是一个字符集可能对应多个校对规则,

mysql 支持的字符集比如有 30 多个,校对规则大概有 70 多个,是字符集的 2 倍以上


比如,查看 gbk 字符集对应的校对规则

show collation like 'gbk%';

gbk字符集对应的校对规则有两个 gbk_chinese_ci 和 gbk_bin

+----------------+---------+----+---------+----------+---------+

 | Collation         | Charset | Id    | Default  | Compiled| Sortlen  |

+----------------+---------+----+---------+----------+---------+

 | gbk_chinese_ci| gbk       | 28   | Yes        | Yes          |       1     |

 | gbk_bin           | gbk       | 87   |               | Yes          |       1     |

+----------------+---------+----+---------+----------+---------+


校对规则的名称

1. 以相关字符集名开始,比如 gbk 开头

2. 中间通常是语言的国家名  _chinese

3. 三种后缀名

     以 _ci 结尾的意思是,在比较的时候大小写不敏感的,也就是不区分大小写的

     以 _cs 结尾的是,大小写敏感的

     以 _bin 结尾的比较是基于字符编码的值,与语言无关了,也就是二进制的比较,而且大小写明感的


utf8 是多国家用的字符集,所以对应的校对规则很多

show collation like 'utf8%';

+--------------------------+---------

 | Collation                        | Charset

+--------------------------+---------

 | utf8_general_ci              | utf8

 | utf8_bin                         | utf8

 | utf8_unicode_ci             | utf8

 | ....


3、服务器的“字符集”和“校对规则”

打开 Mysql 配置文件,

位置在 xampp\mysql\bin 目录下 my.ini 文件(在 mysql 启动的时候会自动加载这个配置文件

在这个文件下没找到 default-character-set = utf8 这个行设置

如果安装 Mysql 的时候没有特定的指定服务器的字符集,默认的字符集是 latin1

视频里高老师用的是 AppServe 集成环境,配置文件在 MYSQL 目录下就直接有 my.ini 文件


\s   可以查看一下服务器的字符集就是 utf8 (如果安装数据时没有指定,默认是 latin1 西欧字符集)

...

Server characterset: utf8mb4   这里安装的时候就指定了服务器字符集(如果没有指定,默认是 latin1 西欧字符集)

Db     characterset: utf8mb4

Client characterset: gbk

Conn.  characterset: gbk

...


我们只看到了字符集,没有看到校对规则,所以使用默认的校对规则,

如果想使用字符集的非默认的校对规则,就需要指定字符集的同时指定校对规则


看一下所有的配置文件中的变量,变量中的 character_set_serser 属性的变量

show variables like 'character_set_server';

设置的字符集是 utf8mb4(视频里是utf8),没有看到校对规则

+----------------------+---------+

 | Variable_name         | Value     |

+----------------------+---------+

 | character_set_server| utf8mb4|

+----------------------+---------+


在看 Mysql 服务器的校对规则

show variables like 'collation_server';

校对规则是 utf8mb4_general_ci 不区分小写的比较方式(课程里是 utf8_general_ci

+------------------+--------------------+

 | Variable_name   | Value                    |

+------------------+--------------------+

 | collation_server | utf8mb4_general_ci |

+------------------+--------------------+


4、设置数据库的字符集和校对规则

数据库的字符集和校对规则,可以在创建数据库的时候指定,

也可以在创建完数据库,通过更改数据库命令进行修改也是可以的


创建数据库的时候指定字符集和校对规则

1. 创建数据库 create database dblemon

2. 指定数据字符集 default character set utf8 

3. 指定不区分大小写的检验字符集 collate utf8_general_ci

create database dblemon default character set utf8 collate utf8_general_ci;

use dblemon; -- 进入库

\s -- 查看

\s

Server characterset: utf8mb4   服务器的字符集是 utf8mb4

Db     characterset: utf8            创建数据的字符集指定的是 utf8

Client characterset: gbk

Conn.  characterset: gbk


如果创建数据库时候不指定字符集

create database dblemon2;

use dblemon2;

\s

Server characterset: utf8mb4   服务器默认字符集 

Db     characterset: utf8mb4    不指定就用的是服务器默认的字符集 utf8mb4

Client characterset: gbk

Conn.  characterset: gbk


创建表的时候不指定字符集,默认就用数据库的,根数据库一样,

创建表的时候也可以指定字符集,跟上面数据指定字符集是一样的

1. 指定字符集 character set utf8

2. 指定校对规则 collate utf8_general_ci

use lemon2

create table t1(
  id int
)engine=MyISAM default character set utf8 collate utf8_general_ci;


当然除了创建库和创建表,

每个字段也可以指定字符集,方法是一样的,但是没有必要了,

因为创建库指定好字符集后,创建表和字段都用默认的字符集了


其实还有设置链接字符集和校对规则,

也就是说前面的设置,只是数据保存的时候,所用的字符集和校对规则,

对于实际的应用访问来说,还存在客户端和服务器之间这种相互的字符集和校对的设置

比如客户端和服务器交互的操作,mysql 提供了三种不同的一些参数


5、设置连接客户端字符集

客户端与服务器交互的时候,用什么字符集呢?我们可以指定三种

1. character_set_client            设置客户端字符集

2. character_set_connection   设置链接字符集

3. character_set_results           设置返回的结果集使用什么字符集


通常情况下,

上面设置的这三个字符集应该是相同的,才能确保数据正确的读出,特别是中文字符


这条命令可以同时修改上面三条命令的值

set names gbk;

\s  

查看一下

Current database:    dblemon2

Server characterset: utf8mb4

Db     characterset: utf8mb4

Client characterset: gbk          客户端字符集被改变了

Conn.  characterset: gbk         链接字符集被改变了


上面创建的数据库 dblemon2 的字符集,有两个值被改变,

现在链接和客户端的字符集都变 gbk 了,服务器、数据库的还是 utf8mb4,

高老师建议全部用 utf8

 set names utf8


还可以更改数据库的字符集

1. use dblemon2 选择数据库命令

2. 执行下面命令

alter database character set gbk;

\s    数据库的字符集变 gbk了

Current database:    dblemon2

Server characterset: utf8mb4

Db     characterset: gbk           数据库的字符集变 gbk 了

Client characterset: gbk

Conn.  characterset: gbk


更改表的字符集也是一样的

语法   alter table 表名 character set utf8  

alter table t1 character set utf8;


6、备份数据库

备份数据库 dblemon2 库

1. 先退出 exit;

2. 备份命令(命令后面不加分号 https://segmentfault.com/q/1010000002544120)

     --default-character-set=gbk  按照gbk导出

     -d dblemon2  导出的数据库名

      > d:/bak/tab.sql  导出位置

3. 输入密码,回车

exit;

mysqldump -h localhost -u root -p --default-character-set=gbk -d dblemon2 > d:/bak/tab.sql -- 按照gbk字符集导出来


再把表导进去

1. 新建一个库,不新建也行

2. exit 退出

3. 导入语句

create database dblemon3;

exit;

mysql -u root -p dblemon3 < d:/bak/tab.sql


总结

mysql 支持那些字符集,各种字符集之间的区别

utf8 字符集用起来比较好

怎么改服务器字符集,怎么改数据库的字符集,怎么改表字符集,怎么改链接客户端的字符集


八、修改表

通过 alter table 更改表的语句修改表


修改表的语法很多,看一下帮助

 ? alter table 

……

ADD COLUMN [IF NOT EXISTS]  add 是添加什么

ADD INDEX [IF NOT EXISTS]

ADD FOREIGN KEY [IF NOT EXISTS]

ADD PARTITION [IF NOT EXISTS]

CREATE INDEX [IF NOT EXISTS]


DROP COLUMN [IF EXISTS]

DROP INDEX [IF EXISTS]

DROP FOREIGN KEY [IF EXISTS]

DROP PARTITION [IF EXISTS]

CHANGE COLUMN [IF EXISTS]   change 是修改语句

MODIFY COLUMN [IF EXISTS]  change 也是修改语句

DROP INDEX [IF EXISTS]

……


1、添加

比如创建一个库 dbsummer,在创建一张表 t1

create database dbsummer;

CREATE TABLE `t1` (
  `id` int(11) not null DEFAULT 0
) ENGINE=MyISAM DEFAULT CHARSET=utf8;


对 t1 表不满意,

增加一个名字 name 字段,类型是varchar,属性

 alter table t1 add name varchar(30) not null default ''; 

alter table t1 add name varchar(30) not null default '';

desc t1;

+-------+-------------+------+-----+---------+-------+

 | Field   | Type            | Null  | Key   | Default | Extra   |

+-------+-------------+------+-----+---------+-------+

 | id        | int(11)         | NO   |          | 0           |            |

 | name  | varchar(30) | NO   |          |              |            |

+-------+-------------+------+-----+---------+-------+


在增加一个 age 年龄字段,要求无符号,不为空,缺省值是 0

 alter table t1 add age tinyint unsigned not null default 0; 

alter table t1 add age tinyint unsigned not null default 0;

desc t1;

+-------+---------------------+------+-----+---------+-------+

 | Field   | Type                       | Null   | Key  | Default  | Extra   |

+-------+---------------------+------+-----+---------+-------+

 | id       | int(11)                     | NO    |         | 0            |           |

 | name | varchar(30)             | NO    |         |               |           |

 | age    | tinyint(3) unsigned | NO    |         | 0            |           |

+-------+---------------------+------+-----+---------+-------+


如果想按自己指定的顺序,

比如在名字 name 字段后面,加一个性别 sex 字段

 alter table t1 add sex char(3) not null default '女' after name

alter table t1 add sex char(3) not null default '女' after name;

desc t1;

关键字 after 可以在任何字段后面加字段

+--------+---------------------+------+-----+---------+-------+

 | Field    | Type                        | Null   | Key  | Default  | Extra   |

+--------+---------------------+------+-----+---------+-------+

 | id         | int(11)                    | NO     |        | 0            |           |

 | name   | varchar(30)             | NO    |         |              |            |

 | sex       | char(3)                    | NO    |         | 女          |           |

 | age      | tinyint(3) unsigned | NO    |         | 0           |            |

+--------+---------------------+------+-----+---------+-------+


怎么在第一个字段  id 前面加字段呢?

alter table t1 add height double(4,1) not null default 180.3 first;

desc t1;

+--------+---------------------+------+-----+---------+-------+

 | Field    | Type                        | Null   | Key  | Default  | Extra   |

+--------+---------------------+------+-----+---------+-------+

 | height | double(4,1)             | NO     |        | 180.3     |           |

 | id         | int(11)                    | NO     |        | 0            |           |

 | name   | varchar(30)             | NO    |         |              |            |

 | sex       | char(3)                    | NO    |         | 女          |           |

 | age      | tinyint(3) unsigned | NO    |         | 0           |            |

+--------+---------------------+------+-----+---------+-------+


2、修改

修改字段有两个关键字

1. change 列明要出现两次,除了更该列名,还能更改类型

2. modify 不能更高列名,只能更改类型


修改性别 sex 字段的类型,把 char 类型改成 varchar(3) 类型

 alter table t1 modify sex varchar(3) not null default '男'; 

alter table t1 modify sex varchar(3) not null default '男';

desc t1;

+--------+---------------------+------+-----+---------+-------+

 | Field     | Type                       | Null   | Key | Default   | Extra   |

+--------+---------------------+------+-----+---------+-------+

 | height  | double(4,1)             | NO   |         | 180.3      |           |

 | id         | int(11)                     | NO   |          | 0            |           |

 | name   | varchar(30)              | NO   |         |               |           |

 | sex       | varchar(3)               | NO    |         | 男          |            |

 | age      | tinyint(3) unsigned | NO    |         | 0           |            |

+--------+---------------------+------+-----+---------+-------+


用户名 name 改成 username,就不能用关键字 modify,modify 适合改类型


改字段名都要改用 change

需要两个字段名

 alter table t1 change 原字段名 修改后的字段名 varchar(30) not null default ''; 

alter table t1 change name username varchar(30) not null default '';

desc t1;

+----------+---------------------+------+-----+---------+-------+

 | Field       | Type                        | Null   | Key | Default  | Extra   |

+----------+---------------------+------+-----+---------+-------+

 | height    | double(4,1)              | NO   |         | 180.3     |            |

 | id           | int(11)                      | NO   |         | 0            |            |

 | username | varchar(30)           | NO    |        |               |            |

 | sex          | varchar(3)               | NO    |        | 男           |           |

 | age         | tinyint(3) unsigned | NO    |        | 0            |            |

+----------+---------------------+------+-----+---------+-------+


表名 t1 本身也可以改成 users

alter table t1 rename as users;

desc users;

show tables;


3、删除

删除表中的 height 字段

alter table users drop height;

desc users;

+----------+---------------------+------+-----+---------+-------+

 | Field       | Type                        | Null  | Key   | Default | Extra   |

+----------+---------------------+------+-----+---------+-------+

 | id            | int(11)                     | NO   |          | 0           |            |

 | username| varchar(30)            | NO   |           |              |           |

 | sex          | varchar(3)               | NO   |          | 男          |            |

 | age         | tinyint(3) unsigned | NO   |          | 0           |            |

+----------+---------------------+------+-----+---------+-------+


删除整张数据表 users

drop table if exists users;


mysql 常用反斜杠命令

https://blog.csdn.net/weixin_30718391/article/details/96543644

视频课程

https://www.bilibili.com/video/BV1EJ41127NB?vd_source=30698713e5e2b66f66e6fa017646273c&spm_id_from=333.788.videopod.episodes&p=71



Leave a comment 0 Comments.

Leave a Reply

换一张