Mysql数据的增删改查——Mysql初级(二)

 

前言:

不管你是一个开发工程师还是测试工程师,或是你是运维工程师,假如我们使用的是关系型数据库的话,可能最多使用到的可能就是数据库中的增删改查了(CRUD)。此文是本系列里面的第二篇文章,第一篇文章主要讲解的是:Mysql表结构的增删改查(CRUD)——Mysql初级(一),假如你也感兴趣的话,可以前往查阅,当然也可以提出你宝贵的意见和建议。此文主要致力于Mysql数据层面的增删改查。首先会先讲解MySQL CRUD语法,主要参考资料是Mysql的官方文档(中文版)。其次,会针对性的提供私人定制的基础案列,用以说明问题。然后会讲解在开发的过程中容易忽视的问题分享,以及关于CRUD的一些高级操作。最后总结关于CRUD的注意事项。这就是本文的行文思路,废话不多说,咱们直接上干货吧!


数据准备:

1、表结构建立:

-- 1、建立测试表
DROP TABLE IF EXISTS T_MYSQL_CRUD; -- 这种方式是删了重建
CREATE TABLE IF NOT EXISTS T_MYSQL_CRUD(
   id INT UNSIGNED AUTO_INCREMENT,
   title VARCHAR(100) NOT NULL,
   author VARCHAR(40) NOT NULL,
   date DATE,
   PRIMARY KEY (id )
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

2、数据插入:

-- 2、添加测试数据
INSERT INTO T_MYSQL_CRUD(title,author,date) VALUES('《C语言》','马云',NOW());
INSERT INTO T_MYSQL_CRUD(title,author,date) VALUES('《C#语言》','马化腾',NOW());
INSERT INTO T_MYSQL_CRUD(title,author,date) VALUES('《Java》','李彦宏',NOW());
INSERT INTO T_MYSQL_CRUD(title,author,date) VALUES('《Mysql》','刘强东',NOW());
INSERT INTO T_MYSQL_CRUD(title,author,date) VALUES('《演员的自我修养》','周星驰',NOW());
INSERT INTO T_MYSQL_CRUD(title,author,date) VALUES('《神雕侠侣》','金庸',NOW());
INSERT INTO T_MYSQL_CRUD(title,author,date) VALUES('《武林外传》','阿猫',NOW());
INSERT INTO T_MYSQL_CRUD(title,author,date) VALUES('《某海堡垒站》','阿狗',NOW());
INSERT INTO T_MYSQL_CRUD(title,author,date) VALUES('《Python基础》','粉红',NOW());
INSERT INTO T_MYSQL_CRUD(title,author,date) VALUES('《Django入门》','五毛',NOW());
INSERT INTO T_MYSQL_CRUD(title,author,date) VALUES('《JavaScrppt高级》','马克思',NOW());
INSERT INTO T_MYSQL_CRUD(title,author,date) VALUES('《Spring学习手册》','二哈',NOW());

3、数据概览

 

 一、数据插入(INSERT)

 1、语法分析:

Mysql数据插入的方式有多种,在不同的应用场景下,我们可能使用不同的插入方式,这样即可以最大限度的节省时间又可以提高程序的性能。以下是Mysql数据插入的语法概览,在接下来的时间会分别讲解,稍安勿躁。代码来源于Mysql官方文档。

INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
    [INTO] tbl_name
    [PARTITION (partition_name [, partition_name] ...)]
    [(col_name [, col_name] ...)]
    {VALUES | VALUE} (value_list) [, (value_list)] ...
    [ON DUPLICATE KEY UPDATE assignment_list]

INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
    [INTO] tbl_name
    [PARTITION (partition_name [, partition_name] ...)]
    SET assignment_list
    [ON DUPLICATE KEY UPDATE assignment_list]

INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
    [INTO] tbl_name
    [PARTITION (partition_name [, partition_name] ...)]
    [(col_name [, col_name] ...)]
    SELECT ...
    [ON DUPLICATE KEY UPDATE assignment_list]

value:
    {expr | DEFAULT}

value_list:
    value [, value] ...

assignment:
    col_name = value

assignment_list:
    assignment [, assignment] ...

使用INSERT ... VALUESINSERT ... SET 语句的形式插入基于明确指定的值的行。 使用INSERT ... SELECT形式插入从另一个或多个表中选择行(这就是常用的SELECT FOR INSERT)。 INSERT使用 ON DUPLICATE KEY UPDATE子句可以使现有行更新,如果要插入的行将导致UNIQUE索引中的重复或PRIMARY KEY冲突。 在MySQL 5.7中,DELAYED关键字被接受,但被服务器忽略。在后续的文章中回具体讨论。

1)、INSERT ... SELECT语法

INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
    [INTO] tbl_name
    [PARTITION (partition_name [, partition_name] ...)]
    [(col_name [, col_name] ...)]
    SELECT ...
    [ON DUPLICATE KEY UPDATE assignment_list]

value:
    {expr | DEFAULT}

assignment:
    col_name = value

assignment_list:
    assignment [, assignment] ...

使用INSERT ... SELECT,您可以根据SELECT 语句的结果快速地将多行插入到表中,该语句可以从一个或多个表中进行选择。例如:

INSERT INTO tbl_temp2 (fld_id)
  SELECT tbl_temp1.fld_order_id
  FROM tbl_temp1 WHERE tbl_temp1.fld_order_id > 100;

在使用INSERT ... SELECT语法时需要注意的点有:

a、 在使用IGNORE忽略会导致重复键违规的行。也就是说,在使用关键字IGNORE关键字的时候会忽略唯一键的行为。

 b、 该INSERT语句的目标表 可能出现在查询部分的FROM子句中 SELECT在从同一个表中选择并插入时,MySQL创建一个内部临时表来存放来自这些表的行SELECT,然后将这些行插入到目标表中。但是,不能使用 INSERT INTO t ... SELECT ... FROM t因为 tTEMPORARY 表,因为TEMPORARY表不能在同一语句中引用两次。

c、AUTO_INCREMENT 标明的列不受影响。

d、为确保二进制日志可用于重新创建原始表,MySQL不允许并发插入INSERT ... SELECT语句

e、为避免SELECTINSERT引用同一个表时引用不明确的列引用问题 , 请为该SELECT部分中使用的每个表提供唯一的别名,并使用适当的别名限定该 部分中的列名
     

案列演示: 

这里为了方便演示,需要再创建一张表,索性就命名未: T_MYSQL_CRUD_COPY.

DROP TABLE IF EXISTS T_MYSQL_CRUD_COPY; 
CREATE TABLE IF NOT EXISTS T_MYSQL_CRUD_COPY(
   id INT UNSIGNED AUTO_INCREMENT,
   title VARCHAR(100) NOT NULL,
   author VARCHAR(40) NOT NULL,
   date DATE,
   PRIMARY KEY (id )
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

使用INSERT ... SELECT进行数据插入:

INSERT INTO T_MYSQL_CRUD_COPY SELECT * FROM T_MYSQL_CRUD;

执行日志和结果。

针对以上的特殊情况感兴趣的朋友可以自行实验。

2)、INSERT ... ON DUPLICATE KEY UPDATE语法

如果指定ON DUPLICATE KEY UPDATE 要插入的行和标志位UNIQUE(唯一值)索引或者PRIMARY KEY(主键冲突),将会执行UPDATE操作。例如,如果列a声明为UNIQUE并且包含该值 1,则以下两个语句具有相似的效果:

-- 语句1
INSERT INTO t1 (a,b,c) VALUES (1,2,3)
  ON DUPLICATE KEY UPDATE c=c+1;

-- 语句2
UPDATE t1 SET c=c+1 WHERE a=1;

对于自动增量列的InnoDB 表,其效果是不相同的a对于自动增量列,INSERT 语句会增加自动增量值,但 UPDATE不会

如果列b也是唯一的, INSERT则相当于这个 UPDATE语句:

UPDATE t1 SET c=c+1 WHERE a=1 OR b=2 LIMIT 1;

如果a=1 OR b=2几个行相匹配,只有 一个行被更新。通常,您应该尽量避免ON DUPLICATE KEY UPDATE 在具有多个唯一索引的表上使用子句。如果一个表包含一AUTO_INCREMENT列并INSERT ... ON DUPLICATE KEY UPDATE插入或更新一行,该LAST_INSERT_ID()函数将返回该AUTO_INCREMENT值。该ON DUPLICATE KEY UPDATE子句可以包含多个列分配,用逗号分隔

ON DUPLICATE KEY UPDATE子句中的赋值表达式中,可以使用values(str) 函数来引用语句部分的 列值 。换句话说, 在子句中指的是将要插入的值,没有发生重复键冲突。这个函数在多行插入中特别有用。该 函数仅在子句或 语句中有意义,否则返回 。例: VALUES(col_name)INSERTINSERT ... ON DUPLICATE KEY UPDATEVALUES(col_name)ON DUPLICATE KEY UPDATEcol_nameVALUES()ON DUPLICATE KEY UPDATEINSERTNULL。

INSERT INTO t1 (a,b,c) VALUES (1,2,3),(4,5,6)
  ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);

以上语句和如下语句相同:

INSERT INTO t1 (a,b,c) VALUES (1,2,3)
  ON DUPLICATE KEY UPDATE c=3;
INSERT INTO t1 (a,b,c) VALUES (4,5,6)
  ON DUPLICATE KEY UPDATE c=9;

对于INSERT ... SELECT语句,这些规则适用于SELECT可以在ON DUPLICATE KEY UPDATE子句中引用的可接受形式的查询表达式:

引用来自单个表(可能是派生表)的查询的列。

引用多个表上联接的查询中的列。

引用DISTINCT 查询中的列。

引用其他表中的列,只要 SELECT不使用 GROUP BY一个副作用是您必须限定对非唯一列名称的引用
来自a的列的引用 UNION不能可靠地工作。要解决此限制,请将UNION其重写 为派生表,以便将其行视为单表结果集。例如,这个语句可能会产生不正确的结果:

INSERT INTO t1 (a, b)
  SELECT c, d FROM t2
  UNION
  SELECT e, f FROM t3
ON DUPLICATE KEY UPDATE b = b + c;

相反,使用重写UNION派生表的等效语句 :

INSERT INTO t1 (a, b)
SELECT * FROM
  (SELECT c, d FROM t2
   UNION
   SELECT e, f FROM t3) AS dt
ON DUPLICATE KEY UPDATE b = b + c;

将查询重写为派生表的技术还支​​持引用GROUP BY 查询中的列。

3)、INSERT DELAYED语法

INSERT DELAYED ...

该语句的DELAYED选项 INSERT是对标准SQL的MySQL扩展。在以前的MySQL版本中,它可以用于某些类型的表(例如 MyISAM),这样当客户端使用时 INSERT DELAYED,它可以立即从服务器获得一个好的行,并且当表不是被任何其他线程使用。

DELAYED插入和替换在MySQL 5.6中被弃用。在MySQL 5.7中, DELAYED不支持。服务器识别但忽略DELAYED关键字,将插入处理为非延迟插入,并生成 ER_WARN_LEGACY_SYNTAX_CONVERTED警告(“ 不再支持INSERT DELAYED。语句已转换为INSERT ”)。该DELAYED 关键字计划在未来版本中删除。

 

二、数据删除(DELETE)

DELETE 是从表中删除行的DML语句。

1)、单表删除语法

DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name
    [PARTITION (partition_name [, partition_name] ...)]
    [WHERE where_condition]
    [ORDER BY ...]
    [LIMIT row_count]

DELETE语句的主要功能是从表中删除行,并返回所删除的行数。假如需要检查已经删除的行数,可以调用Mysql的内置函数ROW_COUNT()

删除演示:

执行删除操作(删除id=13的数据):

-- 执行删除一行数据
DELETE FROM T_MYSQL_CRUD WHERE 1 = 1 AND ID=13;

ROW_COUNT()函数案例演示:

mysql> INSERT INTO t VALUES(1),(2),(3);
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> SELECT ROW_COUNT();
+-------------+
| ROW_COUNT() |
+-------------+
|           3 |
+-------------+
1 row in set (0.00 sec)

mysql> DELETE FROM t WHERE i IN(1,2);
Query OK, 2 rows affected (0.00 sec)

mysql> SELECT ROW_COUNT();
+-------------+
| ROW_COUNT() |
+-------------+
|           2 |
+-------------+
1 row in set (0.00 sec)

当你想要在IDE(比如Navicat)测试ROW_COUNT()的时候,需要将删除语句和查询语句共同执行才能明显的效果,否则执行SELECT ROW_COUNT()返回的可能就是-1;

DELETE FROM T_MYSQL_CRUD WHERE 1 = 1 AND ID=12;
SELECT ROW_COUNT();

如果DELETE语句中带WHERE语句的话就是属于条件删除,仅删除待条件的行。如果不带WHERE的话就会删除所有的行(PS:在生产环境使用DELETE的时候千万要谨慎,不然就只能跑路了)。where_condition是一个表达式,每一行被删除的结果都是true。

如果ORDER BY指定了子句,则按照指定的顺序删除行。该 LIMIT子句限制了可以删除的行数。这些条款适用于单表删除,但不适用于多表删除

2)、多表删除语法

 

DELETE [LOW_PRIORITY] [QUICK] [IGNORE]
    tbl_name[.*] [, tbl_name[.*]] ...
    FROM table_references
    [WHERE where_condition]

DELETE [LOW_PRIORITY] [QUICK] [IGNORE]
    FROM tbl_name[.*] [, tbl_name[.*]] ...
    USING table_references
    [WHERE where_condition]

(1)、TRUNCATE TABLE

当您不需要知道已删除行的数量时,可以使用TRUNCATE TABLE语句执行表清空操作。和DELETE语句相比,TRUNCATE TABLE删除数据的速度更快,只是该语句是不可以条件删除的。相对于DELETE语句比较,TRUNCATE TABLE是事务不安全的。因此,当存在事务控制的时候只能使用DELETE语句去执行删除,而不能使用TRUNCATE TABLE。

 

DELETE支持使用该PARTITION选项的显式分区选择,该选项采用从中选择要删除的行的一个或多个分区或子分区(或两者)的逗号分隔名称的列表。未包括在列表中的分区将被忽略。给定一个t带有分区名称的分区表p0,执行该语句与 执行该表时DELETE FROM t PARTITION (p0)具有相同的效果ALTER TABLE t TRUNCATE PARTITION (p0); 在这两种情况下,分区p0中的所有行都被删除。

PARTITION可以与WHERE条件一起使用 ,在这种情况下,条件仅在列出的分区中的行上进行测试。例如, DELETE FROM t PARTITION (p0) WHERE c < 5 仅从p0条件c < 5为true的分区中删除行; 任何其他分区中的行不会被检查,因此不会受到影响 DELETE

PARTITION选项也可以用在多表DELETE语句中。在选项中,每个表格最多可以使用一个这样的 FROM选项。

(2)、删除顺序

如果DELETE语句包含一个 ORDER BY子句,则按照子句指定的顺序删除行。这主要是有用的LIMIT。例如,以下语句查找与该WHERE子句匹配的行,对它们进行排序timestamp_column,并删除第一个(最早的)一个:

DELETE FROM somelog WHERE user = 'jcole'
ORDER BY timestamp_column LIMIT 1;

ORDER BY 也有助于按照所需的顺序删除行,以避免引用完整性违规。

(3)、多表删除

您可以在DELETE语句中指定多个表,以 根据WHERE子句中的条件从一个或多个表中删除行 。你不能使用ORDER BYLIMIT在一个多表 DELETE中

对于第一个多表语法,只删除FROM子句前列出的表中的匹配行。对于第二个多表语法,只删除FROM子句(子句之前USING)中列出的表中的匹配行。

DELETE t1, t2 FROM t1 INNER JOIN t2 INNER JOIN t3
WHERE t1.id=t2.id AND t2.id=t3.id;

要么

DELETE FROM t1, t2 USING t1 INNER JOIN t2 INNER JOIN t3
WHERE t1.id=t2.id AND t2.id=t3.id;

三、数据更新(UPDATE)

如果我们需要修改或更新 MySQL 中的数据,我们可以使用 SQL UPDATE 命令来操作。以下是 UPDATE 命令修改 MySQL 数据表数据的通用 SQL 语法:

UPDATE table_name SET field1=new-value1, field2=new-value2
[WHERE Clause]
  • 你可以同时更新一个或多个字段。
  • 你可以在 WHERE 子句中指定任何条件。
  • 你可以在一个单独表中同时更新数据。

 

四、数据更新(SELECT)

 1)、SELECT语法 

SELECT
    [ALL | DISTINCT | DISTINCTROW ]
      [HIGH_PRIORITY]
      [STRAIGHT_JOIN]
      [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
      [SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]
    select_expr [, select_expr ...]
    [FROM table_references
      [PARTITION partition_list]
    [WHERE where_condition]
    [GROUP BY {col_name | expr | position}
      [ASC | DESC], ... [WITH ROLLUP]]
    [HAVING where_condition]
    [ORDER BY {col_name | expr | position}
      [ASC | DESC], ...]
    [LIMIT {[offset,] row_count | row_count OFFSET offset}]
    [PROCEDURE procedure_name(argument_list)]
    [INTO OUTFILE 'file_name'
        [CHARACTER SET charset_name]
        export_options
      | INTO DUMPFILE 'file_name'
      | INTO var_name [, var_name]]
    [FOR UPDATE | LOCK IN SHARE MODE]]

SELECT用于检索从一个或多个表中选择的行,并可以包含 UNION语句和子查询。最常用的 SELECT语句是这些:

每个select_expr表示您想要检索的列。必须至少有一个 select_expr

table_references指示从中检索行的表格。

WHERE条件如果给出,则表示行必须满足选择的条件。 where_condition是一个表达式,对于每个要被选择的行,计算结果为true。如果没有WHERE子句,则语句选择所有行 。

WHERE表达式中,除了汇总(汇总)函数,您可以使用MySQL支持的任何函数和运算符。SELECT 也可以用来检索不参考任何表而计算出的行。

mysql> SELECT 1 + 1;
        -> 2

DUAL在没有引用表的情况下, 您可以指定为虚拟表名称:

mysql> SELECT 1 + 1 FROM DUAL;
        -> 2

通常,使用的子句必须按照语法描述中显示的顺序给出。例如,一个 HAVING条款必须在任何 GROUP BY条款之后,在任何ORDER BY条款之前。例外情况是,该 INTO子句可以显示在语法描述中,也可以紧跟在 select_expr列表之后。

2)、SELECT中可以使用的条件运算符

where-clause:布尔条件表达式
= # 等值比较
<=> # 等值比较,包括与NULL的安全比较
<>或!= # 不等值比较
<,<=,>,>= # 其它比较符
IS NULL # 是否为空值
IS NOT NULL # 是否不为空值
LIKE # 支持的通配符有%和_
RLIKE或REGEXP # 正则表达式匹配
IN # 判指定字段的值是否在给定的列表中
BETWEEN … AND …  # 在某取值范围内

3)、组合查询条件

NOT,!  # 非
AND,&& # 和
OR,|| # 或

4)、聚合函数查询

SUM() # 求总和
AVG() # 求平均值
MAX() # 求最大值
MIN() # 求最小值
COUNT() # 求记录总数
#注:count(*)效率最低,可指定某一字段求总数,如count(Name)

5)、各字句类型

where # 条件过滤
group by # 对查询结果分组
having # 对group by的结果进行条件过滤
order by # 排序
limit # 限制输出行数,如”limit 2“表示只显示前2行,“limit 2,3”表示偏移前2行,显示3-5行
distinct # 指定的结果相同的只显示一次
sql_cache # 缓存于查询缓存中
sql_no_cache # 不缓存查询结果

五、总结

以上就是本文的主要内容了,更多的是理论知识铺垫。由于都是简单的CRUD操作,因此就不用太多的案例来解释了。

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值