内容概述

● 数据添加:

(1)INSERT语句可以一次写入一条记录,也可以一次写入多条记录;

(2)在写入多条记录的时候,如果因为一条记录写入失败,导致整条INSERT语句其他数据的写入失败,这是非常不好的,于是引入了IGNORE关键字。使用了IGNORE关键字后,不管是因为违反了什么约束条件,或者是数据类型不对,即便数据写入失败,MySQL也不会报错,只是忽略这条写入的记录,而不影响后面的其他语句;

(3)INSERT方法语言;

(4)INSERT子查询:先根据一些条件查询出数据,然后把查询出的数据作为插入的内容;

● 数据修改:

(1)UPDATE语句中也是可以使用子查询的:比如“把工资高于张三工资的人的工资,降低100块”,就需要先查询张三的工资,然后去查询谁的工资比张三高,然后才是修改工资数据;为了更好的实现这种类似的业务,UPDATE表连接的语法就派上用场了。

(2)UPDATE表连接:只在MySQL具备;Oracle是不具备的;

● 数据删除:

(1)DELETE语句中也是可以利用表连接的:以实现复杂的业务;


注:表连接应用十分广泛!

INSERT语句

前面着重介绍了查询语句,因为在实际工作中,增、删、改、查,使用的最多的就是查询语句。同时,绝大多数软件系统,都是读多写少的,查询的条件也是各种各样,所以前面着重介绍了查询语句。


一:INSERT语句简介

案例1:一次插入一条数据 :向t_dept表中增加一条记录;

​
    INSERT INTO t_dept(deptno,dname,loc)
    VALUES(50,"技术部","北京");

案例2:一次插入多条数据 :向t_dept表中增加多条记录;

    INSERT INTO t_dept(deptno,dname,loc)
    VALUES(60,"后勤部","北京"),(70,"保安部","北京");

案例3:INSERT中附带子查询 :向t_emp表中,插入一条部门为技术部的员工信息;

这种子查询,是将子查询放在了VALUES中了;这种情况下,子查询的结果需要是单行子查询,即子查询的结果必须是单行单列的;

​
    INSERT INTO t_emp(empno,ename,job,mgr,hiredate,sal,comm,deptno)
    VALUES(8001,"李四","SALESMAN",8000,"1988-12-20",2000,NULL,(SELECT deptno FROM t_dept WHERE dname="技术部"));


二:INSERT语句方言

SQL的方言:只能在某一个数据库上执行的方言语法,不具备如通用型。MySQL的方言只能在MySQL上执行,Oracle的方言只能在Oracle上执行。

如:

​
    INSERT INTO t_emp SET empno=8002,ename="李明",job="CLEARK",mgr=7782,hiredate="1985-5-18",sal=2500,comm=NULL,deptno=50;

INTO关键字可以不写

​
    INSERT t_emp SET empno=8003,ename="刘三",job="CLEARK",mgr=7782,hiredate="1985-5-18",sal=2500,comm=NULL,deptno=50;


三:IGNORE关键字

IGNORE关键字:可以让INSERT语句忽略冲突的记录,只写入那些不冲突的记录。比如用INSERT写入多条记录的时候,某一条记录数据没写对,产生了注入主键冲突或唯一值的冲突等,此时,数据库会报错然后整个INSERT语句连一条语句都写不进去。。。但是如果使用了IGNORE关键字,就可以忽略冲突的记录,不冲突的记录还是能写到数据库里的;


四:INSERT子查询:将子查询的结果集全部插入

INSERT语句中可以包含子查询语句,代表把子查询的内容写入到数据表

如:把人数超过5人的部门记录拷贝到新的部门表:

先创建t_dept_new表:

​
    CREATE TABLE t_dept_new LIKE t_dept;

然后,查询数据,将查询的数据插入到t_dept_new表中:下面省略了VALUES哎。

    INSERT INTO t_dept_new(deptno,dname,loc)
    (SELECT d.deptno,d.dname,d.loc FROM t_dept d JOIN(SELECT deptno FROM t_emp GROUP BY deptno  HAVING COUNT(*)>=5) temp ON d.deptno=temp.deptno);


注:

REPLACE INTO语句:

(1)和INSERT INTO语句类似,都可以写入数据;

(2)在使用IGNORE的情况下,INSERT INTO 会忽略产生冲突的记录,REPLACE INTO语句会将产生冲突的记录进行替换;

UPDATE语句

注:(1)内连接可以不使用ON或者WHERE;外连接必须使用ON子句,否则会报错!!!

(2) UPDATE确定数据源头(或者说,UPDATE子句确定“待操作数据集”),WHERE子句:对“待操作数据集”做二次筛选。

(3)案例4: 这个例子说明,UPDATE语句可以同时修改多张表。。。

(4)子查询不能在 UPDATE 语句中使用的原因:首先,在 UPDATE 中使用子查询,这会是相关子查询,效率很低;然后,MySQL 不允许对要更改或要删除记录的数据表做子查询(很显然,动脑子想一想也明白了);


一:UPDATE语句简介

● UPDATE子句,选择要修改的表;UPDATE子句只执行一次;

IGNORE关键字可写可不写,作用是在写入数据的时候,如果遇到冲突就直接忽略。

● WHERE子句:筛选要修改的记录;

● ORDER BY子句的应用场合:把筛选出的记录进行排序。比如,当修改记录的主键的时候,给主键值都加1的时候,就需要把数据降序排列,这样才不会在修改主键的时候发生唯一性冲突;(自然如果给主键值都减1,就需要把数据升序排列了);

LIMIT子句:这儿的LIMIT子句只能写一个参数;

下面的执行顺序:UPDATE子句→WHERE子句→ORDER BY子句→LIMIT子句→SET子句;


二:案例:不涉及表连接 的案例(这部分不难)

案例1: 把每个员工的编号和上司的编号+1,用ORDER BY子句完成;

这个例子很简单,不涉及多表查询;


​
    UPDATE t_emp SET empno=empno+1,mgr=mgr+1
    ORDER BY empno DESC;

……………………………………………………

案例2: 把月收入排在前三名的员工,底薪减100元,用LIMIT子句完成

注意,LIMIT子句的用法。

这个例子很简单,不涉及多表查询;

    UPDATE t_emp SET sal=sal-100
    ORDER BY sal+IFNULL(comm,0) DESC
    LIMIT 3;

……………………………………………………

案例3: 把10部门中,工龄超过20年的员工,底薪增加200元,WHERE子句

这个例子很简单,不涉及多表查询;

​ UPDATE t_emp SET sal=sal+200 WHERE deptno=10 AND FLOOR(DATEDIFF(NOW(),hiredate)/365)>=20;


三:案例:涉及表连接

案例4: 把ALLEN调往RESEARCH部门,职务调整为ANALYST;

这个案例中,涉及到了多张表,RESEARCH部门的编号不知道;

最直接的思路:使用子查询。

​ UPDATE t_emp e SET job=“ANALYST”,deptno=(SELECT d.deptno FROM t_dept d WHERE d.dname=“RESEARCH”) WHERE e.ename=“ALLEN”;

但是上面的做法中,子查询是相关子查询,如果需要修改的不止ALLEN一人,那么【SELECT d.deptno FROM t_dept d WHERE d.dname=“RESEARCH”】将会执行很多次。。。

涉及多张表的时候,需要引入表连接:

下面的两种表连接都是内连接的语法:内连接的,其中包括使用ON子句,和使用ON子句。

利用表连接的方式实现:这种骚操作。。。 (这儿非常重要!!!!!,是核心!!!)

​
    UPDATE t_emp e JOIN t_dept d
    SET e.deptno=d.deptno,e.job="ANALYST",d.loc="成都"
    WHERE e.ename="ALLEN" AND d.dname="RESEARCH";

分析:执行过程是,现将俩表做笛卡尔积(因为没有使用ON子句啦)从t_emp表中筛选出e.name=“ALLEN”这条记录,从t_dept表中筛选出d.dname=“RESEARCH”这条记录, 其实,这所谓的两条记录在【笛卡尔积】中是在一条记录上的; 此时,已经分别在两个表中各获得了一条记录,然后分别在获取的这两条记录上执行执行【SET e.deptno=d.deptno,e.job=“ANALYST”,d.loc=“成都”】。然后,对此条记录的操作就能影响到原表上。

这个表连接的例子其实并不难,很简单,多想一下表连接的那个结果集,,,,,

同时,这个例子说明,UPDATE语句可以同时修改多张表。。。

……………………………………………………

案例5: 把底薪低于公司平均底薪的员工,底薪增加150元;

【公司的平均底薪】和【谁的底薪低于公司的平均底薪】不知道;

我的解决方案:还是这种很骚的操作,,,

   UPDATE t_emp e1 JOIN (SELECT AVG(sal) aa FROM t_emp) e2
    SET e1.sal=e1.sal+150
    WHERE e1.sal<e2.aa;

注:这个例子和【案例4】结合后,可以发现,这种表连接的骚操作,可以应用于多条记录的情况。

即,重复下【案例4】中的话,这些在笛卡尔积上挑选出的记录,对这些记录的更改可以影响到原表上。

通过这个例子,更加说明,UPDATE子句是指执行一次的。

标准做法:和我的做法类似,只是这儿将条件放在了ON子句中,我的做法是将条件放在了WHERE子句中。

​ UPDATE t_emp e1 JOIN (SELECT AVG(sal) aa FROM t_emp) e2 ON e1.sal<e2.aa SET e1.sal=e1.sal+150;

……………………………………………………

UPDATE语句的表连接的第三种方式:外连接的语法,外连接的时候,条件只能写在ON子句中,, ,而且ON子句不能少!!!!!

案例6: 把没有部门的员工,或者SALES部门低于2000底薪的员工,都调往20部门。

涉及到多张表,需要表连接;张三没有部门,连接时需要保留,所以需要外连接;

第一种错误方案:

​ UPDATE t_emp e LEFT JOIN (SELECT deptno FROM t_dept WHERE dname=“SALES”) dd ON e.deptno=NULL OR (e.sal2000 AND e.deptno=dd.deptno) SET e.deptno=20;

可以发现,实际效果出错了如BLACK的部门也没改成20了。 首先,判断字段是不是空,需要IS NULL 而不是=NULL;

动动脑子:在左连接的时候,左边的记录都会被保留下来!!!!!!!!!!所以,这儿的结果是错误的,deptno全变成20了。。。

第二种错误方案: _ _ 错误原因,经过多次测试,发现左连接和右连接必须要有ON子句,否则会报错。这个需要后续确定,并在外连接的那篇博客中标记一下。__

​ UPDATE t_emp e LEFT JOIN (SELECT deptno FROM t_dept WHERE dname=“SALES”) dd SET e.deptno=20 WHERE e.deptno IS NULL OR (e.sal2000 AND e.deptno=dd.deptno);

标准做法:这个例子很典型,调理清晰,好好想想,,,

这儿,UPDATE确定数据源头(或者说,UPDATE子句确定“待操作数据集”),WHERE子句:对“待操作数据集”做二次筛选。

​ UPDATE t_emp e LEFT JOIN t_dept d ON e.deptno=d.deptno SET e.deptno=20 WHERE e.deptno IS NULL OR (d.dname=“SALES” AND e.sal<2000);

DELETE语句

注: (1)子查询不能在DELETE语句中使用的原因:首先,在DELETE中使用子查询,这会是相关子查询,效率很低;然后,MySQL不允许对要更改或要删除记录的数据表做子查询(很显然,动脑子想一想也明白了);


一:DELETE子句简介

DELETE语句是删除数据的,而不能删除数据表本身,删除数据表的是DROP语句,DELETE语句只是删除记录而已。

● DELETE子句:执行删除操作的子句;

● FROM子句:确定删除那张数据表;

● WHERE子句:按照条件去删除记录;如果没有条件,就会删除全表,清空表;

● ORDER BY子句:对结果集进行排序;

● LIMIT子句:限定删除内容;

执行顺序:FROM子句→WHERE子句→ORDER BY子句→LIMIT子句→DELETE子句;


二:DELETE案例:单表的案例:无连接

案例1: 删除10部门中,工龄超过20年的员工;

这个案例很简单,不涉及多张表。

我的做法:

​ DELETE FROM t_emp WHERE deptno=10 AND FLOOR(DATEDIFF(NOW(),hiredate)/365)>=20;

……………………………………………………

案例2: 删除20部门中工资最高的员工记录;

​ DELETE FROM t_emp WHERE deptno=20 ORDER BY sal DESC LIMIT 1;


三:DELETE案例:多张表的案例:内连接

(前面,UPDATE语句,表连接的时候可以修改多张表的记录。。。。DELETE也是这样的)

案例3 :删除SALES部门和该部门的全部员工记录

DELETE子句的作用是:指定要删除那些表的记录。

这儿使用内连接,因为删除的就是有部门的,没有部门的不删除的…

这种操作有点骚,先确定结果集中的记录,然后指定下删除哪些表,然后就能在原表中删除那些在结果集中被指定的记录了。

​ DELETE e,d FROM t_emp e JOIN t_dept d ON e.deptno=d.deptno WHERE d.dname=“SALES”;

……………………………………………………

案例4: 删除每个低于部门平均底薪的员工记录;

这个需要先查询,然后表连接

​ DELETE e FROM t_emp e JOIN (SELECT AVG(sal) aa,deptno dno FROM t_emp GROUP BY deptno) temp ON e.deptno=temp.dno WHERE e.sal<temp.aa;

……………………………………………………

案例5: 删除员工KING和他直接下属的员工记录。。

我的做法:

​ DELETE e1 FROM t_emp e1 JOIN (SELECT empno FROM t_emp WHERE ename=“KING”) temp WHERE e1.ename=“KING” OR e1.mgr=temp.empno;

标准做法:

​ DELETE e FROM t_emp e JOIN(SELECT empno FROM t_emp WHERE ename=“KING”) temp ON e.mgr=temp.empno OR e.empno=temp.empno;


四:DELETE案例:多张表的案例:外连接

案例6: 删除SALES部门的员工,以及没有部门的员工:

我的做法:

​ DELETE e FROM t_emp e left JOIN (SELECT deptno FROM t_dept WHERE dname=“SALES”) temp ON e.deptno=temp.deptno WHERE e.deptno IS NULL OR e.deptno=temp.deptno;

标准做法:看下自己的做法和标准做法的不同……

​ DELETE e FROM t_emp e LEFT JOIN t_dept d ON e.deptno=d.deptno WHERE d.dname=“SALES” OR e.deptno IS NULL;


五:快速删除数据表的全部记录:TRUNCATE语句


注:关于MySQL目前了解的内容: