mysql之DML语句

DML语句

1、dml语句
什么是dml语句:DML:DATA MANIPULATION LANGUAGE(数据操纵语言),由INSERT、UPDATE、DELETE等语句构成,用来修改表中的数据。(数据操纵语言,可以更改表中的数据)
2、插入行到表中
insert
INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name
[PARTITION (partition_name,…)]
[(col_name,…)]
{VALUES | VALUE} ({expr | DEFAULT},…),(…),…
[ ON DUPLICATE KEY UPDATE
col_name=expr
[, col_name=expr] … ]

在mysql中into是可选的,其他数据库不是,是必选的
为了和其他数据库形成统一的sql书写习惯,into必须写在sql语句中,使用values而不是value。
Insert语句作用:向表中插入数据
插入的数据形式:
1.显式插入(字面量形式插入)
2.隐式插入(可以用表达式,函数等)
案例:
CREATE TABLE t5(sys_date DATETIME);
显式插入:INSERT INTO t5 VALUES(‘2019-03-23 9:10:00’);
隐式插入:INSERT INTO t5 VALUES(NOW());

Insert语句的不同插入形式:
1、表名后面跟着列名,所有的列名用小括号括起来,列名与列名之间用逗号分隔
Insert into t4(id,name) values(555,‘aaa’);
2、表名后面不跟列名(整行插入,每一列都要进行赋值)
注意:该形式插入数据时,要了解表的列数及列的数据类型
Insert into t4 values(666,‘yuo’);
假如说插入的列数是表中列的一部分,未列出的列自动为null值。
当对某一列不想赋值时,可以使用null进行占位,防止因为插入数据个数与表中列数不匹配报错。
mysql> insert into t2 values(123,NULL);

Values的数据来源:
1、字面量
2、可以是函数
3、可以是子查询(子查询要用小括号括起来)
注意:insert语句的子查询可以是表自身。

1、insert通常只插入一条数据使用(常用)
2、Insert可以一次插入多行数据(很少用)

当其中一行数据出错,所有的插入都不执行
Insert语句提供ignore(不报错)选项,但是不建议使用。为了排错,定位问题点。

可以使用insert复制某张表的数据到另一张表中
Insert into t2 select * from t1;
案例:
1、在表名后面列出所有的列名
例1: 插入一个新的球队到teams表中
INSERT INTO teams(teamno,playerno,division)
VALUES(3,6,‘third’);
2、在表名后面省略所有的列名
这种写法要求VALUES子句中的值必须按照列在表结构中的顺序来一一赋值
INSERT INTO teams
VALUES(4,104,‘third’);
3、在表名后面只列出部分的列名
所有没有明确赋值的列,将通过隐式赋值自动得到null值
例2: 添加一个新球员
INSERT INTO players(playerno,NAME,initials,sex,joined,street,town)
VALUES(611,‘Jones’,‘GG’,‘M’,1997,‘Green Way’,‘Stratford’);
使用字面量NULL给列赋空值
INSERT INTO players(playerno,NAME,initials,birth_date,sex,joined,street,houseno,postcode,town,phoneno,leagueno)
VALUES(613,‘Tom’,‘CC’,NULL,‘M’,1977,‘Green Way’,NULL,NULL,‘Stratford’,NULL,NULL);
VALUES子句中除了字面量,还可以使用函数、计算、标量子查询等
例4: 创建一个表,存储球员数量和罚款总额
CREATE TABLE totals(
numberplayers INTEGER NOT NULL,
sumpenalties DECIMAL(9,2) NOT NULL
);

INSERT INTO totals(numberplayers,sumpenalties)
VALUES((SELECT count(*) FROM players),
(SELECT sum(amount) FROM penalties));
注意:子查询必须放在单独的小括号中

一条INSERT语句可以插入多个行:
例5:添加4个新的球队
INSERT INTO teams(teamno,playerno,division)
VALUES (6,7,‘third’),
(7,27,‘fourth’),
(8,39,‘fourth’),
(9,112,‘sixth’);
注意:这种语法只要有1行出错,则插入全部取消
INSERT语句中可以使用IGNORE选项来当INSERT语句出错时,不显示错误消息。INSERT语句不会执行,不建议使用

例6:向teams表中再次添加1号球队
INSERT IGNORE INTO teams VALUES(1,39,‘second’);

带子查询的INSERT语句
INSERT [INTO] tbl_name[(col_name,…)]
SELECT …
语法:如果在表名后面列出了列名,那么列的数量和数据类型必须和子查询的select列表相匹配

例7: 创建表recr_players,保存非参赛球员的编号、名字、城市和电话号码
CREATE TABLE recr_players(
playerno SMALLINT NOT NULL,
name char(15) NOT NULL,
town char(10) NOT NULL,
phoneno char(13) ,
PRIMARY KEY(playerno)
);
注意:duplicates主键冲突
将联盟会员号为空的球员插入到recr_players表中
INSERT INTO recr_players
SELECT playerno, NAME, town, phoneno
FROM players
WHERE leagueno IS NULL;
共 4 行受到影响

也可以把本表中的行再次添加到本表中。注意主键值不要重复

例8: 把那些罚款额大于平均罚款额的所有罚款添加到penalties表中
INSERT INTO penalties
SELECT paymentno + 100,playerno,payment_date,amount
FROM penalties
WHERE amount > (SELECT avg(amount)
FROM penalties);
共 4 行受到影响

Replace
作用:替代已有的行
Insert 的变种语句,使用replace语句时,表上一定要有主键

有两种情况:
1.要插入的主键值存在,则覆盖
2.要插入的主键值不存在,则插入(与insert相同操作)
语法:
REPLACE [LOW_PRIORITY | DELAYED]
[INTO] tbl_name
[PARTITION (partition_name,…)]
[(col_name,…)]
{VALUES | VALUE} ({expr | DEFAULT},…),(…),…
Or:
REPLACE [LOW_PRIORITY | DELAYED]
[INTO] tbl_name
[PARTITION (partition_name,…)]
SET col_name={expr | DEFAULT}, …
Or:
REPLACE [LOW_PRIORITY | DELAYED]
[INTO] tbl_name
[PARTITION (partition_name,…)]
[(col_name,…)]
SELECT …

案例:
例1: 添加一个新的球员。如果主键值已经存在,则覆盖该行
REPLACE INTO players(playerno,NAME,initials,
sex,joined,street,town)
VALUES(611,‘john’,‘GG’,‘M’,1977,‘Green Way’, ‘Startford’);
共 1 行受到影响

3、删除表中的数据
delete
作用:删除满足条件的数据,整行删除
语法:
DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name
[PARTITION (partition_name,…)]
[WHERE where_condition]
[ORDER BY …]
[LIMIT row_count]

From:要删除的表-------数据源
Where:删除哪些行-----过滤列(注意:写delete语句时一定要带where条件)
Order by :删除顺序
Limit:限制删除的行数

Where条件:
1.可以是子查询
2.可以是表达式、函数
注意:子查询不可以来自于要删除数据的表

同时从多表删除行:
Multiple-Table Syntax
DELETE [LOW_PRIORITY] [QUICK] [IGNORE]
tbl_name[.] [, tbl_name[.]] …
FROM table_references
[WHERE where_condition]
Or:
DELETE [LOW_PRIORITY] [QUICK] [IGNORE]
FROM tbl_name[.] [, tbl_name[.]] …
USING table_references
[WHERE where_condition]

案例:
Delete t1,t2 from t1,t2 where t1.id=t2.id and t1.id=3;

案例:
例 1: 删除44号球员的罚款
DELETE FROM penalties
WHERE playerno=44;
共 3 行受到影响

带子查询
例2: 删除球员,条件是他们加入俱乐部的年份晚于来自于Stratford的球员加入俱乐部的平均年份
CREATE TABLE players_copy2
AS SELECT * FROM players;
DELETE FROM players_copy1
WHERE joined > (
SELECT avg(joined)
FROM players_copy2
WHERE town = ‘Stratford’);
注意,在WHERE子句的子查询中,不允许访问要删除行的表

DELETE FROM players_copy1
WHERE joined > (
SELECT avg(joined)
FROM players_copy1
WHERE town = ‘Stratford’);
错误代码: 1093
You can’t specify target table ‘players_copy1’ for update in FROM clause
用在DELETE语句中的ORDER BY子句和LIMIT子句的含义和用在UPDATE语句中是类似的

例3: 删除4个最高的罚款
DELETE FROM penalties
ORDER BY amount DESC,playerno ASC
LIMIT 4;
共 4 行受到影响

从多个表中删除行
语法:
DELETE [IGNORE] tbl_name[.] [, tbl_name[.]] …
FROM table_references
[WHERE where_condition]
如果FROM中的表有别名,在DELETE子句中只能使用表别名

例4: 从teams和matches表中删除所有3号球队的行
DELETE teams, matches
FROM teams, matches
WHERE teams.teamno = matches.teamno
AND teams.teamno=3;
两个表中满足连接条件teams.teamno = matches.teamno和过滤条件teams.teamno=3的所有行被删除

truncate
快速清空一张表

原理:将表行尾的指针直接指向0,这样mysql认为该表数据已经清空,真实数据未清空,mysql后台程序会自动清理该表的数据
语法:mysql> help truncate table;
Syntax:
TRUNCATE [TABLE] tbl_name

案例:truncate table t1;
mysql> truncate table t1;
Query OK, 0 rows affected (0.01 sec)
mysql> truncate t1;
Query OK, 0 rows affected (0.02 sec)

4、更新表中的数据
Update语句:
作用:根据条件更新表中的数据
语法:
UPDATE [LOW_PRIORITY] [IGNORE] table_reference
SET col_name1={expr1|DEFAULT} [, col_name2={expr2|DEFAULT}] …
[WHERE where_condition]
[ORDER BY …]
[LIMIT row_count]

Set:要修改的值
Where:过滤条件,哪些数据应该被修改
Order by:排序操作,更改更新表数据的排序
Limit:显示修改的行数
有where条件:修改的满足条件的数据
无where条件:修改整张表的数据(危险操作,以后写update条件要注意)

Set字句:
1、字面量
2、表达式
3、使用函数
4、使用子查询
Update t6 set id=(select sum(id) from t1) where name=‘a’;
注意:set语句子查询不可以是要修改的表本身

Order by:排序操作,更改更新表数据的顺序
修改主键列时会用到,避免主键冲突,先修改主键值大的,再修改小的(很少用)
很少使用,除非涉及到修改主键,修改特定顺序的行
Limit字句:
很少使用
Update也提供ignore(不报错)选项,但是不建议使用。为了排错,定位问题点。

Update可以更改多个表中的数据:
UPDATE [LOW_PRIORITY] [IGNORE] table_reference
SET col_name1={expr1|DEFAULT} [, col_name2={expr2|DEFAULT}] …
[WHERE where_condition]
[ORDER BY …]
[LIMIT row_count]

table_reference:可以使用任何合法的语法,但是不能使用order by和limit字句

同时修改多个表内部数据原理:
1、先根据关联条件形成多表关联,找出多个表相关联的列
2、根据过滤条件筛选出要修改的行
3、同时修改要修改多个表的数据(上两步可以认为形成了一张表的数据)

1.主键order by的操作
Update t1 set id=id+1 order by id desc;
2.同时更新两个表的数据
Update t1 ,t2 set t1.name=‘china’,t2.name=’china’ where t1.id=t2.id and t1.id=2;

案例:
例1: 把95号球员的联盟会员号码改为2000
UPDATE players
SET leagueno = 2000
WHERE playerno = 95;
共 1 行受到影响
例2: 把所有的罚款增加5%
UPDATE penalties
SET amount = amount*1.05;
共 8 行受到影响
例3: 把住在Stratford的球员的获胜局数设为0
UPDATE matches
SET won = 0
WHERE playerno IN(SELECT playerno
FROM players
WHERE town=‘Stratford’);
共 4 行受到影响

例4: 创建表players_data保存每个球员的编号、所参加比赛的次数,和所引起的罚款总数
CREATE TABLE players_data(
playerno INTEGER NOT NULL PRIMARY KEY,
number_mat INTEGER,
sum_penalties DECIMAL(7,2)
);

INSERT INTO players_data(playerno)
SELECT playerno FROM players;
共 12 行受到影响

UPDATE players_data pd
SET number_mat = (
SELECT count(*)
FROM matches m
WHERE m.playerno = pd.playerno),
sum_penalties = (
SELECT sum(amount)
FROM penalties pen
WHERE pen.playerno = pd.playerno);

注意,在SET子句的子查询中,不允许访问要更新的表

例5: 在每笔罚款中减去平均罚款额。以下写法不允许
UPDATE penalties
SET amount = amount - (SELECT avg(amount)
FROM penalties);
错误代码: 1064
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘– (select avg(amount) From penalties)’ at line 2
应该分两步来做:
SET @avg_amount := (SELECT avg(amount) FROM penalties);

UPDATE penalties
SET amount = amount - @avg_amount;
共 8 行受到影响

UPDATE语句中可以使用ORDER BY子句,要求以排序的顺序来依次更新行。这在某些场景可能有用。例如,如果想要把所有罚款的罚款编号都加1,如果从罚款编号为1的行开始更新,要么就会发生主键值重复异常。如果从罚款编号最大的行开始更新,就没有问题。

例6:把所有罚款的编号增加1
UPDATE penalties
SET paymentno = paymentno + 1
ORDER BY paymentno DESC;
共 8 行受到影响

UPDATE语句中可以使用LIMIT子句,指定一次更新的行数

例7:把4个最高的罚款额增加5%(罚款额相同则更新编号小的球员)
UPDATE penalties
SET amount= amount *1.05
ORDER BY amount DESC, playerno ASC
LIMIT 4;
IGNORE选项用于当UPDATE语句出错时,不显示错误消息

更新多个表中的值
MySQL允许我们使用1条UPDATE语句就更新两个或多个表中的行
语法:
UPDATE [IGNORE] table_references
SET col_name1=expr1 [, col_name2=expr2,],…
[WHERE where_condition]

其中, table_references可以使用任何合法的连接语法。不能使用ORDER BY和LIMIT子句

例8:把一个first分级球队的所有比赛的获胜局数设为0,并把first分级球队的队长编号改为112
UPDATE matches m,teams t
SET m.won = 0,
t.playerno = 112
WHERE t.teamno = m.teamno
AND t.division = ‘first’;
共 6 行受到影响

MySQL首先执行一个二表连接查询,从两个表中找到满足连接条件 t.teamno = m.teamno 的所有行,然后对这些行分别进行更新

使用一条语句更新多个表的优点是:要么两个表都更新,要么两个表都不更新

你可能感兴趣的:(MySQL,mysql数据库,数据库,mysql之DML)