赞
踩
- 创建表时指定非空约束:
create table 表名( 字段 数据类型 not null, );
- 在已有表上设置非空约束:
alter table 表名 modify column 字段 数据类型 not null;
- 删除非空约束:
alter table 表名 modify column 字段 数据类型;
- 创建表时指定唯一约束:
create table 表名( 字段 数据类型 UNIQUE, );
- 创建表时指定复合唯一约束(表级约束):
create table 表名 ( 字段1 数据类型, 字段2 数据类型, [constraint 唯一约束名] unique(字段1,字段2) );
- 在已有表上指定一/多列为唯一约束:
alter table 表名 add [constraint 唯一约束名] unique(字段,字段2....);
- 删除列的唯一约束:通过约束名删除
alter table 表名 drop 唯一约束名;
- 除了BLOB与TEXT类型、空间类型,或者具有AUTO_INCREMENT属性的列以外,你还可以指定DEFAULT def_value子句,以此来表明:当在创建新的行时 ,如果没有显式地指定某个值 , 那么该列将被赋值为默认值def_value。
- 除了TIMESTAMP列和DATETIME列有限制以外,这里的默认值def_value必须是一个常量,它不能为表达式/函数等,也不能引用其他列。
DEFAULT与NULL
- 如果某个列定义没有显式包含DEFAULT子句,并且该列允许为NULL值,那么其默认值为 NULL。
- 否则 ,如果该列不允许为NULL值,并且在定义里没有显式包含DEFAULT子句,那么在创建它时也不会带有DEFAULT子句。也就是说 ,它没有默认值。在往表里插入新的行时 ,如果没有为列指定具体值,这会影响MySQL对列的处理。处理规则如下:
- 如果没有启用SQL的严格模式,那么该列将被设置成其数据类型的隐含默认值。(各种隐含默认值将在稍后讨论)。
- 在启用SQL的严格模式之后:
- 如果表是事务性的,就会出现错误。这条语句会中止执行,然后回滚。
- 对于非事务性的表:
- 如果这行是该语句插入的第一个行,那么会出现一个错误,并且该语句会中止执行。
- 如果插入的不是第一行,那么你可以选择让语句中止执行,或者选择把这列设 置为它的隐含默认值,同时发一条警告消息。
- 具体的选择需要参考哪一种严格模式在起作用。更多相关细节请参考https://dongshao.blog.csdn.net/article/details/88055683。更多与事务有关的信息请参考https://dongshao.blog.csdn.net/article/details/104055508。
- 创建表时添加默认值:
create table 表名( 字段 数据类型 DEFAULT 默认值 );
- 在已有表上设置默认值约束:
alter table 表名 modify column 字段 数据类型 default 默认值;
- 删除默认值:赋值为NULL即可
alter table 表名 modify column 字段 数据类型 default null;
AUTO_INCREMENT列行为
- 把NULL值插入AUTO_INCREMENT列将引发 MySQL自动生成下一个序列编号,并把它插入列。
- AUTO_INCREMENT序列通常是从1开 始,并依次单步递增,因此连续插入表的各行的序号 值将为1、2、3,如此等等。
- 在某些场合,根据所用存储引擎的不同,可以显式地设置或重置下一个序号,或者重复使用已从序列顶端删除的那些序号值。(例如,如果插入数据时指定了值,则字段的默认值改变,下一次插入时将为本次改变值的+1)。
LAST_INSERT_ID()函数
- 要获得最近生成的序号值,可以调用LAST_INSERT_ID()函数 。这样,即使在你根本不知道AUTO_INCREMENT值到底是多少的时候,也可以在后续的语句里引用它。
- 如果在当前会话里,还没有生成过AUTO_INCREMENT值 ,那么LAST_INSERT_ID()将返回0。
SELECT LAST_INSERT_ID();
- LAST_INSERT_ID()只会依赖于与服务器的当前会话连接所生成的AUTO_INCREMENT值。
- 你可以生成一个序号,接着在同一个会话连接里调用LAST_INSERT_ID()来检索它。即使其他客户在此期间生成了它们自己的序号值,也不会出现任何问题。
- 一次插入多个行的INSERT语句,将生成多个AUTO_INCREMENT值,LAST_INSERT_ID()只会返回其中的第一个。
- 如果使用INSERT DELAYED,那么要直到实际插入行时,才会生成AUTO_INCREMENT值 。这时,就不能依靠LAST_INSERT_ID()来返回序号值了。
- 在插入一行时,如果不为AUTO_INCREMENT列指定值 ,则等同于向该列插入一个NULL值 。如ai_col是一个 AUTO_INCREMENT列,那么下面这两条语句就是等效的:
INSERT INTO t (ai_col,name) VALUES(NULL, 'abc'); INSERT INTO t (name) VALUES('abc');
- 默认情况下,把0插入AUTO_INCREMENT列,等效于插入NULL值。如果启用了SQL的 NO_AUTO_VALUE_ON_ZERO模式,那么插入0则会导致存储值为0,而非下一个序号值 。
- 如果要插入一行,并为某个拥有唯一索引的AUTO_INCREMENT列指定一个既不为NULL,也不为0的值,那么将发生这样两种情况中的某一种:
- 如果已存在一行使用该值的记录,那么将会发生键重复错误。
- 否则,这行会被正常插入,而那个AUTO_INCREMENT列会被设置为那个给定值。如果该值大于当前的下一个序号值 ,那么这个序列将被重置,对于随后的行,所使用的编号会继续由该值开始生成。换句话说 ,即可以插入一行,让其序号值大于当前计数 器值 ,以此达到增大计数器的目的。
- 对于某些存储引擎,从序列顶端删除的值可以被重用:
- 如果把包含最大AUTO_INCREMENT列值的那行删除,那么在下次生成新值时可以重用这个最大值。
- 如果把表里的所有记录都删除,那么所有值都可以重用,并且这个序列会重新从1开 始。
- 如果使用UPDATE命令把AUTO_INCREMENT列的值设置成某个正被其他行使用的值,并且这个列拥有唯一索引,那么会出现一个键重复错误。如果把这个列设置成某个大于所有已有列值的编号值 ,那么对于随后的行,这个序列从那个值开始继续生成下一个编号。 如果 把该列更新为0,那么它会被设置为0(不管是否启用了NO_AUTO_VALUE_ON_ZERO都一样)。
- 如果根据AUTO_INCREMENT列的值 ,使用REPLACE来更新行,那么这个行的AUTO_INCREMENT值将保持不变。如果择据其他具有PRIMARY KEY或UNIQUE索引的列 的值,使用REPLACE命令来更新行,那么当你把AUTO_INCREMENT列设置为NULL,或者把它设置为0,而且没有启用NO_AUTO_VALUE_ON_ZERO时,该列的值将被更新为一个新的序号值。
刚才介绍的通用AUTO_INCREMENT特征,是理解各种存储引擎特有序列行为的基础。绝大多数 引擎实现的行为与上面的描述大体是一致的。MylSAM为序列处理提供了最大的灵活性,因此这 里的讨论便由该引擎开始。
MyISAM
- MylSAM存储引擎拥有以下AUTO_INCREMENT特征:
- MylSAM表里的序列一般是单调的。在一个自动生成的序列里,这些值都是严格递增的;并且在行被删除之后,不会被重用。如果最大值是143,而你删除了包含这个值的行,那么MySQL生成的下一个值仍然是144。不过,这种行为存在以下两种例外情况 :
- 如果使用TRUNCATE TABLE清空了表,那么计数器将被重置为从1开 始。
- 如果在表里使用了复合索引来生成多个序列,那么从序列顶 端删除的那些值将 被重用 。 (此项技术随后将被讨论到)。
- MylSAM序列将默认从1开 始,不过你可以在CREATETABLE语句里,通过AUTO_INCREMENT=n选项显式地指定初始值 。下面这个示例会创建一个MylSAM表, 其中带有一个名为seq的AUTO_INCREMENT列,其起始值为1000000:CREATE TABLE mytbl(...)ENGINE=MYISAM AUTO_INCREMENT=1000000;
- ALTER TABLE:
- 可以使用ALTER TABLE来更改某个已有MylSAM表的当前序列计数器。例如,序列的当 前编号为1000,那么下面这条语句将使下一个生成的编号值变为2000:ALTER TABLE mytbl AUTO_INCREMENT=2000;
- 如果想要重用那些从序列顶端删除了的值,也可以用ALTER TABLE语句来设置。把编号计数器设置到最低,使得下一个编号只比当前最大序号值多1:ALTER TABLE mytbl AUTO_INCREMENT=1;
- 不能使用AUTO_INCREMENT选项来把当前计数值设置得比表里当前的最大计数值还小。例如,如果某个AUTO_INCREMENT列包含的值为1〜10,那么使用AUTO_INCREMENT = 5来设置这个计数器,得到的下一个自动值仍然为11,而非5。
- MylSAM存储引擎支持在同一个表里使用复合(多列)索引,以创建多个相互独立的序列。
- 为利用这个特性,为表创建一个由多列组成的KRIMARYKEY或UNIQUE索引,并把包含 AUTO_INCREMENT的那个列作为其中的最后一个。对于该索引最左边的列构成的每一个 相异键, AUTO_INCREMENT列将生成一组彼此互不干扰的序列值。
- 例如,有一个名为bugs的表,你需要用它来同时记录多个软件项目的bug报告,该表的定义如下:
- 其中,proj_name列用于标识项目名,description列用于存放bug描述。
- bug_id列是一个 AUTO_INCREMENT列,通过创建一个与proj_name列相关联的索引,可以为各个项目分别生成一个互不干扰的序列编号。
CREATE TABLE bugs ( proj_name VARCHAR(20) NOT NULL, bug_id INT UNSIGNED NOT NULL AUTO_INCREMENT, description VARCHAR(100), PRIMARY KEY (proj_name, bug_id) )ENGINE=MYISAM;
- 假设,需要把下面几行输到表里,记录SuperBrowser项目的3个bug,以及SpamSquisher项目的2个bug:
INSERT INTO bugs (proj_name,description) VALUES('SuperBrowser','crashes when displaying complex tables'); INSERT INTO bugs (proj_name,description) VALUES('SuperBrowser','image scaling does not work'); INSERT INTO bugs (proj_name,description) VALUES('SpamSquisher','fails to block known blacklisted domains'); INSERT INTO bugs (proj_name,description) VALUES('SpamSquisher','fails to respect whitelist addresses'); INSERT INTO bugs (proj_name,description) VALUES('SpamSquisher','background patterns not displayed');
- 表的最终内容如下所示:
SELECT * FROM bugs ORDER BY proj_name,bug_id;
- 这个表为每一个项目的bug_id值进行了单独的编号,整个过程与这些项目的行输入顺序毫无关系。在输入另一个项目的行之前,你不用先全部输入某个项目的所有行。
- 如果使用复合索引来创建多个序列,那么从各个序列顶端删除的值都可以被重用。这 一点 与MylSAM表的不重用序号值的行为有所不同。
InnoDB
- 在CREATE TABLE语句里,可以使用AUTO_INCREMENT=n表选项来设置初始序列值,并 且在表创建之后,还可以使用ALTER TABLE来进行更改。(参考上面MyISAM语法)
- 从序列顶端删除的值通常不能再重用:
- 不过,如果使用TRUNCA TETABLE清空表,那么序列将被重置,并重新从1开始编号。
- 此外,在满足后面几个条件时也可以重用:
- 首先,在首次为AUTO_INCREMENT列生成序号值时,InnoDB会把列的当前最大值加上1,得到的结果作为新生成的序号值 (如果表此前为空,那么新的序号值为1)。
- 其次,为满足生成后续序号值的需要,InnoDB是在内存里维护这个计数器——它并未存储在表内部。这意味着,如果从这个序列的顶端删除了某些值,然后又重启 了服务器,那么这些删除的值将会被重用。重启服务器还将取消在CREATE TABLE或ALTER TABLE语句里使用AUTO_INCREMENT表选项所带来的效果。
- 如果生成AUTO_INCREMENT值的事务被回滚,那么在序列里可能会出现断裂。
- 在表里,不能使用复合索引生成多个独立的序列。
MEMORY
- 在CREATE TABLE语句里,可以使用AUTO_INCREMENT=n表选项来设置初始序列值,并 且在表创建之后,还可以使用ALTER TABLE来进行更改。(参考上面MyISAM语法)
- 从序列顶端删除的值通常不能再重用。不过,如果使用TRUNCA TETABLE清空表,那么序列将被重置,并重新从1开始编号。
- 在表里,不能使用复合索引生成多个独立的序列。
DELETE FROM tbl_name WHERE TRUE;
- create table 表名(
- 字段 数据类型 PRIMARY KEY AUTO_INCREMENT
- );
- # 如果表已经设置了主键或索引
- ALTER TABLE 表名 MODIFY COLUMN 字段 数据类型 AUTO_INCREMENT;
-
- # 如果表没有设置主键或索引
- ALTER TABLE 表名 MODIFY COLUMN 字段 数据类型 PRIMARY KEY AUTO_INCREMENT;
重置已有列的序列编号
- 如果表已经有了一个AUTO_INCREMENT列,但是你想要对其进行重新编号,以便消除因删除行而在序列里产生的断裂。实现这一目标的最简单办法是:先删除该列,然后再重新添加它。 当MySQL添加列时,会自动分配新的序列号。
- 假设,有这样一个表t,其中的i为一个AUTO_INCREMENT列:
CREATE TABLE t ( c CHAR(10), i INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY ); INSERT INTO t(c) VALUES('a'),('b'),('c'),('d'),('e'),('f'),('g'),('h'),('i'),('j'),('k'); DELETE FROM t WHERE c IN('a','d','f','g','i'); SELECT * FROM t;
- 下面的ALTER TABLE语句将依次删除列,再重加它,重回的过程中会对列重新编号:
ALTER TABLE t DROP PRIMARY KEY, DROP i, ADD i INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,AUTO_INCREMENT = 1; SELECT * FROM t;
- AUTO_INCREMENT=1子句将把序列的起始编号重置为1。对于MylSAM、MEMORY或 InnoDB表,可以把序列的起始编号设置为不等于1的其他数。对于其他的存储引擎,则可以忽略AUTO_INCREMENT子句,因为它们不允许使用这样的方式设定序列的初始值。这个序列将从1开始编号。
- 虽然可以轻易地重新设置列的编号,但是“要怎么才能做到呢?”这个问题仍然很常见,而且通常没有必要这么做。MySQL并不会在意序列里是否存在有断裂,并且在重置序列编号后 也不会获得任何性能上的提高。此外,如果在另一个表里有行引用了AUTO_INCREMENT列里的值,那么调整该列的编号将破坏这两个表之间的对应关系。
这种策略的一种用途是,创建一个只有一个行的表,其中包含一个在每次需要该序列里下一个值 时都会进行更新的值。例如,可以像下面这样创建和初始化这个表:
CREATE TABLE seq_table (seq INT UNSIGNED NOT NULL); INSERT INTO seq_table VALUES(0);
- 上面这些语句会创建一个只有一个行的seq_table表,其中seq的值为0。为生成下一个序列编号 ,并对它进行检索,可以这样做:
UPDATE seq_table SET seq=LAST_INSERT_ID(seq+1); SELECT LAST_INSERT_ID();
- 上面的UPDATE语句将检索seq列的当前值,并把它加上1,从而产生该序列的下一个编号。利用LAST_INSERT_ID(seq+1)生成的新编号值,与AUTO_INCREMENT值很相像,因此可以通 过不带参数调用LAST_INSERT_ID()的方式来检索它。LAST_INSERT_ID()函数是客户端专用的,因此即使在UPDATE和SELECT两个操作之间的时间间隔里,其他客户端程序又生成多个序列编号,你也会检索到正确值。
- 利用这种方法,可以生成步长不为1(甚至可以为负值)的序列编号。例如,反复执行下面这条语句,将生成一个步长为100的序列:
UPDATE seq_table SET seq=LAST_INSERT_ID(seq+100);
- 反复执行下面这条语句将生成一个递减序列:
UPDATE seq_table SET seq=LAST_INSERT_ID(seq-1);
- 你也可以生成一个从任意值开始编号的序列,只要给seq列设置一个合适的初始值就行。
- CREATE TABLE counter
- (
- name VARCHAR(255) CHARACTER SET latin1 COLLATE latin1_general_cs NOT NULL,
- value INT UNSIGNED,
- PRIMARY KEY(name)
- );
- INSERT INTO counter(name,value)
- VALUES('index.html',LAST_INSERT_ID(1))
- ON DUPLICATE KEY UPDATE value=LAST_INSERT_ID(value+1);
- SELECT LAST_INSERT_ID();
- UPDATE counter SET value = value+1 WHERE name='index.html';
- SELECT value FROM counter WHERE name='index.html';
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。