面试数据库(二)—— 增删改查CRUD

增加(Create)

检索(Retrieve)

更新(Update)

删除(Delete)

 

 

上面抽象意义的概括,如果用具体的sql命令简写表示,则为IDUS

1)增(INSERT)

INSERT into tableName (col1,col2...coln) values (value1,value2...valuen);

当然,如果能保证是全值插入,则可以省略tableName后面的列名(但values不能省):

INSERT into tableName values (value1,value2...valuen);

1)tableName后面的列名用于部分值插入时,将values的值对应到列中去,如

insert into tableName(col1,col3,col5) values(value1,value2,value3);

就将values(value1,value2,value3)分别插入到tableName的第1,3,5列中去了。

这里提一句:那么没有指定的列的值怎么办?——按照定义表时列的default 值来自动填入,如果没有默认值但是允许为NULL则填入NULL值。如果定义表时既没有指定默认值,也没有允许为空(NOT NULL),怎么办?

会报错。。。。此条insert语句不能成功执行,插入记录失败。

2)如果指定的列(tableName后面的列名)中有主键列,则插入值一定要保证不与已经存在的主键重复

insert into tableName(col3,col1,col5) values(value1,value2,value3); 中col1,col2,col3没有一个是主键列,则插入时,MySQL会使用设计表时的auto_increment策略:

但是,如果insert into tableName(col3,col1,col5) values(value1,value2,value3); 指定列中存在主键列,现在假设col1是主键列,则要保证value2与表中已经存在的主键不重复,否则会插入失败,报错:

插入id为1失败:

如果与与表中已经存在的主键不重复,则会成功,如插入id = 3:

并且以后都是从3往后递增:

值得注意的是,此时回头看

“insert into tableName(col3,col1,col5) values(value1,value2,value3);” 指定列中存在主键列

是可以插入中间“空闲的id”的,e.g:

用户

但是,此时不指定id的insert还是会从6开始,而不是2。即MySQL自己为维持一个最大指针,如果使用auto_increment,而不是用户指定id,则从这个最大指针往后追加。

 

综上所述,MySQL的策略是这样的:如果指定了主键自增(id int(11) NOT NULL primary key auto_increment;),则:

若用户指定id,则检查表中是否已经存在,不重复才会插入,并且如果此指定id大于当前最大id指针,则更新此最大id指针,相当于中间的id都skip掉了;

若不指定id,则MySQL自己添加id,规则追加在维持的最大id指针的后面。

可以看到,MySQL支持利用间隙之间的id,也支持直接skip掉一段id,但是这个只是MySQL提供的灵活性,在实际应用中,尽量避免用户自己指定id的情况,数据库数据的完整性不能由用户数据来保证,不管什么什么情况都应该使用主键自增的设定,并且插入时使用不指定id的插入方式(insert into tableName(col3,col1,col5) values(value1,value2,value3);中的col不应该有主键列)。

2)删(DELETE)

DELETE from tableName [WHERE Clause];  

前面有个细节:where cause使用方括号 [] 包围起来的——是可选的,即可以不使用,那么delete变成了:

DELETE from tableName;

这代表删除这张表中的所有数据,注意不是删除表:

但是注意, delete不会重置主键,主键自增的属性使下次insert时接着上次最大的id+1开始:

如果想清空表并且重置主键可以使用 truncate命令:

TRUNCATE table tableName;

但是注意,这个命令要慎用,要保证需求是删除全部数据而不是删除一部分,并且以后永远不不着这部分数据;另外,本表中的id不是任何其他表的外键,不然一旦删除从1重新开始,会使其他表连接到本表的新数据,这会导致严重错误。

 

3)改(UPDATE)

UPDATE table_name SET field1=new-value1, field2=new-value2 [WHERE Clause];

其实和DELETE很像,可以使用WHERE子句更新特定行,也可以不使用WHERE子句更新所有行:

特定行:

所有行:

一个很有趣的问题是:能update主键的值吗?

试试便知:

成功了,可以想见,改成7也是可以的。

其实update就是将特定的值重新赋值的过程,机制相当于INSERT,只是代价更小,只用更新特定的列即可。

但是,修改id同样是强烈不推荐的,这个insert不指定id是一个道理。

 

 

4)查(SELECT)

单表查询:

select是最复杂的语句,先看单表查询:

select col1,col2... from tableName [WHERE Cacuse];

当然,可以对查出的列作各种“运算”:拼接字符串Concate,统计个数count,求最大值max,起别名AS等等。

 

 

多表查询:

内连接 inner join(MySQL的默认连接方式:join 就是inner join)

准备两张表:家长表和学生表

parent:

student:

可以看到,Chenwei的孩子Tom,Wangjianguo的孩子Jerry,Lilin的孩子HH。

使用inner join:

 

要注意语法,很容易错误,如果是select * from 内连,则全部列都被列出来:

 

左连接 left join(左表所有记录都在,右表没有的为NULL)

一定要注意顺序,另外也要注意一些“潜规则”:

① select顺序不影响left join,但是Concat会影响

以某一键(上例中id)进行左连接,是从左表中按顺序拿出一个个id(遍历)去右表中查找有无记录,这样做最终的结果里必然是左表中的记录肯定有(除非select的刚好是NULL的记录),右表中不一定有(NULL)。select的顺序并不会影响结果。

为了更形象地展示,还是上面的例子,将select s.name, p.name 换成 select p.name,s.name:

看下原始列值和Concat拼接结果:

select s.name,s.name

select p.name,s.name

即concate任意一列为null时,直接返回结果null,而不是带有部分值的结果。

② A a left join B b  等于 B b right join A a

不多说,明显是对的 

 

右连就是左连,不多说

 

不使用join实现连接:

① 使用from多表+where替代on

select p.name,s.name from parent p,student s where p.childid = s.id;

 

② 子查询

但是子查询方式下,主select“看不见”子select的信息,所以上面只能取到p.name,不能拿到s.name:

显而易见,也可以使用EXISTS:

 

这里还稍微再po一下IN和EXISTS的区别:

可以看到,IN是先扫描外表,再进内表

EXISTS是先扫描内表,再扫外表。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值