mysql面试题
数据库设计过程
1、需求分析:分析用户的需求,包括数据、功能和性能需求
2、概念结构分析:主要采用E-R模型进行设计,包括花E-R图
3、逻辑结构设计:通过将E-R图转换成表,实现从E-R模型到关系模型的变换
4、数据库物理设计:主要是为所设计的数据库选择合适的存储结构和存取路径
5、数据库实施:包括编程、测试和试运行
6、数据库运行与维护:系统的运行与数据库的日常维护
什么是MVCC
MVCC叫做多版本并发控制,全称是Muli-Version Concurrent Control
。是一种多版本并发控制的方法,在数据库管理系统中,实现对数据库的并发访问,在编程语言中实现事务内存。
MVCC实现原理
InnoDB的MVCC是通过read view
和版本链(三个隐藏式字段)还有undo日志实现的,版本链保存有历史版本记录,通过read view
判断当前版本是否可见,如果不可见,再从版本链中找到上一个版本,继续判断直到找到一个可见的版本
- read view:将数据在每个时刻的状态拍成“照片”记录下来。在获取某时刻t的数据时,到t时间点拍的“照片”上取数据
- 版本链是通过表的三个隐藏字段实现。
DB_TRX_ID
当前事务id、DB_ROLL_PRT
回滚指针、DB_ROLL_ID
主键
当前读和快照读
- 当前读:它读取的是数据库记录的最新版本,在读取时还有保证其他的并发事务不会修改当前记录,会对读取的记录进行加锁。比如select lock in share mode(共享锁)、select for update、update、insert、delete操作都是当前读
- 快照读:前提是隔离级别不是串行级别,串行级别的快照读会退化成当前读,而使用快照读是基于提高并发性能的考虑,它实现的是多版本并发控制值,就是MVCC。在很多情况下,避免了加锁操作,减少了开销,比如不加锁的select操作就是快照读,即不加锁的非阻塞读操作。但是快照读读到的不一定是数据的最新版本,也有可能是历史版本,因为它是基于多版本的
MVCC实现的原因
在写并发读写数据库时,读操作可能会有不一样的数据。为了避免这种情况,需要实现数据库的并发访问控制,最简单的方法就是加锁访问。由于加锁会将读写操作串行化,所以不会出现不一致的状态。但是,读操作会被写操作阻塞,大幅减低读性能,而在javaconcurrent包中,有copywrite系列的类,专门用于优化读大于写的情况。
优化的手段是,在进行写操作时,将数据copy一份,不会影响原有数据,然后进行修改,再原子替换旧的数据,而读操作只会读取原有数据。通过这种方式实现写操作不会阻塞读操作,从而优化读写效率。但是写操作之间是互斥的,并且每次写操作都会有一次copy的操作,所以只适合读大于写的情况
在MVCC协议下,每个读操作会看到一个一致性的snapshot,并且可以实现非阻塞的读。MVCC允许数据具有多个版本,这个版本可以是时间戳或者是全局递增的事务ID,在同一个时间点,不同的事务看到的数据是不同的。
mysql的innodb引擎实现MVCC
innodb会为每一行添加两个字段,分别表示创建该行创建的版本和删除的版本,填入的是事务的版本号,这个版本号随着事务的创建不断递增。
数据库各种操作:
select:
1、该行的创建版本号小于等于当前版本号,用于保证select操作之前所有操作的已经执行完成
2、该行的删除版本号大于当前版本号或者为空,意味着有一个并发事务将该行删除了
insert:将新插入的行的创建版本号设置为当前系统的版本号
delete:将删除的行的创建版本号设置为当前系统的版本号
update:不执行原地update,而是转换成insert+delete。将旧行的删除版本号设置为当前版本号,insert操作时将新行创建版本号同时设置为当前版本号
其中,写操作执行时,是需要将系统版本号递增的,包括insert,delete,update
操作
注意:
1、由于旧数据并不真正的删除,所以必须对这些数据进行清理,innodb会开启一个后台线程执行清理工作,具体的规则是将删除版本号小于当前系统版本的行删除,这个过程叫做purge。
2、通过MVCC很好的实现了事务的隔离性,可以达到repeated read级别,要实现serializable还必须加锁。
具体实例
1、在user表中执行id小于等于3的操作
select * from user where id<=3
实际上:
select * from user where id<=3 and create_version<=3 and (delete_version>3 or delete_version is null);
实际上每行数隐藏了两列,创建时间版本号,删除时间版本号,每开始一个新的事务,版本号都会自动递增。
a-draft-type=“table” data-size=“normal” data-row-style=“normal”>
id name create_version delete_version
执行select操作前,假设current_version = 3
2、修改id为1的数据,此时current_version = 4
update user set name = "zhangsan" where id=1
执行完结果是后面也会有:
a-draft-type=“table” data-size=“normal” data-row-style=“normal”>
id name create_version delete_version
索引
在Mysql中也是一种“键”,是存储引擎用于快速查询的一种数据结构。索引优化是对查询性能优化最有效的手段,能够对查询性能提升几个数量级
索引原理
通过不断地缩小数据的范围来筛选出最终想要的结果,同时把随机的事件变成顺序的事件。数据库也是用索引来查询的,但要复杂的多,还有等值查询、范围查询、模糊查询等等。按照索引的原理可以进行分段查询,而当数据成千上万时,如何分段
可以按照搜索树的模型,其平均复杂度为lgN,有着不错的查询性能,但是数据库实现较为复杂,一方面数据保存在磁盘上,另外一方面为了提高性能,每次又将部分数据存入内存来计算,采用分块读取,所以Mysql的InnoDB存储引擎用的是B+树的储存结构,而一块读取称为一页读取
优缺点
优点:
- 通过创建数唯一索引可以保证数据库每一行数据的唯一性
- 可以给所有的mysql列类型设置索引
- 大大加快数据查询的速度
缺点:
- 维护索引很昂贵,特别是插入新行或者主键更新导致分页时
- 索引需要磁盘空间,除了在数据表中占用数据空间,每一个索引都需要占一定的物理空间
创建索引
1、使用alter table
命令
--普通索引
alter table table_name add index index_name(column_list)
--column_list指出对哪些列进行索引,多列时各列之间用逗号分隔
--唯一索引
alter table table_name add unique index_name(column_list)
--全文索引
alter table table_name add fulltext index_name(column_list)
注:
alter table用来创建普通索引、unique索引或primary key索引
2、使用create index
命令
create index index_name on table_name(column_list)
create unique index index_name on table_name(column_list)
create fulltext index index_name on table_name(colmn_list)
CREATE INDEX 可对表增加普通索引或 UNIQUE 索引
# 实例:将id设为主键索引,userId设为普通索引,索引名为idx_userid,name设为唯一索引,索引名u_name
CREATE TABLE user (
id int(11) NOT NULL AUTO_INCREMENT,
userId varchar(32) NOT NULL,
age varchar(16) NOT NULL, name varchar(255) NOT NULL,
PRIMARY KEY (id),
KEY idx_userid (userId),
UNIQUE INDEX u_name (name)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
删除索引
DROP INDEX <索引名|index_name> ON <表名|table_name>
DROP INDEX sampleId ON sampleInfo
DROP PRIMARY KEY ON <表名> 表示删除表中的主键
DROP FOREIGN KEY fk_symbol ON <表名|table_name> 表示删除外键
索引设计原则
1、对查询次数频数较高,且数据量较大的表中建立索引,mysql将同一个表中的索引总数设置为16
2、索引字段的选择,应当挑选最常用、过滤效果最好的列的组合
3、使用唯一索引,区分度高,使用效率越高
4、索引可以有效的提升查询数据的效率,但是索引数量不是越多越好,越多,维护的代价也就越大。对于插入、更新、删除等DML操作比较繁琐的表来说,索引过多,维护的代价越大
5、使用段索引,索引创建之后使用硬盘来储存的,因此提升索引访问的I/O效率,提升总体的效率。假如构成索引的字段总长度比较短,那在给定大小的存储块内,可以存储更多的索引值,相应的可以有效地提升mysql访问索引的I/O效率
6、利用最左前缀的原则,N个列组合而成的组合索引,相当于创建了N个索引。如果查询时where子句使用了组成该索引的前几个字段,那么这条查询sql可以利用组合索引来提升查询效率
7、索引可以加快数据检索操作,但会使数据修改操作变慢。每修改数据记录,索引就必须刷新一次。为了弥补这一缺陷,许多sql命令都有一个DELAY_KEY_WRITE
项。这个项的作用是暂时制止Mysql在该命令每插入一条新记录或者修改之后立刻对索引进行刷新,对索引的刷新等到所有的记录插入或修改完毕之后再进行
8、如果某个数据列包含许多重复的内容,为他建立索引没有太大的效果
9、表记录行数较少或者经常插入、删除、修改的表不应创建索引
索引的数据结构
Mysql中主要用到:B+ Tree索引、hash索引、fulltext和RTREE索引
- InnoDB存储引擎默认是B+Tree索引
- MEMORY存储引擎默认是hash索引
- 目前只有MyISAM引擎支持
- RTREE在Mysql中很少使用,仅支持geometry数据类型
1、Mysql中只有Memory存储引擎显示支持Hash索引,是Memory表的默认索引类型,而Memory表只存在与内存中,断电会消失,适用于临时表,但是Memory表也可以使用B+Tree索引。
Hash索引是基于hash表是实现的,对于每一行数据,存储引擎对索引列进行hash计算得到hash码,并且hash算法尽量保证不同的列值计算出的hash值是不同的,之后会将hash码作为key值,将指向数据行的指正作为hash表的value值
2、B+Tree索引是InnoDB和Myisam存储引擎的索引类型。B+Tree是基于B树和叶子节点顺序访问指针进行实现,具有B树的平衡性,并且通过顺序访问指针提高了区间查询的性能
3、全文索引(FULLTEXT)只有char
、varchar
、text
列上可以创建全文索引
4、RTREE索引,相较于BTree
,优势在与范围查找
B+ Tree索引和hash索引的区别
索引 | 查询单条记录 | 范围查询 | 排序 |
---|---|---|---|
B+Tree | 较慢 | 快 | 适合 |
Hash | 较快 | 慢 | 不适合 |
1、Hash索引将数据以hash形式组织起来,所以查找记录时,速度非常快,但是hash索引的结构,每一个键对应一个值,而且是散列的方式分布,因此也不支持范围查找和排序等功能。
2、因为hash表中会存在哈希冲突,哈希索引的性能是不稳定的,而B+Tree的性能相对稳定,每次查询都是从根结点到叶子节点
覆盖索引
覆盖索引是对select的数据列只用从索引中就能获取数据,不需要回表进行二次查询,即查询列要被所使用的索引覆盖
覆盖索引的优点
1、索引条目远小于数据行大小,只需要读取索引,就可以大大减少数据访问量
2、索引按顺序存储,对于IO密集类型的范围查询会比从磁盘读取每一行数据的IO要少
3、对于InnoDB表的二级索引,如果索引能覆盖到查询的列,那就可以避免对主键索引的二次查询
4、MyISAM在内存中只缓存索引,数据依赖操作系统来缓存,访问数据需要一次系统调用
注意:不是所有类型的索引都可以成为覆盖索引,覆盖索引要存储索引列的值,而哈希索引、全文索引不存储索引列的值,所以只有B+数索引可以用过覆盖索引
原始的:
SELECT * FROM `tbl_works`
WHERE `status`=1
LIMIT 100000, 10 // 78.3 秒
覆盖索引优化后:
SELECT * FROM tbl_works t1
JOIN (
SELECT id from tbl_works WHERE status=1
limit 100000, 10) t2
ON t1.id = t2.id // 53.6 ms
通过自连接与join
定位到目标 ids
,然后再将数据取出。在定位目标 ids
时,由于 SELECT
的元素只有主键 ID
,且status
存在索引,因此MySQL只需在索引中,就能定位到目标 ids
,不用在数据文件上进行查找。因而,查询效率非常高。
前缀索引
前缀索引是对文本或者字符串的前几个字符建立索引,索引的长度较短,查询速度更快
需要在很长的字符上创建索引,会造成索引特别大并且查询速度慢,而使用前缀索引可以避免这个问题。创建前缀的关键在与选择足够长的前缀保证较高的索引选择性
最左前缀匹配原则
在Mysql建立联合索引时会遵守最左前缀匹配原则,即最优优先,在检索数据时从联合索引的最左边开始匹配
Mysql创建联合索引的规则就是首先对联合索引的最左边第一个字段进行排序,然后在此基础上进行对第二个字段进行排序
导致索引失效的情况
1、对于组合索引,不使用组合索引的最左边的字段,则不会使用索引
2、范围查询,如使用%开头或者结尾的like查询
3、查询条件中列类型是字符串,没有使用引号,可能因为类型不同发生隐式转换,致使索引失效
4、判断索引列是否不等于某个值
5、对索引进行计算
6、查询条件使用or连接
索引的设计原则
1、使用区分度高的字段作为索引列,索引的效果更好
2、尽量使用短索引,对于较长的字符串进行索引时应该指定一个较短的前缀长度,因为较小的索引涉及的磁盘I/O较少,查询速度更快
3、索引不是越多越好,每一个索引都需要额外的物理空间
4、使用最左前缀原则
为什么Mysql用B+树
B树
特点
1、节点排序
2、一个节点可以存放多个元素,并且多个元素也进行了排序
3、一个节点可以存放多少个元素取决于max.degree的值,当max.degree等于3时,说明最多可以有三个节点,一个节点里面有最多有两个元素
以Max.Degree=3为例的b树
B+树
特点
1、拥有B树的特点
2、叶子节点之间有指针
3、非叶子节点的元素在叶子节点都冗余了,叶子节点中存储了所有元素,并且排序所有元素
4、有着两种类型的节点:内部节点和叶子节点。内部节点就是非叶子节点,不存储数据,只存储索引,父节点就存有右孩子的第一个元素的索引,而数据存储在叶子节点中
案例
Mysql用B+树
Mysql使用的B+树并不是上面的B+树,是在原来基础上,增加了一个指向相邻叶子节点的链表指针
MySQL中的 B+Tree 索引结构示意图:
索引可以加快查询,B+树通过对数据进行排序,能够提高查询速度,并且B+树上的一个节点可以存储多个元素,因此B+树的高度不会太高
在mysql中一个innoDB页就是一个B+树节点,而一个innodb页默认是16kb,所以一般情况下一棵两层的B+树可以存放2000万行左右的数据,通过利用B+树子节点存储数据并进行排序,而且叶子节点之间有指针,可以很好的支持全表扫描,范围内查找等SQL语句
ACID靠什么保证
事务是作为单个逻辑单位工作单元执行的一系列操作,这些操作作为一个整体一起向系统提交,要么都执行或者都不执行。事务是不可分割的工作逻辑单位。
原子性(Atomicity)
1、事务是一个完整的操作,事务的各步操作时不可分割的,是原子的,要么不执行,要么都执行
2、原子性是由undo log日志保证的,记录了需要回滚的日志信息,事务回滚时撤销已经执行成功的sql
一致性(Consistency)
1、当数据完成时,数据必须保持一致状态
2、一致性一般由代码层面来保证
隔离性(Isolation)
1、对数据进行修改的所有并发事务是彼此隔离的,这表明事务必须是独立的,它不应以任何方
式依赖于或影响其他事务
2、隔离性由MVCC来保证
永久性(Durability)
1、事务完成后,它对数据库的修改被永久保持,事务日志能够保持事务的永久性
2、持久性由内存+redo log来保证,mysql修改数据同时在内存和redo log记录这次操作,事务提交的时候通过redo log刷盘,宕机的时候可以从redo log恢复
这就是ACID
MyISAM和InnoDB的区别
Mysql的架构
Mysql主要分为Server层和存储引擎层
存储引擎主要负责数据的存储和读取。server层通过api与存储引擎进行通信
Server层主要包括连接器、查询缓存、分析器、优化器、执行器等,所有跨存储引擎的功能都在在这一层实现,比如存储过程、触发器、视图、函数等,还有一个通用的日志模块binglog
日志模块
常用的存储引擎
Mysql中常用的四种存储引擎分别是:MyISAM
,InnoDB
,MEMORY
,ARCHIVE
。而在Mysql5.5版本后默认的存储引擎是InnoDB
InnoDB是Mysql默认的事务型存储引擎,使用最广泛,基与聚蔟索引建立的。InnoDB内部做了很多优化,能够自动在内存中创建自适应hash索引,用来加速读操作
MyISAM引擎,适用于只读数据,或者表比较小、可以容忍修复操作。而MyISAM引擎会将表储存在两个文件中,数据文件.MYD
和索引文件.MYI
MEMORY引擎将数据全部放在内存中,访问速度较快,但是系统一旦奔溃的话,数据都会丢弃的
ARCHIVE存储引擎适合存储大量独立的、作为历史记录的数据。他提供了压缩功能,拥有高效的插入速度,但是这种引擎不支持索引,因此查询性能较差
MyISAM和InnoDB的区别
1、使用锁的不同
MyISAM
不支持行级锁,只有表级锁,而InnoDB
支持行级锁和表级锁,默认为行级锁
2、是否支持外键
MyISAM
不支持外键,而InnDB
支持外键,对于一个包含外键的InnoDB
转为MYISAM
会失败
3、事务是否支持
MyISAM
不提供事务支持,而InnoDB
提供事务支持,具有事务、回滚和崩溃修复能力
4、是否支持MVCC
MyISAM
不支持MVCC,而InnoDB
支持,在应对高并发事务时,MVCC比单纯的加锁更高效
5、是否支持聚集索引
MyISAM
不支持聚集索引,使用B+树作为索引结构,索引和数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的
而InnoDB
支持聚集索引,也是使用B+树作为索引结构,数据文件和主键是绑定在一起的,主键索引的叶子节点就是数据文件,辅助节点的叶子节点是主键的值
分区表
分区表是一个独立的逻辑表,但是底层由多个物理子表组成
当查询条件的数据分布在某个分区的时候,插序引擎只会去每一个分区查询,而不是遍历整个表
在管理层面,需要删除某一个分区的数据,只需要删除对应的分区即可
分区表的类型
1、按照范围分区
2、按照“List”分区,分区字段必须是已知的,如果插入的字段不在分区时枚举值中,将无法插入
3、hash分区,可以将数据均匀分布到预先定义的分区中
分区表的问题
1、打开和锁住所有底层表的成本可能很高。当查询访问分区表时,MySQL需要打开并锁住所有的底层表,这个操作在分区过滤之前发生,所以无法通过分区过滤来降低此开销,会影响到查询速度。可以通过批量操作来降低此类开销,比如批量插入、LOADDATA INFILE和一次删除多行数据。
2、维护分区的成本可能很高。例如重组分区,会先创建一个临时分区,然后将数据复制到其中,最后再删除原分区。
Mysql的隔离级别
mysql定义了四种隔离级别,包括一些具体规则,用于限定事务内外哪些是可见的,哪些是不可见的。一般低级别的隔离支持更高的并发处理,并且拥有更低的系统开销,mysql默认的隔离级别是可重复读
读取未提交内容(read uncommitted)
在这个隔离级别下,所有事务都可以“看到”未提交事务的执行结果。在这种情况下,效率很高,但是产生的问题也很多。除非符合特殊的情况,对于此有很好的使用。这个隔离级别很少用于实际应用,他的性能比起其他的隔离级别只是较好,而别的隔离级别还有其他的他所不具备的优点。
对于读取到未提交内容,也称为脏读。A事务修改数据,B事务读取数据后事务A报错回滚,修改的数据没有提交到数据库中,而事务B读取到修改的数据就是脏读
可能会出现脏读、不可重复读、幻读的问题
读取提交内容(read committed)
大多数数据库系统默认的隔离级别,但不是Mysql的默认隔离级别。一个事务开始时,只能“看见”已经提交事务所做的改变,一个事务从开始提交前,所做的任何数据改变都是不可见的,除非已经commit。但是不支持不可重复读,解决了脏读的问题。
当A事务执行两个select语句,而B事务在两个select语句执行的间隔里执行了update操作,这时看到的结果是不同的,这就是不可重复读
可能会出现不可重复读、幻读的问题
可重复读(repeatable read)
Mysql默认的隔离级别,解决了read committed隔离级别的不可重复读。他保证了同一事务的多个实例在并发读取事务时,会看到同样的数据,但是又会导致“幻读”问题,而这一问题在InnoDB存储引擎通过多版本并发控制(MVCC)解决了
幻读是事务非独立执行时发生的一种现象,事务A中对一个表中属性值为1 修改为2,但是事务B对这个表插入了一条属性值为1 的数据,并且完成提交。而事务A查看完成后的数据,还有一条未完成修改的数据,就是刚刚插入的数据,就是幻读
可能会出现幻读的问题
可串行化(serializable)
是最高级别的隔离级别。通过强制事务排序,使之不可能相互冲突,解决了幻读问题。而他的操作就是给每一个读和写的数据行上加锁,所以效率较低,可能导致超时和锁竞争现象。实际情况下很少使用,但是为了数据的稳定,需要强制减少并发,也可以选择
Mysql如何实现主从同步
主从同步原理
- master提交完事务后,写入binlog日志中
- slave连接到master,获取binlog日志
- master创建dump线程,推送binlog到slave
- slave启动一个IO线程读取同步过来的master的binlog,记录到relaylog
中继日志
- slave再开启一个sql线程读取relaylog事件并在slave执行,完成同步
- slave记录自己的binlog
函数
数学函数
- ABS(num) 绝对值
- BIN(num) 十进制转二进制
- CELLING(num) 向上取整,得到比num大的最小整数
- FLOOR(num) 向上取整,得到比num小的最大整数
- CONV(num1,from_base,to_base) 将num1从from_base进制转换成to_base进
- FORMAT(num,decimal_places) 保留小数位数(四舍五入)
- ROUND(num,decimal_places) 保留小数位数
- LEAST(num1,num2,..) 求最小值
- MOD(num1,num2) 求余
时间函数
- current_date() 当前日期
- current_time() 当前时间
- current_timestamp() 当前时间戳
- datediff(date1,date2) 两个日期差(天)
- date_add(date,interval value minute) date加上日期或者时间
select * from mes where DATE_ADD(send_time.INTERVAL 10 MINUTE) >= NOW()
--查询在十分钟内发布的新闻
- date_sub(date,interval value minute) date减去日期或者时间
select * from mes where send_time >= DATE_SUB(NOW(),INTERVAL 10 MINUTE)
--查询在十分钟内发布的新闻
- unix_timestamp() 返回1970-1-1到现在的秒数
- from_unixtime()
select FROM_UNIXTIME(1618483484,'%Y-%m-%d') from ...
--存放一个整数,表示时间,通过FROM_UNIXTIME()转换
- timestampdiff(unit,datetime_expr1,datetime_expr2) 按照unit返回两个日期差
unit:year,quarter(季),month,day,week,hour,minute,second
加密函数和系统函数
- USER() 查看登录到mysql的有哪些用户以及登录的ip
- DATEBASE() 查看当前使用数据库名称
- MD5() 加密
流程控制函数
- IF(expr1,expr2,expr3) 如果expr1为true,则返回expr2,否则返回expr3
- IFNULL(expr1,expr2) 如果expr1不为null,返回expr1,否则返回expr2
- case expr1 when ‘expr2’ then ‘2’ when ‘expr3’ then ‘3’ end 当expr1字段的值为expr2,则返回2;当expr1字段的值为expr3,则返回3
- case when expr1 then expr2 else expr3 当expr1为true,则返回expr2,否则返回expr3。可以配合sum()函数统计符合复杂条件的记录
any_value()函数
在使用group by时某些字段无法使用,select的数据要么来自聚合函数(sum,avg,max等),要么来自group by 中的值,是因为ONLY_FULL_GROUP_BY是mysql中的一个sql mode,会强制对group by 子句进行严格的限制,而any_value()函数可以抑制ONLY_FULL_GROUP_BY值被拒绝
字符串函数
LEFT函数
LEFT 字符串函数从结构化查询语言中的原始字符串的左侧检索到给定索引值的字符
SELECT LEFT(Column_Name, Index_position) AS Alias_Name FROM Table_Name;
select left('abcd',3);//结果abc
CHAR_LENGTH()、LENGTH()
CHAR_LENGTH和LENGTH函数都可以用来计算字符串的长度,在处理多字节字符和字节长度有区别
- CHAR_LENGTH函数返回字符串的字符数,每个字符均被计算。例如,对于多字节字符(如汉字或包含两个字节的字符集),CHAR_LENGTH将其视为一个字符
- LENGTH函数返回字符串的字节数,而不是字符数。对于多字节字符,LENGTH可能会返回比实际字符数更大的长度。这是因为LENGTH按照字节来统计长度,而不是按照字符。
对于包含5个字符且每个字符占两个字节(比如汉字)的字符串,CHAR_LENGTH返回长度为5,而LENGTH返回长度为10。如果对于单字节的字符(如ASCII字符),CHAR_LENGTH和LENGTH返回的结果相同。
upper()和lower()
upper函数是将字符串中的所有字符转换成大写,lower函数是将字符串中的所有字符转换成小写。对于非字母字符(数字、空格等)不会产生影响
表操作
重置自增列
1、删除原表数据并重置自增列
truncate table tablename
2、保留数据并重置表自增列
DBCC CHECKINENT('tablename',RESEED,0)
注:
显式插入自增列:可以在insert语句中明确指定要插入的自增列的值。通常情况下,自增列的值会自动分配,无需指定。但是,在一些情况中,可能需要再插入数据时明确听过自增列的值
set IDENTITY_INSERT tableName on;
INSERT INTO tableName (column1, column2, column3) VALUES (value1, value2, value3);
SET IDENTITY_INSERT tableName OFF;
--column3是一个自增列,但在INSERT语句中明确提供了它的值。通过将SET IDENTITY_INSERT设置为ON,允许显式插入自增列,然后执行INSERT语句插入数据,最后再将SET IDENTITY_INSERT设置为OFF,禁止显式插入自增列。
修改表
1、在字段level的后面增加一列最多可以保存15个汉字的字段school
alter table user_info add school varchar(15) after level
2、将job列名改为profession,同时varchar字段长度变为10
alter table user_info change job profession varchar(10)
3、achievement的默认值设置为0
alter table user_info modify achievement int(11) default 0
删除表
drop table if exists tableName;