创建表
MySQL不仅用于表数据操作,而且还可以用来执行数据库和表的所有操作,包括表本身的创建和处理。
创建表一般有如下两种方式:
1、使用具有交互式创建和管理表的工具(如公司使用的SQLyog)
2、直接使用MySQL语句操纵表
注:
为了使用程序创建表,可以使用SQL的CREATE TABLE语句。值得注意的是,在使用交互式工具时,实际上使用的是MYSQL语句。但是这些语句不是用户编写的,界面工具会自动生成并执行相应的MYSQL语句(更改现有表时也是这样的)
表创建基础
在使用程序创建表,可使用SQL中的CREATE TABLE语句,需要以下两个信息:
1、新表的名字:在关键字CREATE TABLE后给出
2、表列的名字和定义,用逗号分隔
注:
CREATE TABLE语句也可能会包括其他关键字或选项,但至少要包括表的名字和列的细节
例1:
CREATE TABLE customers
(
cust_id int NOT NULL AUTO_INCREMENT,
cust_name char(50) NOT NULL,
cust_address char(50) NULL,
cust_city char(50) NULL,
cust_state char(5) NULL,
cust_zip char(10) NULL,
cust_country char(50) NULL,
cust_contact char(50) NULL,
cust_email char(255) NULL,
PRIMARY KEY(cust_id)
)
ENGINE = INNODB;
注:
1、从上面的例子中可以看到,表名紧跟在CREATE TABLE关键字后面。实际上表定义(所有列)括在圆括号之中,各列之间用逗号分隔。这个表由9列构成,每列的定义以列名开始(列名在表中必须是唯一的),后面跟列的数据类型。表的主键可以在创建表时用PRIMARY KEY关键字指定。
2、ENGINE = INNODB语句的意思为:设置表或库的数据库引擎为InnoDB(可以使用外键,事务等功能)
3、AUTO_INCREMENT语句的作用:使用AUTO_INCREMENT对主键建立自增id的行为,MySQL会自行保证主键ID的自增与不重复,使程序不需对ID进行关注
4、可在字段定义脚本中添加COMMENT属性来添加注释;在定义列时可以使用DEFAULT来指定列值得默认值
5、创建新表时,指定的表名必须不存在,如果只想在一个表不存在时创建它,应在表名前给出IF NOT EXISTS:这样做不检查表模式是否与打算创建的表模式匹配,只检查表名是否存在
例1_1:
/*角色表*/
CREATE TABLE IF NOT EXISTS `roleInfo`
(
`roleId` BIGINT(8) NOT NULL COMMENT '游戏生成的角色id',
`userId` BIGINT(8) NOT NULL COMMENT '游戏生成的账号id',
`funcelUUid` VARCHAR(128) NOT NULL COMMENT 'funcel平台生成的uuid',
`platformName` VARCHAR(64) NOT NULL COMMENT '平台名',
`channelName` VARCHAR(64) NOT NULL COMMENT '子渠道名',
`roleName` VARCHAR(64) COLLATE utf8_bin NOT NULL COMMENT '角色名',
`level` INT(4) NOT NULL DEFAULT 0 COMMENT '角色等级',
`career` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '角色职业',
`sex` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '角色性别',
`camp` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '角色阵营',
`lastOffTime` INT(4) NOT NULL DEFAULT 0 COMMENT '上次离线时间',
`mapDataId` INT(4) NOT NULL DEFAULT 0 COMMENT '当前进入的地图id',
`oldMapDataId` INT(4) NOT NULL DEFAULT 0 COMMENT '之前进入的世界地图id',
`appearance` VARCHAR(512) COLLATE utf8_bin COMMENT '角色外观数据,比如衣服、武器、翅膀等',
`roledata` LONGTEXT COLLATE utf8_bin COMMENT '角色数据',
`createServerId` INT(4) NOT NULL DEFAULT 0 COMMENT '角色创建时所在服',
`createTime` INT(4) NOT NULL DEFAULT 0 COMMENT '角色创建时间',
`deleteTime` INT(4) NOT NULL DEFAULT 0 COMMENT '0未删除,大于0删除时间',
`changename` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '0不能1可以改名',
KEY `index1` (`userId`),
KEY `index2` (`roleName`),
KEY `index3` (`funcelUUid`),
UNIQUE KEY `roleId` (`roleId`)
) ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='角色数据表';
注:
1、COLLATE关键字:utf8_unicode_ci,其实是用来排序的规则。对于mysql中那些字符类型的列,如VARCHAR,CHAR,TEXT类型的列,都需要有一个COLLATE类型来告知mysql如何对该列进行排序和比较。简而言之,COLLATE会影响到ORDER BY语句的顺序,会影响到WHERE条件中大于小于号筛选出来的结果,会影响**DISTINCT**、**GROUP BY**、**HAVING**语句的查询结果。另外,mysql建索引的时候,如果索引列是字符类型,也会影响索引创建,只不过这种影响我们感知不到。总之,凡是涉及到字符类型比较或排序的地方,都会和COLLATE有关。
2、utf8_bin将字符串中的每一个字符用二进制数据存储,区分大小写。utf8_genera_ci不区分大小写,ci为case insensitive的缩写,即大小写不敏感。utf8_general_cs区分大小写,cs为case sensitive的缩写,即大小写敏感。
3、mysql中ENGINE=INNODB DEFAULT CHARSET=utf8的作用:这个是在建表的时候指定表引擎为INNODB,字符集为utf8
4、UNIQUE约束的字段中不能包含重复值,可以为一个或多个字段定义UNIQUE约束,因此,UNIQUE即可以在字段级也可以在表级定义,在UNIQUE约束的字段上可以包含空值,(UNIQUED 可空,可以在一个表里的一个或多个字段定义)。PRIMARY KEY不可空不可重复,在一个表里可以定义联合主键;简单的说, primary key = unique + not null
5、primary key是主键,一般为自动增长并且是非空、int类型的,主要用来保证数据的唯一性;
6、Key是索引约束,对表中字段进行约束索引的,都是通过primary foreign unique等创建的。Key关键字括号外是建立索引的名称,括号内是对应字段。key的用途:主要是用来加快查询速度的。
使用NULL值
1、NULL就是没有值或者缺值。允许NULL值的列也允许在插入行时可以不给出该列的值,不允许NULL值的列不接受该列没有值的行(在插入或更新行时,该列必须有值)
2、每个表列或者是NULL列,或者是NOT NULL列,这种状态在创建时由表的定义规定
3、如上面例子中混合了NULL列和NOT NULL列:对于指定了NOT NULL的列,这将会阻止插入时没有值的行,如果试图插入没有值的行时,将会返回错误,且插入失败。对于指定了NULL的列,则可以插入没有值的行
4、NULL为默认值,如果不指定NOT NULL,则认为指定的是NULL
5、不要把NULL值与空串相混淆。NULL值是没有值,它不是空串。如果指定" "(两个引号,中间无字符),这在NOT NULL列中是允许的。空串是一个有效的值,它不是无值。NULL值用关键字NULL而不是空串指定
主键
1、主键值必须唯一的。即,表中的每个行都必须具有唯一的主键值。如果主键使用单个列,则它的值必须唯一的。如果使用多个列,则这些列的组合值必须唯一的
2、目前我们看到的CREATE TABLE例子都是用单个列作为主键,其中主键用以下类似的语句定义:PRIMARY KEY (vend_id)
3、创建由多个列组成的主键,应该以逗号分隔的列表给出各列名
4、主键可以在创建表时定义,也可以在创建表之后定义
5、主键为唯一标识表中每个行的列,主键中只能使用不允许NULL的行,允许NULL值的列不能作为唯一标识
例2:
CREATE TABLE IF NOT EXISTS `ordefitems`
(
order_num int NOT NULL,
order_item int NOT NULL,
prod_id char(10) NOT NULL,
item_price decimal(8,2) NOT NULL,
PRIMARY KEY(order_num,order_item)
)
ENGINE=INNODB
注:
1、MYSQL索引有四种PRIMARY、INDEX、UNIQUE、FULLTEXT, 其中PRIMARY、INDEX、UNIQUE是一类,FULLTEXT是一类。这四种都是单列索引,也就是他们都是作用于单个一列,所以也称单列索引;但是所有一个索引也可以作用于多个列上,称为组合索引或复合索引。
①PRIMARY:主键索引。索引列唯一且不能为空;一张表只能有一个主键索引(主键索引通常在建表的时候就指定)
CREATE TABLE T_USER(ID INT NOT NULL,USERNAME VARCHAR(16) NOT NULL,PRIMARY KEY(ID))
②NORMAL:普通索引。索引列没有任何限制
建表时指定
CREATE TABLE T_USER(ID INT NOT NULL,USERNAME VARCHAR(16) NOT NULL,INDEX USERNAME_INDEX(USERNAME(16))) //给列USERNAME建普通索引USERNAME_INDEX
ALTER语句指定
ALTER TABLE T_USER ADD INDEX U_INDEX (USERNAME) //给列USERNAME建普通索引 U_INDEX
删除索引
DROP INDEX U_INDEX ON t_user //删除表t_user中的索引U_INDEX
③UNIQUE:唯一索引。索引列的值必须是唯一的,但允许有空
建表时指定
CREATE TABLE t_user(ID INT NOT NULL,USERNAME VARCHAR(16) NOT NULL,UNIQUE U_INDEX(USERNAME)) //给列USERNAME添加唯一索引T_USER
ALTER语句指定
ALTER TABLE t_user ADD UNIQUE u_index(USERNAME) //给列T_USER添加唯一索引u_index
删除索引
DROP INDEX U_INDEX ON t_user
④FULLTEXT:全文搜索的索引。FULLTEXT 用于搜索很长一篇文章的时候,效果最好。用在比较短的文本,如果就一两行字的,普通的 INDEX 也可以。索引的新建和删除和上面一致
注:
2、创建唯一索引的目的不是为了提高访问速度,而只是为了避免数据出现重复。唯一索引可以有多个但索引列的值必须唯一,索引列的值允许有空值。如果能确定某个数据列将只包含彼此各不相同的值,在为这个数据列创建索引的时候就应该使用关键字UNIQUE,把它定义为一个唯一索引。
3、主键索引:它是一种特殊的唯一索引,不允许有空值。一般是在建表的时候同时创建主键索引:CREATE TABLE testIndex(i_testID INT NOT NULL AUTO_INCREMENT,vc_Name VARCHAR(16) NOT NULL,PRIMARY KEY(i_testID)); 当然也可以用ALTER命令。
使用AUTO_INCREMENT
在数据库应用中,我们经常需要用到自动递增的唯一编号来标识记录。在MySQL中,可通过数据列的auto_increment属性来自动生成。可在建表时可用“auto_increment=n”选项来指定一个自增的初始值。可用"alter table table_name auto_increment=n"命令来重设自增的起始值,当然在设置的时候Mysql会取数据表中auto_increment列的最大值 + 1与n中的较大者作为新的auto_increment值。
Myql的auto_increment属性具有以下特性:
1、具有auto_increment属性的数据列应该是一个正数序列,如果把该数据列声明为UNSIGNED,这样序列的编号个数可增加一倍。比如tinyint数据列的最大编号是127,如果加上UNSIGNED,那么最大编号变为255
2、auto_increment数据列必须有唯一索引,以避免序号重复;必须具备NOT NULL属性
在创建表时的语句中经常有一句为:
CREATE TABLE "table1" ("id" bigint(20) NOT NULL auto_increment;
1、AUTO_INCREMENT告诉MYSQL,本列每当增加一行时自动增量,每次执行一个INSERT操作时,MYSQL自动对该列增量(从而才有这个关键字AUTO_INCREMENT)给该列赋予下一个可用的值。这样给每行分配一个唯一的值(id),从而可以用作主键
2、每个表只允许一个AUTO_INCREMENT列,而且它必须被索引:如,通过使它成为主键
例3:
创建一张名为insect的表
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 );
插入一系列的值:该表没有指定id列为主键,因此可以使用null
INSERT INTO insect (id,NAME,DATE,origin) VALUES
(NULL,'housefly','2001-09-10','kitchen'),
(NULL,'millipede','2001-09-10','driveway'),
(NULL,'grasshopper','2001-09-10','front yard');
检索刚才插入的值
SELECT * FROM INSECT;
/*
id name date origin
------ ----------- ---------- ------------
1 housefly 2001-09-10 kitchen
2 millipede 2001-09-10 driveway
3 grasshopper 2001-09-10 front yard
------ --------- ---------- ----------
*\
覆盖AUTO_INCREMENT
使用简单的INSERT语句,在语句中指定一个值只要它是唯一的(至今未被使用过的)即可。该值将被用来代替自动生成的值,后续的增量将开始使用该手工插入的值
例4:
INSERT INTO insect (id,NAME,DATE,origin) VALUES (17,"nihao","2001-09-18","hello");
/*
id name date origin
------ ----------- ---------- ------------
1 housefly 2001-09-10 kitchen
2 millipede 2001-09-10 driveway
3 grasshopper 2001-09-10 front yard
17 nihao 2001-09-18 hello
------ ----------- ---------- ------------
*\
INSERT INTO insect (id,NAME,DATE,origin) VALUES (NULL,"nihao","2001-09-18","hello");
/*
id name date origin
------ ----------- ---------- ------------
1 housefly 2001-09-10 kitchen
2 millipede 2001-09-10 driveway
3 grasshopper 2001-09-10 front yard
17 nihao 2001-09-18 hello
18 nihao 2001-09-18 hello
------ ----------- ---------- ------------
*\
确定AUTO_INCREMENT的值
可使用SELECT LAST_INSERT_ID( )语句来查询最后一个AUTO_INCREMENT值例5:
SELECT LAST_INSERT_ID();
/*
last_insert_id()
------------------
18
*\
备注:
一张表,里面有ID自增主键,当insert了17条记录之后,删除了第15,16,17条记录,再把Mysql重启,再insert一条记录,这条记录的ID是18还是15 。
答案:
如果表的类型是MyISAM,那么是18。
因为MyISAM表会把自增主键的最大ID记录到数据文件里,重启MySQL自增主键的最大ID也不会丢失。
如果表的类型是InnoDB,那么是15。
InnoDB表只是把自增主键的最大ID记录到内存中,所以重启数据库或者是对表进行OPTIMIZE操作,都会导致最大ID丢失。
指定默认值
如果在插入行时没有给出值,MYSQL允许指定此时使用的默认值。默认值是在CREATE TABLE语句的列定义中的DEFAULT关键字指定的
例6:
CREATE TABLE orderitems
(
order_num int NOT NULL,
quantity int NOT NULL DEFAULT 1,
prod_id char(10) NOT NULL,
PRIMARY KEY(order_num)
)ENGINE=InnoDB;
注:
与大多数DBMS不一样,MYSQL不允许使用函数作为默认值,它只支持常量
引擎类型
迄今为止使用的CREATE TABLE语句都是以ENGINE=InnoDB语句结束的。在你使用SQL语句或进行其他数据库操作时,引擎在内部处理你的请求,多数时候此引擎都是隐藏在DBMS内,不需要过多关注它。但MYSQL与其他DBMS不一样,它具有多种引擎,这些引擎都隐藏在MYSQL服务器内,全都能执行CREATE TABLE、SELECT等操作。它们具有不同的功能和特性,为不同的任务选择正确的引擎能获得良好的功能和灵活性。如果在创建表时忽略ENGINE=语句时,则使用默认引擎(一般是MYISAM)
InnoDB:是一个可靠的事务处理引擎,它不支持全文搜索。
MEMORY:功能等同于MyISAM,由于数据存储在内存中,速度很快,适合于临时表。
MyISAM:性能极高的引擎,它支持全文搜索,但不支持事务处理。
混合使用引擎有一点需要注意:外键不能跨引擎
更新表
可以使用ALTER TABLE语句来更新表(结构)。但是一般情况下,当表中储存了数据以后,该表就不应该被更新。在表的设计过程中就应该花费大量的时间来考虑,以便后期不对该表进行较大的改动
为了使用ALTER TABLE更改表结构,必须给出下面信息:
1、在ALTER TABLE之后给出要更改的表明(该表必须存在,否则会报错)
2、所做更改的列表
例7:
ALTER TABLE insect ADD time_new CHAR(20);
\*
id name date origin time_new
------ ----------- ---------- ---------- ----------
13 housefly 2001-09-10 kitchen (NULL)
14 millipede 2001-09-10 driveway (NULL)
15 grasshopper 2001-09-10 front yard (NULL)
17 nihao 2001-09-18 hello (NULL)
18 nihao 2001-09-18 hello (NULL)
该条语句给insect表增加了一个名为time_new的列,必须明确其数据类型
*\
注:
使用ALTER TABLE要极为小心,应该在改动前做一个完整的备份,因为数据库的更改不能撤销
删除表
删除表(删除整个表而不是删除其内容)可以使用DROP TABLE语句
例8:
DROP TABLE demo_1;
重命名表
使用RENAME TABLE语句可以重命名一个表
例9:
RENAME TABLE insect TO info;
例9_1:
RENAME TABLE
insect TO info,
demo_1 TO demo_2;