MySQL学习笔记

MySQL学习笔记

整理:Jims of 肥肥世家

发布时间: 2004年11月06日

最近更新: 2005年01月12日


Table of Contents

1. MySQL数据库的数据
1.1. 数据值类型(data type)
1.1.1. 数值 1.1.2. 字符串 1.1.3. 日期和时间
1.2. 列类型(column type)
1.2.1. 数值类的数据列类型 1.2.2. 字符串类数据列类型 1.2.3. 日期,时间型数据列类型
1.3. 唯一编号 1.4. 字符集支持
1.4.1. MySQL4.1以前版本 1.4.2. MySQL4.1以后版本 1.4.3. 各级字符集的查询方法 1.4.4. Unicode支持
1.5. 如何选择数据列类型? 1.6. 表达式操作符 1.7. 类型转换
2. 查询优化
2.1. 索引 2.2. 查询优化程序 2.3. 数据列类型与查询效率 2.4. 有效地加载数据 2.5. 调度和锁定 2.6. 服务器优化 2.7. 硬件优化
3. 数据库管理
3.1. 数据目录 3.2. MySQL数据表在系统中表现形式 3.3. 数据表最大尺寸限制 3.4. 状态文件和日志文件 3.5. 调整MySQL数据目录位置
4. MySQL数据库日常管理
4.1. 数据库安全管理 4.2. 服务器的启动和关闭 4.3. 连接故障恢复 4.4. MySQL用户帐号管理 4.5. 日志文件管理
4.5.1. 日志失效处理
4.6. MySQL服务器的一些优化配置 4.7. 优化服务器 4.8. 运行多个MySQL服务器 4.9. MySQL服务器镜像配置
5. 数据库安全
5.1. 保护MySQL安装程序文件 5.2. 权限表 5.3. 建立加密连接
6. 数据库的备份、维护和修复
6.1. 检查/修复数据表 6.2. 备份数据库 6.3. 使用备份恢复数据
7. MySQL程序介绍 8. MySQL How-To
8.1. 连接数据库服务器 8.2. 更新用户密码 8.3. MySQL读取配置文件的顺序 8.4. 重设置MySQL管理员密码的方法 8.5. NULL值 8.6. 使用SQL变量 8.7. 改变默认提示符 8.8. 非优化的全数据表DELETE操作 8.9. MySQL事务处理示例

Chapter1.MySQL数据库的数据

MySQL数据库是由数据组成的,为了能方便管理和使用这些数据,我们把这些数据进行分类,形成各种数据类型,有数据值的类型,有表中数据列的类型,有数据表的类型。理解MySQL的这些数据类型能使我们更好地使用MySQL数据库。下面对各种数据类型进行简单的介绍。

1.1.数据值类型(data type)

对MySQL中数据值的分类,有数值型、字符型、日期型和空值等,这和一般的编程语言的分类差不多。

1.1.1.数值

MySQL中的数值分整型和浮点型两种。MySQL支持科学记数法。整型可以是十进制,也可是十六进制数。

1.1.2.字符串

MySQL支持以单或双引号包围的字符序列。如“MySQL tutorial”、‘Mysql Database’。

MySQL能识别字符串中的转义序列,转义序列用反斜杠(\)表示。下面是一个转义序列列表。

Table1.1.转义序列

转义序列含义
\0NUL(ASCII的0值)
\'单引号
\"双引号
\b后退符
\n换行符
\r回车符
\t制表符
\\反斜杠
\ZCtrl+Z

如果字符串本身包含有单双引号,则用以下三种方法中的一种来表示:

  • 字符串的引号和字符串两端的引号双同,则双写该引号。如:'mysql''s test'。

  • 用与字符串的引号不同的引号把字符串引起来,如:"mysql's test"。

  • 用反斜杠转义引号,如:"mysql\' test",'mysql\' test'。这样就不用理会字符串两端的是单引号还是双引号了。

字符串可由一个十六进制数表示,如0x61表示字符"a"。由MySQL 4.0开始,字符串值也可用ANSI SQL表示法X'val'来表示。如X'61'表示字符"a"。

从MySQL 4.1开始,可以为字符串值专门指定一个字符集。

1.1.3.日期和时间

MySQL默认按“年-月-日”的顺序显示日期。

1.2.列类型(column type)

MySQL 数据库的表是一个二维表,由一个或多个数据列构成。每个数据列都有它的特定类型,该类型决定了MySQL如何看待该列数据,我们可以把整型数值存放到字符类型的列中,MySQL则会把它看成字符串来处理。MySQL中的列类型有三种:数值类、字符串类和日期/时间类。从大类来看列类型和数值类型一样,都是只有三种。但每种列类型都还可细分。下面对各种列类型进行详细介绍。

1.2.1.数值类的数据列类型

数值型的列类型包括整型和浮点型两大类。

Table1.2.数值类数据列类型

数据列类型存储空间描述
TINYINT1字节非常小的正整数,带符号:-128~127,不带符号:0~255
SMALLINT2字节小整数,带符号:-32768~32767,不带符号:0~65535
MEDIUMINT3字节中等大小的整数,带符号:-8388608~8388607,不带符号:0~16777215
INT4字节标准整数,带符号:-2147483648~2147483647,不带符号:0~4294967295
BIGINT8字节大整数,带符号:-9223372036854775808~9233372036854775807,不带符号:0~18446744073709551615
FLOAT4字节单精度浮点数,最小非零值:+-1.175494351E-38,最大非零值:+-3.402823466E+38
DOUBLE8字节双精度浮点数,最小非零值:+-2.2250738585072014E-308,最大非零值:+-1.7976931348623157E+308
DECIMALM+2字节以字符串形式表示的浮点数,它的取值范围可变,由M和D的值决定。
1.2.1.1.整型数据列类型

MySQL有五种整型数据列类型,即TINYINT,SMALLINT,MEDIUMINT,INT和BIGINT。它们之间的区别是取值范围不同,存储空间也各不相同。在整型数据列后加上UNSIGNED属性可以禁止负数,取值从0开始。

声明整型数据列时,我们可以为它指定个显示宽度M(1~255),如INT(5),指定显示宽度为5个字符,如果没有给它指定显示宽度,MySQL会为它指定一个默认值。显示宽度只用于显示,并不能限制取值范围和占用空间,如:INT(3)会占用4个字节的存储空间,并且允许的最大值也不会是999,而是 INT整型所允许的最大值。

1.2.1.2.浮点型数据列类型

MySQL有三种浮点型数据列类型,分别是:FLOAT,DOUBLE和DECIMAL。浮点类数据类型有一个最大可表示值和一个最小非零可表示值,最小非零可表示值决定了该类型的精确度。

MySQL 4.0.2版之后,FLOAT和DOUBLE都可以指定UNSIGNED属性。当指定该属性时,取值范围不平移到正数区间,而只是简单地把浮点类型的负数部份去掉。

浮点类型也有M(1~255)和D(1~30,且不能大于M-2)。分别表示显示宽度和小数位数。M和D在FLOAT和DOUBLE中是可选的,默认,当 MySQL版本大于3.23.6时,FLOAT和DOUBLE类型将被保存为硬件所支持的最大精度。DECIMAL的M和D值在MySQL3.23.6后可选,默认D值为0,M值为10。

1.2.1.3.如何选择数值类数据列类型?

为了节省存储空间和提高数据库处理效率,我们应根据应用数据的取值范围来选择一个最适合的数据列类型。如果把一个超出数据列取值范围的数存入该列,则 MySQL就会截短该值,如:我们把99999存入SMALLINT(3)数据列里,因为SMALLINT(3)的取值范围是-32768~32767,所以就会被截短成32767存储。显示宽度3不会影响数值的存储。只影响显示。

对于浮点数据列,存入的数值会被该列定义的小数位进行四舍五入。如把一个1.234存入FLOAT(6.1)数据列中,结果是1.2。

DECIMAL 与FLOAT和DOUBLE的区别是:DECIMAL类型的值是以字符串的形式被储存起来的,它的小数位数是固定的。它的优点是,不会象FLOAT和 DOUBLE类型数据列那样进行四舍五入而产生误差,所以很适合用于财务计算;而它的缺点是:由于它的存储格式不同,CPU不能对它进行直接运算,从而影响运算效率。DECIMAL(M,D)总共要占用M+2个字节。

1.2.1.4.数值类数据列的属性
  • ZEROFILL属性适用于所有数值类数据列类型,作用是,如果数值的宽度小于定义的显示宽度,则在数值前填充0。

  • UNSIGNED属性不允许数据列出现负数。

  • AUTO_INCREMENT属性可生成独一无二的数字序列。只对整数类的数据列有效。

  • NULL和NOT NULL属性设置数据列是否可为空。

  • DEFAULT属性可为数据列指定默认值。

1.2.2.字符串类数据列类型

字符串可以用来表示任何一种值,所以它是最基本的类型之一。我们可以用字符串类型来存储图象或声音之类的二进制数据,也可存储用gzip压缩的数据。下表介绍了各种字符串类型:

Table1.3.字符串类数据列类型

类型最大长度占用存储空间
CHAR[(M)]M字节M字节
VARCHAR[(M)]M字节L+1字节
TINYBLOD,TINYTEXT2^8-1字节L+1字节
BLOB,TEXT2^16-1字节L+2
MEDIUMBLOB,MEDIUMTEXT2^24-1字节L+3
LONGBLOB,LONGTEXT2^32-1字节L+4
ENUM('value1','value2',...)65535个成员1或2字节
SET('value1','value2',...)64个成员1,2,3,4或8字节

L+ 1、L+2是表示数据列是可变长度的,它占用的空间会根据数据行的增减面则改变。数据行的总长度取决于存放在这些数据列里的数据值的长度。L+1或L+2 里多出来的字节是用来保存数据值的长度的。在对长度可变的数据进行处理时,MySQL要把数据内容和数据长度都保存起来。

如果把超出字符串最大长度的数据放到字符类数据列中,MySQL会自动进行截短处理。

ENUM和SET类型的数据列定义里有一个列表,列表里的元素就是该数据列的合法取值。如果试图把一个没有在列表里的值放到数据列里,它会被转换为空字符串(“”)。

字符串类型的值被保存为一组连续的字节序列,并会根据它们容纳的是二进制字符串还是非二进制字符而被区别对待为字节或者字符:

  • 二进制字符串被视为一个连续的字节序列,与字符集无关。MySQL把BLOB数据列和带BINARY属性的CHAR和VARCHAR数据列里的数据当作二进制值。

  • 非二进制字符串被视为一个连续排列的字符序列。与字符集有关。MySQL把TEXT列与不带BINARY属性的CHAR和VARCHAR数据列里的数据当作二进制值对待。

在MySQL4.1以后的版本中,不同的数据列可以使用不同的字符集。在MySQL4.1版本以前,MySQL用服务器的字符集作为默认字符集。

非二进制字符串,即我们通常所说的字符串,是按字符在字符集中先后次序进行比较和排序的。而二进制字符串因为与字符集无关,所以不以字符顺序排序,而是以字节的二进制值作为比较和排序的依据。下面介绍两种字符串的比较方式:

  • 二进制字符串的比较方式是一个字节一个字节进行的,比较的依据是两个字节的二进制值。也就是说它是区分大小写的,因为同一个字母的大小写的数值编码是不一样的。

  • 非二进制字符串的比较方式是一个字符一个字符进行的,比较的依据是两个字符在字符集中的先后顺序。在大多数字符集中,同一个字母的大小写往往有着相同的先后顺序,所以它不区分大小写。

二进制字符串与字符集无关,所以无论按字符计算还是按字节计算,二进制字符串的长度都是一样的。所以VARCHAR(20)并不表示它最多能容纳20个字符,而是表示它最多只能容纳可以用20个字节表示出来的字符。对于单字节字符集,每个字符只占用一个字节,所以这两者的长度是一样的,但对于多字节字符集,它能容纳的字符个数肯定少于20个。

1.2.2.1.CHAR和VARCHAR

CHAR和VARCHAR是最常用的两种字符串类型,它们之间的区别是:

  • CHAR是固定长度的,每个值占用相同的字节,不够的位数MySQL会在它的右边用空格字符补足。

  • VARCHAR是一种可变长度的类型,每个值占用其刚好的字节数再加上一个用来记录其长度的字节即L+1字节。

CHAR(0)和VARCHAR(0)都是合法的。VARCHAR(0)是从MySQL4.0.2版开始的。它们的作用是作为占位符或用来表示各种on/off开关值。

如何选择CHAR和VARCHAR,这里给出两个原则:

  • 如果数据都有相同的长度,选用VARCHAR会多占用空间,因为有一位用来存储其长度。如果数据长短不一,选用VARCHAR能节省存储空间。而CHAR不论字符长短都需占用相同的空间,即使是空值也不例外。

  • 如果长度出入不大,而且是使用MyISAM或ISAM类型的表,则用CHAR会比VARCHAR好,因为MyISAM和ISAM类型的表对处理固定长度的行的效率高。

[Note]
在一个数据表里,只要有一个数据列的长度是可变的,则所有数据列的长度将是可变的。MySQL会进行自动地转换。一个例外,CHAR长度小于4的不会进行自动转换,因为MySQL会认为这样做没必要,节省不了多少空间。反而MySQL会把大量长度小的VARCHAR转换成CHAR,以减少空间占用量。
1.2.2.2.BLOB和TEXT

BLOB是二进制字符串,TEXT是非二进制字符串。两者都可存放大容量的信息。

有关BLOB和TEXT索引的建立:

  • BDB表类型和MySQL3.23.2以上版本的MyISAM表类型允许在BLOB和TEXT数据列上建立索引。

  • ISAM、HEAP和InnoDB表不支持大对象列的索引。

使用BLOB和TEXT应注意的问题:

  • 由于这两个列类型所存储的数据量大,所以删除和修改操作容易在数据表里产生大量的碎片,需定期运行OPTIMIZE TABLE以减少碎片和提高性能。

  • 如果使用的值非常巨大,就需对服务器进行相应的优化调整,增加max_allowed_packet参数的值。对那些可会用到变些巨大数据的客户程序,也需加大它们的数据包大小。

1.2.2.3.ENUM和SET

ENUM和SET都是比较特殊的字符串数据列类型,它们的取值范围是一个预先定义好的列表。ENUM或SET数据列的取值只能从这个列表中进行选择。ENUM和SET的主要区别是:

  • ENUM只能取单值,它的数据列表是一个枚举集合。它的合法取值列表最多允许有65535个成员。例如:ENUM("N","Y")表示,该数据列的取值要么是"Y",要么就是"N"。

  • SET可取多值。它的合法取值列表最多允许有64个成员。空字符串也是一个合法的SET值。

ENUM和SET的值是以字符串形式出现的,但在内部,MySQL以数值的形式存储它们。

  • ENUM的合法取值列表中的字符串被按声明定义的顺序被编号,从1开始。

  • SET 的编号不是按顺序进行编号的,SET中每一个合法取值都对应着SET值里的一个位。第一个合法取值对应0位,第二个合法取值对应1位,以此类推,如果数值形式的SET值等于0,则说明它是一个空字符串,如果某个合法的取值出现在SET数据列里,与之对应的位就会被置位;如果某个合法的取值没有出现在SET 数据列里,与之对应的位就会被清零。正因为SET值与位有这样的对应关系,所以SET数据列的多个合法取值才能同时出现并构成SET值。

1.2.2.4.字符串类型数据列的字符集属性

在MySQL 4.1以前的版本,字符串数据列的字符集由服务器的字符决定,MySQL 4.1版以后的版本可对每个字符串数据列指定不同的字符串。如果按默认方式设置,可按数据列、数据表、数据库、服务器的顺序关联字符串的字符集,直到找一个明确定义的字符集。

1.2.3.日期,时间型数据列类型

MySQL的日期时间类型有:DATE,DATETIME,TIME,TIMESTAMP和YEAR,下表是这些类型的取值范围和存储空间要求:

Table1.4.日期,时间类型列

类型取值范围存储空间零值表示法
DATE1000-01-01~9999-12-313字节(MySQL3.23版以前是4字节 )0000-00-00
TIME-838:59:59~838:59:593字节00:00:00
DATETIME1000-01-01 00:00:00~9999-12-31 23:59:598字节0000-00-00 00:00:00
TIMESTAMP19700101000000~2037年的某个时刻4字节00000000000000
YEARYEAR(4):1901~2155 YEAR(2):1970~20691字节0000
[Note]
MySQL总是把日期和日期里的年份放在最前面,按年月日的顺序显示。
1.2.3.1.DATE、TIME、DATATIME数据列类型

DATE、TIME和DATATIME类型分别存放日期值、时间值、日期和时间值的组合。它们的格式分别是“CCYY-MM-DD”、“hh:mm:ss”、“CCYY-MM-DD hh:mm:ss”。

DATATIME里的时间值和TIME值是有区别的,DATATIME里的时间值代表的是几点几分,TIME值代表的是所花费的时间。当向TIME数据列插值时,需用时间的完整写法,如12分30秒要写成“00:12:30”。

1.2.3.2.TIMESTAMP数据列类型

TIMESTAMP数据列的格式是CCYYMMDDhhmmss,取值范围从19700101000000开始,即1970年1月1号,最大到2037年。它的特点是能把数据行的创建或修改时间记录下来:

  • 如果把一个NULL值插入TIMESTAMP列,这个数据列就将自动取值为当前的日期和时间。

  • 在创建和修改数据行时,如果没有明确对TIMESTAMP数据列进行赋值,则它就会自动取值为当前的日期和时间。如果行中有多个TIMESTAMP列,只有第一个会自动取值。

  • 如果对TIMESTAMP设置一个确定的日期和时间值,则会使TIMESTAMP的自动取值功能失效。

TIMESTAMP默认的列宽是14,可指定列宽,以改变显示效果。但不论你指定的列宽如何,MySQL都是以4字节来存储TIMESTAMP值,也总是以14位精度来计算。

如果需要把创建时间和最近一次修改时间同时记录下来,可以用两个时间戳来记录,一个记录创建时间,一个记录修改时间。不过需记住两件事,一是要把记录修改时间的TIMESTAMP数据列放在最前面,这样才会自动取值;二是创建一条新记录时,要用now()函数来初始化创建时间TIMESTAMP数据列,这样,该TIMESTAMP数据列就不会再变化。

1.2.3.3.YEAR

YEAR 是一种单字节的数据列类型,YEAR(4)的取值范围是1901~2155,YEAR(2)的取值范围是1970~2069,但只显示最后两位数。 MySQL能自动把两位数字年份转换成四位数字的年份,如97和14分被转换成1997和2014。转换规则是这样的:

  • 年份值00~69将被转换成2000~2069;

  • 年份值70~99将被转换成1970~1999。

[Note]
00被转换成0000,而不是2000。因为数值00也就是0,而0值是YEAR的一个合法取值。

1.3.唯一编号

在数据库应用,我们经常要用到唯一编号,以标识记录。在MySQL中可通过数据列的AUTO_INCREMENT属性来自动生成。MySQL支持多种数据表,每种数据表的自增属性都有差异,这里将介绍各种数据表里的数据列自增属性。

  • ISAM表

    • 如果把一个NULL插入到一个AUTO_INCREMENT数据列里去,MySQL将自动生成下一个序列编号。编号从1开始,并1为基数递增。

    • 把0插入AUTO_INCREMENT数据列的效果与插入NULL值一样。但不建议这样做,还是以插入NULL值为好。

    • 当插入记录时,没有为AUTO_INCREMENT明确指定值,则等同插入NULL值。

    • 当插入记录时,如果为AUTO_INCREMENT数据列明确指定了一个数值,则会出现两种情况,情况一,如果插入的值与已有的编号重复,则会出现出错信息,因为AUTO_INCREMENT数据列的值必须是唯一的;情况二,如果插入的值大于已编号的值,则会把该插入到数据列中,并使在下一个编号将从这个新值开始递增。也就是说,可以跳过一些编号。

    • 如果自增序列的最大值被删除了,则在插入新记录时,该值被重用。

    • 如果用UPDATE命令更新自增列,如果列值与已有的值重复,则会出错。如果大于已有值,则下一个编号从该值开始递增。

    • 如果用replace命令基于AUTO_INCREMENT数据列里的值来修改数据表里的现有记录,即AUTO_INCREMENT数据列出现在了 replace命令的where子句里,相应的AUTO_INCREMENT值将不会发生变化。但如果replace命令是通过其它的PRIMARY KEY OR UNIQUE索引来修改现有记录的(即AUTO_INCREMENT数据列没有出现在replace命令的where子句中),相应的 AUTO_INCREMENT值--如果设置其为NULL(如没有对它赋值)的话--就会发生变化。

    • last_insert_id()函数可获得自增列自动生成的最后一个编号。但该函数只与服务器的本次会话过程中生成的值有关。如果在与服务器的本次会话中尚未生成AUTO_INCREMENT值,则该函数返回0。

    其它数据表的自动编号机制都以ISAM表中的机制为基础。

  • MyISAM数据表

    • 删除最大编号的记录后,该编号不可重用。

    • 可在建表时可用“AUTO_INCREMENT=n”选项来指定一个自增的初始值。

    • 可用alter table table_name AUTO_INCREMENT=n命令来重设自增的起始值。

    • 可使用复合索引在同一个数据表里创建多个相互独立的自增序列,具体做法是这样的:为数据表创建一个由多个数据列组成的PRIMARY KEY OR UNIQUE索引,并把AUTO_INCREMENT数据列包括在这个索引里作为它的最后一个数据列。这样,这个复合索引里,前面的那些数据列每构成一种独一无二的组合,最末尾的AUTO_INCREMENT数据列就会生成一个与该组合相对应的序列编号。

  • HEAP数据表

    • HEAP数据表从MySQL4.1开始才允许使用自增列。

    • 自增值可通过CREATE TABLE语句的 AUTO_INCREMENT=n选项来设置。

    • 可通过ALTER TABLE语句的AUTO_INCREMENT=n选项来修改自增始初值。

    • 编号不可重用。

    • HEAP数据表不支持在一个数据表中使用复合索引来生成多个互不干扰的序列编号。

  • BDB数据表

    • 不可通过CREATE TABLE OR ALTER TABLE的AUTO_INCREMENT=n选项来改变自增初始值。

    • 可重用编号。

    • 支持在一个数据表里使用复合索引来生成多个互不干扰的序列编号。

  • InnDB数据表

    • 不可通过CREATE TABLE OR ALTER TABLE的AUTO_INCREMENT=n选项来改变自增初始值。

    • 不可重用编号。

    • 不支持在一个数据表里使用复合索引来生成多个互不干扰的序列编号。

在使用AUTO_INCREMENT时,应注意以下几点:

  • AUTO_INCREMENT是数据列的一种属性,只适用于整数类型数据列。

  • 设置AUTO_INCREMENT属性的数据列应该是一个正数序列,所以应该把该数据列声明为UNSIGNED,这样序列的编号个可增加一倍。

  • AUTO_INCREMENT数据列必须有唯一索引,以避免序号重复。

  • AUTO_INCREMENT数据列必须具备NOT NULL属性。

  • AUTO_INCREMENT数据列序号的最大值受该列的数据类型约束,如TINYINT数据列的最大编号是127,如加上UNSIGNED,则最大为255。一旦达到上限,AUTO_INCREMENT就会失效。

  • 当进行全表删除时,AUTO_INCREMENT会从1重新开始编号。全表删除的意思是发出以下两条语句时:

    delete from table_name;
    or
    truncate table table_name
    

    这是因为进行全表操作时,MySQL实际是做了这样的优化操作:先把数据表里的所有数据和索引删除,然后重建数据表。如果想删除所有的数据行又想保留序列编号信息,可这样用一个带where的delete命令以抑制MySQL的优化:

    delete from table_name where 1;
    

    这将迫使MySQL为每个删除的数据行都做一次条件表达式的求值操作。

  • 强制MySQL不复用已经使用过的序列值的方法是:另外创建一个专门用来生成AUTO_INCREMENT序列的数据表,并做到永远不去删除该表的记录。当需要在主数据表里插入一条记录时,先在那个专门生成序号的表中插入一个NULL值以产生一个编号,然后,在往主数据表里插入数据时,利用LAST_INSERT_ID()函数取得这个编号,并把它赋值给主表的存放序列的数据列。如:

    insert into id set id = NULL;
    insert into main set main_id = LAST_INSERT_ID();
    
  • 可用alter命令给一个数据表增加一个具有AUTO_INCREMENT属性的数据列。MySQL会自动生成所有的编号。

  • 要重新排列现有的序列编号,最简单的方法是先删除该列,再重建该,MySQL会重新生连续的编号序列。

  • 在不用AUTO_INCREMENT的情况下生成序列,可利用带参数的LAST_INSERT_ID()函数。如果用一个带参数的 LAST_INSERT_ID(expr)去插入或修改一个数据列,紧接着又调用不带参数的LAST_INSERT_ID()函数,则第二次函数调用返回的就是expr的值。下面演示该方法的具体操作:

    先创建一个只有一个数据行的数据表:
    create table seq_table (id int unsigned not null);
    insert into seq_table values (0);
    接着用以下操作检索出序列号:
    update seq_table set seq = LAST_INSERT_ID( seq + 1 );
    select LAST_INSERT_ID();
    通过修改seq+1中的常数值,可生成不同步长的序列,如seq+10可生成步长为10的序列。
    

    该方法可用于计数器,在数据表中插入多行以记录不同的计数值。再配合LAST_INSERT_ID()函数的返回值生成不同内容的计数值。这种方法的优点是不用事务或LOCK,UNLOCK表就可生成唯一的序列编号。不会影响其它客户程序的正常表操作。

1.4.字符集支持

MySQL4.1以前版本服务器只能使用单一字符集,从MySQL4.1版本开始,不仅服务器能够使用多种字符集,而且在服务器、数据库、数据表、数据列以及字符串常数多个级别上设置不同的字符集。

1.4.1.MySQL4.1以前版本

MySQL4.1 以前版本的字符集由服务器默认指定,默认值是编译系统时指定的字符集,该字符集也可通过在启动服务器时指定--default-character- set来修改。这种修改会对数据表的索引造成影响,因为索引的顺序是和字符集有关的,修改字符集会使这个已排序的顺序产生错误。要解决该问题,我们要用修改后的字符集的排序顺序重建表的索引。重建索引有以下几种方法:

  • 用mysqldump导出数据,再清除表里的内容,最后用导出文件重新导入。数据表的索引将在导入数时重建。该方法适用于所有数据表类型。

  • 删除索引,然后重建。用alter table命令或drop index和create index命令来完成。该方法也适用于所有数据表类型。但该方法需要我们了解重建索引的精确定义。

  • MyISAM 数据表的索引可以用myisamchk程序的--recover和--quick选项加上一个用来设定新字符集的--set-character-set 选项进行重建。还可以用mysqlcheck程序的--repair和--quick选项或者一个带QUICK选项的REPLACE TABLE语句来重建索引,这种方式较方便。

1.4.2.MySQL4.1以后版本

MySQL4.1以后的版本对字符集的支持好了很多,具有以下新增功能:

  • 支持服务器同时使用多种字符集。

  • 允许在服务器,数据库,数据表,数据列等多级别上设置不同的字符集。

    • 服务器的默认字符集在编译时选定,但可在启动服务器时用--default-character-set选项来更改。

    • 用ALTER DATABASE db_name DEFAULT CHARACTER SET charset来设置数据库字符集。 如果只有default参数,则使用服务器的字符集。

    • 用CREATE TABLE table_name(...) CHARACTER SET = charset设置数据表字符集。如果charset为default,则使用数据表所在数据库的字符集作为数据表的字符集。

    • 在数据列中,可用CHARACTER SET charset属性来设置数据列的字符集。charset不能是default,如果没有该属性,则默认使用数据表的字符集。允许设置字符集的数据列有char,varchar(不带binary属性)及TEXT类型。

    • 用_charset str转换字符串常数的字符集。如:_utf8 'mysql',_latinl 'oracle'。该方法只适用于括在引号内的字符串,其它十六进制常数 、字符串表达式等可用CONVERT()函数进行转换,如:SELECT CONVERT( str USING charset)。

  • 通过MySQL提供的函数可进行字符集转换和查询。

  • 新增的COLLATE操作符使我们可按某一种字符集的排序顺序来处理另一种字符集的数据。如:SELECT a from t ORDER BY a COLLATE utf-8;

  • 用SHOW CHARACTER SET命令可显示服务器支持的字符集列表。

  • 当服务器转换到另一种字符集时,会自动对索引进行重新排序。

  • 通过UTF-8和UCS2字符集提供了Unicode支持。

MySQL现在还不支持:1,在同一个字符串里混用不同字符集的字符;2,在同一个数据列里混用不同的字符集。

1.4.3.各级字符集的查询方法

  • 服务器级

    SHOW CHARACTER SET;可查出可供使用的所有字符集。
    SHOW VARIABLES LIKE 'character_set';可查出服务器的默认字符集。
    
  • 可查出数据库级的字符集。

    SHOW CREATE DATABASE db_name;
    
  • 两条命令可查出数据表的字符集。

    SHOW CREATE TABLE table_name;
    SHOW TABLE STATUS LIKE 'table_name'
    
  • 以下几命令可查出数据列的字符集:

    DESCRIBE table_name;
    SHOW COLUMNS FROM table_name;
    SHOW CREATE TABLE table_name;
    
  • 用CHARSET()函数可确定特定字符串,字符串表达式或数据列值相关联的字符串的字符集。如:SELECT CHARSET(str)。

1.4.4.Unicode支持

MySQL提供两种字符集来支持Unicode。一个是UTF-8,一种可变长的编码格式,需用1至4个字节来表示一个字符;另一个是UCS2,该字符集中的每个字符需要用两个字节来表示。

1.5.如何选择数据列类型?

选择正确的数据列类型能大大提高数据库的性能和使数据库具有高扩展性。在选择数据列类型时,请从以下几个方面考虑:

  • 存放到数据列中的数据类型。

  • 数据值的取值范围。

  • 考虑性能和处理效率。

    • 数值操作比字符操作快。

    • 小类型的处理速度比大类型快。

    • 不同数据表中固定长度类型和可变长度类型的处理效率是不同的。

      可变长度类型在经过删除和修改操作后容易产生碎片,降低系统性能,需定期运行OPTIMIZE TABLE命令以优化数据表。

      固定长度类型由于有固定的长度,所以容易确定每条记录的起始点,可加快数据表的修复速度。

      在MyISAM和ISAM表中使用固定长度类型数据列有助改善数据库性能。

      在InnoDB表中,固定长度和可变长度数据列类型都以相同方式存储,所以固定长度数据列类型并没有性能优势,反而由于可度长度数据列类型由于占用存储空间较少,所以处理速度会快些。

    • 可索引类型能加快数据的查询速度。

    • 明确指定数据列的NOT NULL属性可使MySQL在检索过程中不用去判断数据列是否是NULL,所以可加快处理速度。

  • 数据如何进行比较,是否区分大小写。

  • 是否要在数据列上建立索引。

1.6.表达式操作符

Table1.5.算术操作符

操作符语法含义
+a + b相加
-a - b相减
-- a求负
*a * b乘法
/a / b除法
%a % b求余

Table1.6.逻辑操作符

操作符语法含义
AND 或 &&a AND b 或 a && b逻辑与,若两个操作数同时为真,则为真
OR 或 ||a OR b 或 a || b逻辑或,只要有一个操作数为真,则为真
XOR a XOR b逻辑异或,若有且仅有一个操作数为真,则为真
NOT 或 !NOT a 或 !a逻辑非,若操作数为假,则为真

Table1.7.位操作符

操作符语法含义
&a & b按位与,若操作数同位同为1,则该位为1
|a | b按位或,若操作数同位有一位为1,则该位为1
^a ^ b按拉异或,若操作数同一位分别为1和0,则该位为1
<<a << b把a中的各个位左移b个位置
>>a >> b把a中的各个位右移b个位置

Table1.8.比较操作符

操作符语法含义
=a = b若两个操作数相等,则为真
<=>a <=> b若两个操作数相等,则为真,可用于NULL值比较
!= 或 <>a != b 或 a <> b若两个操用数不等,则为真
<a < b若a小于b,则为真
<=a <= b若a小于或等于b,则为真
>a > b若a大于b,则为真
>=a > b若a大于或等于b,则为真
INa IN (b1,b2,...)若a等于b1,b2,...中的某一个,则为真
BETWEENa BETWEEN b AND c若a在b和c之间(包括b和c),则为真
NOT BETWEENa NOT BETWEEN b AND c若a不在b和c之间(包括b和c),则为真
LIKEa LIKE bSQL模式匹配,若a匹配b,则为真
NOT LIKEa NOT LIKE bSQL模式匹配,若a不匹配b,则为真
REGEXPa REGEXP b正则表达式匹配,若a匹配b,则为真
NOT REGEXPa NOT REGEXP b正则表达式匹配,若a不匹配b,则为真
IS NULLa IS NULL若a为NULL,则为真
IS NOT NULLa IS NOT NULL若a不为NULL,则为真
[Note]
LIKE模式匹配中的“%”匹配任意个字符,“_”匹配一个字符。匹配不区分大小写字符。

Table1.9.操作符优先级(由高至低排列)

操作符
BINARY,COLLATE
NOT、!
^
XOR
-(一元求负操作符)、~(一元取反操作符)
*、/、%
+、-
<<、>>
&
|
<、<=、=、<=>、!=、<>、>=、>、IN、IS、LIKE、REGEXP、RLIKE
BETWEEN、CASE、WHEN、THEN、ELSE
AND、&&
OR、||
:=

1.7.类型转换

在MySQL的表达式中,如果某个数据值的类型与上下文所要求的类型不相符,MySQL则会根据将要进行的操作自动地对数据值进行类型转换。如:

1 + '2'      会转换成1 + 2 = 3
1+ 'abc'     会转换成1 + 0 = 1 由于abc不能转换成任何的值,所以默认为0

MySQL会根据表达式上下文的要求,把字符串和数值自动转换为日期和时间值

对于超范围或非法的值,MySQL也会进行转换,但转换出来的结果是错误的。出现该情况时,MySQL会提示警告信息,我们可捕获该信息以进行相应的处理。

Chapter2.查询优化

Table of Contents

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值