当前位置: 首页 > news >正文

MySQL十部曲之六:数据操作语句(DML)

文章目录

  • 前言
  • 语法约定
  • DELETE
  • INSERT
  • SELECT
    • 查询列表
    • SELECT 选项
    • 子句
      • FROM
      • WHERE
      • ORDER BY
      • GROUP BY
      • HAVING
      • WINDOW
      • LIMIT
      • FOR
    • SELECT ... INTO
    • 连接查询
      • CROSS JOIN和INNER JOIN
      • ON和USING
      • OUTER JOIN
      • NATURE JOIN
    • 子查询
      • 标量子查询
      • 使用子查询进行比较
      • 带有ANY、IN或SOME的子查询
      • 带有ALL的子查询
      • 行子查询
      • 带有EXISTS或NOT EXISTS的子查询
      • 关联子查询
      • 派生表
      • 横向派生表
      • 子查询的限制
    • 集操作(UNION、INTERSECT和EXCEPT)
  • UPDATE

前言

本文翻译自官方文档。

语法约定

方括号[]表示可选词或语句,例如,在下面的语句中,IF EXISTS是可选的:

DROP DTABLE [IF EXISTS] tab1_name

当一个语法元素由多个备选项组成时,这些备选项由竖条|分隔。当可以从一组选项中选择一个成员时,备选项列在方括号内:

TRIM([[BOTH | LEADING | TRAILING] [remstr] FROM] str)

当必须从一组选项中选择一个成员时,备选项在大括号{}中列出:

{DESCRIBE | DESC} tbl_name [col_name | wild]

省略号表示省略语句的某一部分,通常是为了提供更复杂语法的更短版本。例如,SELECT…INTO OUTFILESELECT语句形式的简写。省略号还可以表示语句的前一个语法元素可以重复。在下面的示例中,可以给出多个reset_option值,每个值在第一个值之后以逗号开头:

RESET reset_option [,reset_option] ...

DELETE

DELETE是一条DML语句,用于从表中删除行,并返回删除的行数。

DELETE FROM tbl_name [[AS] tbl_alias][WHERE where_condition][ORDER BY ...][LIMIT row_count]
  • WHERE:可选WHERE子句中的条件确定要删除哪些行。如果没有WHERE子句,则删除所有行。
  • ORDER BY:如果指定了ORDER BY子句,则按指定的顺序删除行。
  • LIMIT:LIMIT子句对可以删除的行数设置了限制。

DELETE语句注意事项如下:

  • 不能在子查询中从表中删除并从同一表中进行选择。
  • 如果删除包含AUTO_INCREMENT列最大值的行,则该值不会在MyISAM或InnoDB表中重用。
  • 如果在autocommit模式下使用DELETE FROM tbl_name删除表中的所有行,则除InnoDB和MyISAM外的所有存储引擎都将重新开始该顺序。

INSERT

INSERT语句将新行插入到现有表中。

INSERT [INTO] tbl_name{ VALUES (value_list) [, (value_list)] ... }INSERT [INTO] tbl_nameSET assignment_listINSERT [INTO] tbl_name{ SELECT ... | TABLE table_name | VALUES row_constructor_list}value:{expr | DEFAULT}value_list:value [, value] ...row_constructor_list:ROW(value_list)[, ROW(value_list)][, ...]assignment:col_name = value| [tbl_name.]col_nameassignment_list:assignment [, assignment] ...

插入行的列和值可以通过以下规则对应:

  • tbl_name后面提供用括号括起来的以逗号分隔的列名列表。在这种情况下,每个指定列的值必须被提供。
  • 如果没有指定列名列表,所有列的值都必须按顺序被提供。
  • SET子句通过名称显式地指示列,以及为每个列分配的值。

列值可以通过几种方式给出:

  • 如果未启用严格SQL模式,则未显式给定值的任何列都将被设置为其默认值。如果启用严格SQL模式,如果INSERT语句没有为没有默认值的每个列指定显式值,则会生成错误。
  • 如果列名列表和值列表都是空的,INSERT将创建一行,每一列都设置为默认值:
INSERT INTO tbl_name () VALUES();
  • 使用关键字DEFAULT显式地将列设置为默认值。在表达式中,您可以使用DEFAULT(col_name)为列col_name生成默认值。
  • 如果表达式expr数据类型与列数据类型不匹配,MySQL将根据列类型进行类型转换。
  • 表达式expr可以引用先前在值列表中设置的任何列。例如,你可以这样做,因为col2的值引用了col1,它之前已经被赋值:
INSERT INTO tbl_name (col1,col2) VALUES(15,col1*2);
  • 引用包含AUTO_INCREMENT值的列会出现异常。因为AUTO_INCREMENT值是在其他值赋值之后生成的,所以对赋值中的AUTO_INCREMENT列的任何引用都会返回0。

插入语句会有以下返回值:

Records: N1 Duplicates: N2 Warnings: N3
  • Records:表示语句处理的行数。(这不一定是实际插入的行数)
  • Duplicate:表示无法插入的行数,因为它们会重复某些现有的唯一索引值。
  • Warnings:表示以某种方式出现问题的插入列值的尝试次数。

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

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

从MySQL 8.0.19开始,你可以用TABLE语句代替SELECT语句,如下所示:

INSERT INTO ta TABLE tb;

TABLE tb相当于SELECT * FROM tb。当将源表中的所有列插入目标表时,它非常有用,并且不需要使用WHERE进行过滤。此外,可以使用ORDER BY对来自TABLE的行按一个或多个列排序,并且可以使用LIMIT子句限制插入的行数。

SELECT

SELECT用于从一个或多个表中选择的行。

SELECT[ALL | DISTINCT]select_expr [, select_expr] ...[into_option][FROM table_references[WHERE where_condition][GROUP BY {col_name | expr}, ... [WITH ROLLUP]][HAVING where_condition][WINDOW window_name AS (window_spec) [, window_name AS (window_spec)] ...][ORDER BY {col_name | expr} [ASC | DESC], ... [WITH ROLLUP]][LIMIT {[offset,] row_count | row_count}][into_option][FOR {UPDATE | SHARE}[OF tbl_name [, tbl_name] ...][NOWAIT | SKIP LOCKED]][into_option]into_option: {INTO OUTFILE 'file_name'[CHARACTER SET charset_name]export_options| INTO DUMPFILE 'file_name'| INTO var_name [, var_name] ...
}

SELECT还可以用于检索不引用任何表而计算出来的行。

mysql> SELECT 1 + 1;-> 2

在不引用表的情况下,允许指定DUAL作为虚拟表名。DUAL纯粹是为了方便那些要求所有SELECT语句都应该有FROM和其他可能的子句的人:

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

查询列表

select_expr子句包含一个查询列表,该列表指示要检索哪些列。该子句可以指定一个列或表达式,或者可以使用*简写:

  • 只包含一个不限定的*的查询列表可以用来从所有表中选择所有列:
  • tbl_name.*可以作为限定的简写来选择指定表中的所有列。
  • 如果一个表有不可见的列,*tbl_name.*将不会包含它们。

可以使用alias_nameselect_expr指定别名。别名用作表达式的列名,可以在GROUP BYORDER BYHAVING子句中使用。例如:

SELECT CONCAT(last_name,', ',first_name) AS full_nameFROM mytable ORDER BY full_name;

SELECT 选项

ALLDISTINCT修饰符指定是否应该返回重复的行。ALL(默认值)指定应该返回所有匹配的行,包括重复的行。DISTINCT指定从结果集中删除重复行。同时指定两个修饰符是错误的。

STRAIGHT_JOIN强制优化器按照表在FROM子句中列出的顺序连接表。如果优化器以非最优顺序连接表,则可以使用它来加快查询速度。

子句

一般来说,所使用的子句必须完全按照语法描述中显示的顺序排列。

FROM

FROM table_references子句指示要从中检索行的表。如果指定了多个表,则执行连接查询。对于指定的每个表,您可以选择指定一个别名。

tbl_name [[AS] alias] [index_hint]

index_hint提供了有关如何在查询处理期间选择索引的信息。

可以将默认数据库中的表引用为tbl_namedb_name.tbl_name显式指定数据库。可以将列引用为col_nametbl_name.col_namedb_name.tbl_name.col_name。通常不需要这么做,除非该引用具有二义性。

WHERE

如果给定WHERE子句,则指示行必须满足的一个或多个条件才能被选中。where_condition是一个表达式,对于要选择的每一行,其计算结果为true。如果没有WHERE子句,语句将选择所有行。在WHERE表达式中,您可以使用MySQL支持的任何函数和操作符,除了聚合函数。

ORDER BY

ORDER BY用于排序要输出的列,可以在ORDER BY子句中使用列名和列别名:

SELECT college, region, seed FROM tournamentORDER BY region, seed;SELECT college, region AS r, seed AS s FROM tournamentORDER BY r, s;

ORDER BY默认为升序,这可以使用ASC关键字显式指定。要按反向顺序排序,请将DESC关键字添加到要排序的ORDER BY子句中的列名的后边。

当您使用ORDER BYSELECT中的列进行排序时,服务器仅使用max_sort_length系统变量指示的初始字节数对值进行排序。

GROUP BY

GROUP BY子句用于将查询结果分组,SQL-92及更早版本的查询不允许在查询列表、HAVINGORDER BY内引用未在GROUP BY子句中使用的非聚合列。SQL:1999及以后版本在特定情况下允许使用非聚合列。

MySQL实现了功能依赖检测。如果启用了ONLY_FULL_GROUP_BY SQL模式(默认),MySQL会遵循SQL-92标准。

当启用了SQL的ONLY_FULL_GROUP_BY模式时,MySQL也允许没有在GROUP BY子句中命名的非聚合列,只要该列被限制为单个值,如下例所示:

mysql> CREATE TABLE mytable (->    id INT UNSIGNED NOT NULL PRIMARY KEY,->    a VARCHAR(10),->    b INT-> );mysql> INSERT INTO mytable-> VALUES (1, 'abc', 1000),->        (2, 'abc', 2000),->        (3, 'def', 4000);mysql> SET SESSION sql_mode = sys.list_add(@@session.sql_mode, 'ONLY_FULL_GROUP_BY');mysql> SELECT a, SUM(b) FROM mytable WHERE a = 'abc';
+------+--------+
| a    | SUM(b) |
+------+--------+
| abc  |   3000 |
+------+--------+

当使用ONLY_FULL_GROUP_BY时,也可能在SELECT列表中有多个非聚合列。在这种情况下,每个这样的列必须在WHERE子句中被限制为单个值,并且所有这样的限制条件必须通过逻辑与连接,如下所示:

mysql> DROP TABLE IF EXISTS mytable;mysql> CREATE TABLE mytable (->    id INT UNSIGNED NOT NULL PRIMARY KEY,->    a VARCHAR(10),->    b VARCHAR(10),->    c INT-> );mysql> INSERT INTO mytable-> VALUES (1, 'abc', 'qrs', 1000),->        (2, 'abc', 'tuv', 2000),->        (3, 'def', 'qrs', 4000),->        (4, 'def', 'tuv', 8000),->        (5, 'abc', 'qrs', 16000),->        (6, 'def', 'tuv', 32000);mysql> SELECT @@session.sql_mode;
+---------------------------------------------------------------+
| @@session.sql_mode                                            |
+---------------------------------------------------------------+
| ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION |
+---------------------------------------------------------------+mysql> SELECT a, b, SUM(c) FROM mytable->     WHERE a = 'abc' AND b = 'qrs';
+------+------+--------+
| a    | b    | SUM(c) |
+------+------+--------+
| abc  | qrs  |  17000 |
+------+------+--------+

如果禁用了ONLY_FULL_GROUP_BY,MySQL不在遵循SQL-92标准。在这种情况下,服务器可以从每个组中自由选择任何值,所以除非它们相同,否则所选择的值是不确定的,这可能不是你想要的。

HAVING

HAVING子句和WHERE子句一样,指定了选择条件。WHERE子句为查询列表中的列指定条件,但不能引用聚合函数。HAVING子句指定组的条件,组通常由GROUP BY子句指定。查询结果只包含满足HAVING条件的组。如果没有GROUP BY,所有行隐式地形成一个组。

SQL标准要求HAVING必须只引用GROUP BY子句中的列或聚合函数中使用的列。然而,MySQL支持对这种行为的扩展,并允许HAVING引用SELECT列表中的列和外部子查询中的列。

WINDOW

WINDOW子句定义了可由窗口函数引用的命名窗口。

LIMIT

LIMIT子句可用于约束SELECT语句返回的行数。LIMIT接受一个或两个数字参数,它们必须都是非负整数常量,但有以下例外:

使用两个参数,第一个参数指定要返回的第一行的偏移量,第二个参数指定要返回的最大行数。初始行的偏移量为0:

SELECT * FROM tbl LIMIT 5,10;  # Retrieve rows 6-15

要检索从某个偏移量到结果集末尾的所有行,可以为第二个参数使用较大的数字。这个语句检索从第96行到最后一行的所有行:

SELECT * FROM tbl LIMIT 95,18446744073709551615;

通过一个参数,该值指定从结果集的开头返回的行数:

SELECT * FROM tbl LIMIT 5;     # Retrieve first 5 rows

FOR

如果对使用页锁或行锁的存储引擎使用FOR UPDATE,则查询检查的行将被写锁,直到当前事务结束。

FOR SHARE设置共享锁,允许其他事务读取检查的行,但不能更新或删除它们。

NOWAIT导致立即执行FOR UPDATEFOR SHARE查询,如果由于另一个事务持有的锁而无法获得行锁,则返回错误。

SKIP LOCKED导致立即执行FOR UPDATEFOR SHARE查询,排除结果集中被另一个事务锁定的行。

NOWAITSKIP LOCKED选项对于基于语句的复制是不安全的。

OF tbl_name适用于对命名表的UPDATESHARE查询。例如:

SELECT * FROM t1, t2 FOR SHARE OF t1 FOR UPDATE OF t2;

当省略OF tbl_name时,查询块所引用的所有表都被锁定。因此,将没有OF tbl_name的锁定子句与另一个锁定子句结合使用将返回错误。在多个锁子句中指定同一个表将返回错误。如果在SELECT语句中指定了别名作为表名,则锁子句只能使用该别名。如果SELECT语句没有显式指定别名,则锁定子句可能只指定实际的表名。

SELECT … INTO

SELECT…INTO形式可以将查询结果存储在变量或写入文件中。

  • SELECT ... INTO var_list :选择列值并将其存储到变量中。
  • SELECT ... INTO OUTFILE:将选定的行写入文件。可以指定列和行终止符以产生特定的输出格式。
  • SELECT ... INTO DUMPFILE:将单行写入文件而不进行任何格式化。

更多详情请看官方文档。

连接查询

MySQL支持以下JOIN语法,用于SELECT语句和多表DELETEUPDATE语句的table_references部分:

table_references:table_reference[, table_reference] ...table_reference: {table_factor| joined_table
}table_factor: {[LATERAL] table_subquery [AS] alias [(col_list)]| ( table_references )
}joined_table: {table_reference CROSS JOIN table_factor | table_reference INNER JOIN  table_factor [join_specification]| table_reference {LEFT|RIGHT} [OUTER] JOIN table_reference join_specification| table_reference NATURAL [INNER | {LEFT|RIGHT} [OUTER]] JOIN table_factor
}join_specification: {ON search_condition| USING (join_column_list)
}join_column_list:column_name [, column_name] ...index_hint_list:index_hint [, index_hint] ...index_hint: {USE {INDEX|KEY}[FOR {JOIN|ORDER BY|GROUP BY}] ([index_list])| {IGNORE|FORCE} {INDEX|KEY}[FOR {JOIN|ORDER BY|GROUP BY}] (index_list)
}index_list:index_name [, index_name] ...

下面的列表描述了编写JOIN时需要考虑的一般因素:

  • table_references表名可以使用别名tbl_name AS alias_name
  • table_subquery也称为FROM子句中的派生表或子查询。这样的子查询必须包含一个别名来为子查询结果提供一个表名,并且可以选择在括号中包含一个表列名列表。下面是一个简单的例子:
SELECT * FROM (SELECT 1, 2, 3) AS t1;
  • 在单个连接中可以引用的表的最大数量是61。这包括通过将FROM子句中的派生表和视图合并到外部查询块中来处理的连接。

请添加图片描述

CROSS JOIN和INNER JOIN

在标准SQL中,CROSS JOININNER JOIN的区别在于CROSS JOIN不能带有连接条件,而CROSS JOIN可以带有连接条件,除此之外,它们都会在指定的表之间产生笛卡尔积。但在MySQL中,CROSS JOININNOR JOINJOIN都是等价的,此外,,和它们在语义上也是等价的:

SELECT * FROM t1 LEFT JOIN (t2, t3, t4)ON (t2.a = t1.a AND t3.b = t1.b AND t4.c = t1.c)SELECT * FROM t1 LEFT JOIN (t2 CROSS JOIN t3 CROSS JOIN t4)ON (t2.a = t1.a AND t3.b = t1.b AND t4.c = t1.c)

但逗号操作符的优先级是最低的,因此连接表达式t1, t2 JOIN t3被解释为(t1, (t2 JOIN t3)),而不是((t1, t2) JOIN t3)。这会影响使用ON子句的语句,因为该子句只能引用连接操作数中的列,并且优先级会影响对这些操作数的解释。

CREATE TABLE t1 (i1 INT, j1 INT);
CREATE TABLE t2 (i2 INT, j2 INT);
CREATE TABLE t3 (i3 INT, j3 INT);
INSERT INTO t1 VALUES(1, 1);
INSERT INTO t2 VALUES(1, 1);
INSERT INTO t3 VALUES(1, 1);
SELECT * FROM t1, t2 JOIN t3 ON (t1.i1 = t3.i3);

JOIN优先于逗号操作符,因此ON子句的操作数是t2和t3,所以该语句是错误的。

同样的优先级解释也适用于将逗号操作符与INNER JOINCROSS JOINLEFT JOINRIGHT JOIN混合在一起的语句,所有这些语句的优先级都高于逗号操作符。

因此在编写语句时应该使用括号控制好优先级或避免使用逗号运算符。

ON和USING

ON一起使用的search_condition是可以在WHERE子句中使用的任何形式的条件表达式。通常,ON子句用于指定如何连接表的条件,而WHERE子句限制在结果集中包含哪些行。

USING(join_column_list)子句命名一个列列表,这些列必须同时存在于两个表中。如果表a和表b都包含c1、c2、c3列,下面的连接将比较两个表中对应的列:

a LEFT JOIN b USING (c1, c2, c3)

USING子句可以重写为比较对应列的ON子句。然而,尽管USINGON是相似的,但它们并不完全相同。考虑以下两个查询:

a LEFT JOIN b USING (c1, c2, c3)
a LEFT JOIN b ON a.c1 = b.c1 AND a.c2 = b.c2 AND a.c3 = b.c3

在确定哪些行满足连接条件方面,两个连接在语义上是相同的。

关于SELECT *展开显示哪些列,这两个连接在语义上并不相同。USING连接选择相应列的合并值,而ON连接选择所有表中的所有列。对于USING连接,SELECT *选择这些值:

COALESCE(a.c1, b.c1), COALESCE(a.c2, b.c2), COALESCE(a.c3, b.c3)

对于ON连接,SELECT *选择以下值:

a.c1, a.c2, a.c3, b.c1, b.c2, b.c3

使用内连接时,COALESCE(a.c1, b.c1)与a.c1或b.c1相同,因为两列具有相同的值。对于外部连接,两个列中的一个可以为NULL。该列将从结果中省略。

OUTER JOIN

如果在LEFT JOINONUSING部分中没有与右表匹配的行,则将所有列都设置为NULL的行用于右表。你可以使用这个事实来查找在另一个表中没有对应的行:

SELECT left_tbl.*FROM left_tbl LEFT JOIN right_tbl ON left_tbl.id = right_tbl.idWHERE right_tbl.id IS NULL;

RIGHT JOIN的工作原理类似于LEFT JOIN。为了保持代码跨数据库的可移植性,建议使用LEFT JOIN而不是RIGHT JOIN

NATURE JOIN

自然连接的冗余列不会出现,等价于使用USING的连接。MySQL根据标准SQL进行列合并和列排序,产生如下显示顺序:

  • 首先,按照第一个表中出现的顺序合并两个连接表的公共列
  • 第二,如果列在第一个表中是唯一的,按它们在该表中出现的顺序排列
  • 第三,如果列在第二个表中是唯一的,按它们在第二个表中出现的顺序排列

对于内连接,合并列定义的结果是:包含相同值列的某一列;对于外部连接,合并列定义的结果是:

  • 如果两列的值不同,则均包含
  • 如果两列的值相同,则包含某一列
  • 如果两列中有一列始终为NULL,则合并列包含非NULL列的值。

子查询

子查询是另一个语句中的SELECT语句。下面是子查询的一个例子:

SELECT * FROM t1 WHERE column1 = (SELECT column1 FROM t2);

在这个例子中,SELECT * FROM t1…是外部查询,(SELECT column1 FROM t2)是子查询。我们说子查询嵌套在外部查询中,实际上可以在其他子查询中嵌套更深的子查询。子查询必须始终出现在括号内。

子查询可以返回标量(单个值)、单行、单列或表。这些子查询称为标量子查询、列子查询、行子查询和表子查询。返回特定类型结果的子查询通常只能在某些上下文中使用。

标量子查询

在最简单的形式中,子查询是返回单个值的标量子查询。标量子查询是一个简单的操作数,您几乎可以在任何允许单列值或文字合法的地方使用它。例如:

CREATE TABLE t1 (s1 INT, s2 CHAR(5) NOT NULL);
INSERT INTO t1 VALUES(100, 'abcde');
SELECT (SELECT s2 FROM t1);

这个SELECT中的子查询返回单个值('abcde'),其数据类型为CHAR,长度为5,字符集和排序等于CREATE TABLE时的默认值。如果子查询结果为空,则结果为NULL。对于刚才显示的子查询,如果t1为空,结果将为NULL,即使s2不是NULL

使用子查询进行比较

通常使用以下形式使用子查询进行比较:

non_subquery_operand comparison_operator (subquery)

其中comparison_operator是这些操作符之一:

=  >  <  >=  <=  <>  !=  <=>

MySQL也允许这种结构:

non_subquery_operand LIKE (subquery)

带有ANY、IN或SOME的子查询

operand comparison_operator ANY (subquery)
operand IN (subquery)
operand comparison_operator SOME (subquery)

其中comparison_operator是这些操作符之一:

=  >  <  >=  <=  <>  != 

ANY关键字必须跟在比较运算符后面,表示“如果子查询返回的列中的任何一个值的比较为TRUE,则返回TRUE”。例如:

SELECT s1 FROM t1 WHERE s1 > ANY (SELECT s1 FROM t2);

当与子查询一起使用时,单词IN= ANY的别名。因此,这两个语句是相同的:

SELECT s1 FROM t1 WHERE s1 = ANY (SELECT s1 FROM t2);
SELECT s1 FROM t1 WHERE s1 IN    (SELECT s1 FROM t2);

单词SOMEANY的别名。

带有ALL的子查询

operand comparison_operator ALL (subquery)

单词ALL必须跟在比较运算符后面,表示“如果子查询返回的列中的所有值的比较都为TRUE,则返回TRUE”。例如:

SELECT s1 FROM t1 WHERE s1 > ALL (SELECT s1 FROM t2);

NOT IN<> ALL的别名。

行子查询

标量子查询或列子查询返回单个值或一列值。行子查询是返回单行的子查询变体,因此可以返回多个列值。行子查询比较的合法操作符是:

=  >  <  >=  <=  <>  !=  <=>

例如:

SELECT * FROM t1WHERE (col1,col2) = (SELECT col3, col4 FROM t2 WHERE id = 10);
SELECT * FROM t1WHERE ROW(col1,col2) = (SELECT col3, col4 FROM t2 WHERE id = 10);

带有EXISTS或NOT EXISTS的子查询

如果子查询返回任何行,则EXISTS子查询为TRUE, NOT EXISTS子查询为FALSE。例如:

SELECT column1 FROM t1 WHERE EXISTS (SELECT * FROM t2);

关联子查询

关联子查询是包含对出现在外部查询中的表的引用的子查询。例如:

SELECT * FROM t1WHERE column1 = ANY (SELECT column1 FROM t2WHERE t2.column2 = t1.column2);

派生表

派生表是在查询FROM子句范围内生成表的表达式。例如,SELECT语句FROM子句中的子查询是派生表:

SELECT ... FROM (subquery) [AS] tbl_name ...

[AS] tbl_name子句是强制性的,因为FROM子句中的每个表都必须有一个名称。派生表中的任何列都必须具有唯一的名称。或者,tbl_name后面可以跟一个带括号的派生表列的名称列表:

SELECT ... FROM (subquery) [AS] tbl_name (col_list) ...

横向派生表

派生表通常不能在同一个FROM子句中引用前面表的列。从MySQL 8.0.14开始,派生表可以定义为横向派生表,以指定允许这样的引用。

SELECTsalesperson.name,max_sale.amount,max_sale.customer_name
FROMsalesperson,LATERAL(SELECT amount, customer_nameFROM all_salesWHERE all_sales.salesperson_id = salesperson.idORDER BY amount DESC LIMIT 1)AS max_sale;

子查询的限制

  • 通常,不能在修改表的同时在子查询中从同一表中进行选择。
  • 仅部分支持行比较操作
  • MySQL不支持某些子查询LIMIT

集操作(UNION、INTERSECT和EXCEPT)

SQL集操作将多个查询块的结果合并为单个结果。查询块是返回结果集的任何SQL语句,例如SELECT。SQL标准定义了以下三种集合操作:

  • UNION:将来自两个查询块的所有结果合并为单个结果,省略任何重复项。
  • INTERSECT:只合并两个查询块的结果相同的行,省略任何重复的行。
  • EXCEPT:对于两个查询块A和B,返回A中不存在于B中的所有结果,省略任何重复的结果。

这些集合操作符都支持一个ALL修饰符,该修饰符会导致结果中包含重复项。

所有三个集操作符还支持DISTINCT关键字,该关键字抑制结果中的重复项。由于这是集操作符的默认行为,因此通常不需要显式指定DISTINCT

你应该知道,在UNIONEXCEPT之前,INTERSECT会被求值。这意味着,例如,TABLE x UNION TABLE y INTERSECT TABLE z总是被计算为TABLE x UNION (TABLE y INTERSECT TABLE z)

集操作结果的列名取自第一个查询块的列名。

mysql> CREATE TABLE t1 (x INT, y INT);
Query OK, 0 rows affected (0.04 sec)mysql> INSERT INTO t1 VALUES ROW(4,-2), ROW(5,9);
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0mysql> CREATE TABLE t2 (a INT, b INT);
Query OK, 0 rows affected (0.04 sec)mysql> INSERT INTO t2 VALUES ROW(1,2), ROW(3,4);
Query OK, 2 rows affected (0.01 sec)
Records: 2  Duplicates: 0  Warnings: 0mysql> TABLE t1 UNION TABLE t2;
+------+------+
| x    | y    |
+------+------+
|    4 |   -2 |
|    5 |    9 |
|    1 |    2 |
|    3 |    4 |
+------+------+
4 rows in set (0.00 sec)mysql> TABLE t2 UNION TABLE t1;
+------+------+
| a    | b    |
+------+------+
|    1 |    2 |
|    3 |    4 |
|    4 |   -2 |
|    5 |    9 |
+------+------+
4 rows in set (0.00 sec)

要将ORDER BYLIMIT子句应用于作为联合、交集或其他集合操作的一部分的单个查询块,请将查询块括起来,将子句放在括号内,如下所示:

(SELECT a FROM t1 WHERE a=10 AND b=1 ORDER BY a LIMIT 10)
UNION
(SELECT a FROM t2 WHERE a=11 AND b=2 ORDER BY a LIMIT 10);(TABLE t1 ORDER BY x LIMIT 10) 
INTERSECT 
(TABLE t2 ORDER BY a LIMIT 10);

要使用ORDER BY或LIMIT子句对集合操作的整个结果进行排序或限制,请将ORDER BY或LIMIT放在最后一条语句之后:

SELECT a FROM t1
EXCEPT
SELECT a FROM t2 WHERE a=11 AND b=2
ORDER BY a LIMIT 10;TABLE t1
UNION 
TABLE t2
ORDER BY a LIMIT 10;

如果要排序的列有别名,ORDER BY子句必须引用别名,而不是列名。

UPDATE

UPDATE是一个DML语句,用于修改表中的行,返回实际更改的行数

UPDATE table_referenceSET assignment_list[WHERE where_condition][ORDER BY ...][LIMIT row_count]value:{expr | DEFAULT}assignment:col_name = valueassignment_list:assignment [, assignment] ...

UPDATE语句用新值更新已命名表中现有行的列。SET子句指出要修改哪些列,以及应该给它们指定哪些值。每个值可以通过表达式给出,也可以通过关键字DEFAULT显式地设置列的默认值。如果给出了WHERE子句,它指定了标识要更新哪些行的条件。如果没有WHERE子句,则更新所有行。如果指定了ORDER BY子句,则按照指定的顺序更新行。LIMIT子句限制了可以更新的行数。

相关文章:

MySQL十部曲之六:数据操作语句(DML)

文章目录 前言语法约定DELETEINSERTSELECT查询列表SELECT 选项子句FROMWHEREORDER BYGROUP BYHAVINGWINDOWLIMITFOR SELECT ... INTO连接查询CROSS JOIN和INNER JOINON和USINGOUTER JOINNATURE JOIN 子查询标量子查询使用子查询进行比较带有ANY、IN或SOME的子查询带有ALL的子查…...

Quartus生成烧录到FPGA板载Flash的jic文件

简要说明&#xff1a; Altera的FPGA芯片有两种基本分类&#xff0c;一类是纯FPGA&#xff0c;另一类是FPGASoc&#xff08;System on chip)&#xff0c;也就是FPGAHPS&#xff08;Hard Processor System&#xff0c;硬核处理器&#xff09;&#xff0c;对应两种Flash烧录方式&a…...

CSS 多色正方形上升

<template><view class="loop cubes"><view class="item cubes"></view> <!-- 方块1 --><view class="item cubes"></view> <!-- 方块2 --><view class="item cubes"></vie…...

《HelloGitHub》第 94 期

兴趣是最好的老师&#xff0c;HelloGitHub 让你对编程感兴趣&#xff01; 简介 HelloGitHub 分享 GitHub 上有趣、入门级的开源项目。 https://github.com/521xueweihan/HelloGitHub 这里有实战项目、入门教程、黑科技、开源书籍、大厂开源项目等&#xff0c;涵盖多种编程语言 …...

uniapp 实现路由拦截,权限或者登录控制

背景&#xff1a; 项目需要判断token&#xff0c;即是否登录&#xff0c;登录之后权限 参考uni-app官方&#xff1a; 为了兼容其他端的跳转权限控制&#xff0c;uni-app并没有用vue router路由&#xff0c;而是内部实现一个类似此功能的钩子&#xff1a;拦截器&#xff0c;由…...

[GXYCTF2019]BabySQli1

单引号闭合&#xff0c;列数为三列&#xff0c;但是没有期待的1 2 3回显&#xff0c;而是显示wrong pass。 尝试报错注入时发现过滤了圆括号&#xff0c;网上搜索似乎也没找到能绕过使用圆括号的方法&#xff0c;那么按以往爆库爆表爆字段的方法似乎无法使用了 在响应报文找到一…...

【架构】Docker实现集群主从缩容【案例4/4】

实现集群主从缩容【4/4】 接上一节&#xff0c;在当前机器为4主4从的架构上&#xff0c;减缩容量为3主3从架构。即实现删除6387和6388. 示意图如下&#xff1a; 第一步&#xff1a;查看集群情况&#xff08;第一次&#xff09; redis-cli --cluster check 127.0.0.1:6387roo…...

【ArcGIS微课1000例】0097:栅格重采样(以数字高程模型dem为例)

Contents 1. 最邻近法(Nearest Neighbor)2. 双线性内插法(Bilinear Interpolation)3. 三次卷积法(Cubic Convolution)4. ArcGIS重采样工具(Resample)5. 注意事项栅格/影像数据进行配准或纠正、投影等几何变换后,像元中心位置通常会发生变化,其在输入栅格中的位置不一…...

【技术分享】Ubuntu 20.04如何更改用户名

产品简介 本文适用于所有RK3568/RK3588平台产品在Ubuntu 20.04系统上如何更改用户名&#xff0c;本文以IDO-EVB3588开发板为例&#xff0c;在ubuntu20.04系统上修改用户名industio为usernew。 IDO-EVB3588开发板是一款基于RK3588平台的产品。该开发板集成了四核Cortex-A76和四…...

LabVIEW振动信号分析

LabVIEW振动信号分析 介绍如何使用LabVIEW软件实现希尔伯特-黄变换&#xff08;Hilbert-Huang Transform, HHT&#xff09;&#xff0c;并将其应用于振动信号分析。HHT是一种用于分析非线性、非平稳信号的强大工具&#xff0c;特别适用于旋转机械等复杂系统的振动分析。开发了…...

清理Docker环境

清理Docker环境&#xff1a;有时&#xff0c;Docker环境可能会出现一些问题&#xff0c;导致网络连接故障。您可以尝试清理Docker环境并重新启动。可以尝试运行以下命令&#xff1a; 复制 docker-compose down docker system prune -a docker-compose up docker-compose up 和…...

oracle等保测评

实战|等保2.0 Oracle数据库测评过程 一、身份鉴别 a) 应对登录的用户进行身份标识和鉴别,身份标识具有唯一性,身份鉴别信息具有复杂度要求并定期更换; sysdba是Oracle数据库的最高权限管理员。通常使用sqlplus或PL/SQL 管理软件进行管理,PL/SQL 为第三方管理软件,但S…...

x-cmd pkg | go - Google 开发的开源编程语言

目录 简介首次用户技术特点竞品分析编译型语言解释型语言JavaWebAssebmly 进一步阅读 简介 Go 语言&#xff08;或 Golang&#xff09;是 Google 开发的开源编程语言&#xff0c;诞生于 2006 年。其设计目标是“兼具 Python 等动态语言的开发速度和 C/C 等编译型语言的性能与安…...

32个Java面试必考点-09(下)MySQL调优与最佳实践

详解 MySQL 下面来学习互联网行业使用最为广泛的关系型数据库 MySQL&#xff0c;它的知识点结构图如下所示。 常用 SQL 语句 对于手写常用 SQL 语句&#xff0c;没有什么特殊的技巧&#xff0c;根据所列的语句类型多做一些练习就好。 数据类型 要知道 MySQL 都提供哪些基本的…...

优思学院|精益管理如何判定哪些活动是增值或非增值?

“时间就是金钱”——这句老话我们都耳熟能详。但在工作中&#xff0c;我们真正从事的、对组织增加价值的活动有多少呢&#xff1f;我们常常认为自己的每一项任务都是维持运营的关键。然而&#xff0c;当我们从精益管理的视角进行分析&#xff0c;可能会惊讶地发现&#xff0c;…...

详解操作系统各章大题汇总(死锁资源分配+银行家+进程的PV操作+实时调度+逻辑地址->物理地址+页面置换算法+磁盘调度算法)

文章目录 第三章&#xff1a;死锁资源分配图例一例二 第三章&#xff1a;银行家算法第四章&#xff1a;进程的同步与互斥做题步骤PV操作的代码小心容易和读者写者混 1.交通问题&#xff08;类似读者写者&#xff09;分析代码 2.缓冲区问题&#xff08;第二个缓冲区是复制缓冲区…...

用ASM HEMT模型提取GaN器件的参数

标题&#xff1a;Physics-Based Multi-Bias RF Large-Signal GaNHEMT Modeling and Parameter Extraction Flow (JEDS 17年) 模型描述 该模型的核心是对表面势&#xff08;ψ&#xff09;及其随施加的栅极电压&#xff08;Vg&#xff09;和漏极电压&#xff08;Vd&#xff09…...

github ssh ssh-keygen

生成和使用 SSH 密钥对是一种安全的身份验证方式&#xff0c;用于在你的本地系统和 GitHub 之间进行身份验证。以下是在 GitHub 上生成和使用 SSH 密钥对的基本步骤&#xff1a; 1. 生成 SSH 密钥对 在命令行中执行以下命令来生成 SSH 密钥对&#xff1a; ssh-keygen -C &q…...

响应式Web开发项目教程(HTML5+CSS3+Bootstrap)第2版 例5-2 JavaScript 获取HTML元素对象

代码 <!doctype html> <html> <head> <meta charset"utf-8"> <title>JavaScript 获取 HTML 元素对象</title> </head><body> <input type"text" value"admin" /> <br> <input …...

微信实现如何批量自动添加好友?

在快节奏的社交环境中&#xff0c;我们常常需要扩展我们的社交圈子并与更多人建立联系。那么&#xff0c;有没有一种方法可以帮助我们更高效地批量添加微信好友呢&#xff1f;答案是肯定的&#xff01;借助微信管理系统&#xff0c;你将能够轻松实现这一目标。 首先&#xff0…...

vue3+echarts绘制某省区县地图

vue3echarts绘制某省区县地图 工作中经常需要画各种各样的图&#xff0c;echarts是使用最多的工具&#xff0c;接近春节&#xff0c;想把之前画的echarts图做一个整合&#xff0c;方便同事和自己随时使用&#xff0c;因此用vue3专门写了个web项目&#xff0c;考虑之后不断完善…...

MyBatis详解(2)-- mybatis配置文件

MyBatis详解&#xff08;2&#xff09; mybatis配置文件 mybatis配置文件 1.构建SqlSessionFactory的依据。 2.MyBatis最为核心的内容&#xff0c;对MyBatis的使用影响很大。 3.配置文件的层次顺序不能颠倒&#xff0c;一旦颠倒会出现异常。 < c o n f i g u r a t i o n…...

蓝桥杯备战——8.DS1302时钟芯片

1.分析原理图 由上图可以看到&#xff0c;芯片的时钟引脚SCK接到了P17,数据输出输入引脚IO接到P23,复位引脚RST接到P13。 2.查阅DS1302芯片手册 具体细节还需自行翻阅手册&#xff0c;我只截出重点部分 总结&#xff1a;数据在上升沿写出&#xff0c;下降沿读入&#xff0c;…...

freeRTOS / day02

1. 定时器使用流程 1.1 ST32CubeMX 设置 1.1.0 选择定时器 --> TIM1 1.1.1 Clock Source --> Internal Clock 1.1.2 Prescaler --> 预分频系数 1.1.3 Counter Period -- > 重装值 1.1.4 Prescaler 和 Counter Period 计算公式 定时时间&#xff08;s) &…...

Ubuntu 18.04 x86_64 上交叉编译 boost 库(ARMv7L)

先安装 ARMv7L 交叉编译器环境&#xff1a; 在 Ubuntu 18.04 x86_64 上面安装 Linux-ARMv7 A/L GCC编译器-CSDN博客 1、下载 boost 1.84 的源代码访问要编译的目录&#xff0c;并且解压出来源代码&#xff0c;切入源代码根目录 2、./bootstrap.sh --with-librariesfilesyste…...

为什么 FPGA 比 CPU 和 GPU 快?

FPGA、GPU 与 CPU——AI 应用的硬件选择 现场可编程门阵列 (FPGA) 为人工智能 (AI) 应用带来许多优势。图形处理单元 (GPU) 和传统中央处理单元 (CPU) 相比如何&#xff1f; 人工智能&#xff08;AI&#xff09;一词是指能够以类似于人类的方式做出决策的非人类机器智能。这包…...

js常用函数总结

js常用函数总结 1、模糊搜索 export const fuzzyQuery (list, keyWord, attribute name) > {const reg new RegExp(keyWord)const arr []for (let i 0; i < list.length; i) {if (reg.test(list[i][attribute])) {arr.push(list[i])}}return arr } list 原数组 ke…...

cartographer离线建图报错:data_.trajectory_nodes.SizeOfTrajectoryOrZero

cartographer离线建图报错: data_.trajectory_nodes.SizeOfTrajectoryOrZero [FATAL] [1706177325.876019302, 1706015603.398505596]: F0125 18:08:45.000000 17607 pose_graph_2d.cc:1314] Check failed: data_.trajectory_nodes.SizeOfTrajectoryOrZero(trajectory_id) &…...

【YOLO系列算法俯视视角下舰船目标检测】

YOLO系列算法俯视视角下舰船目标检测 数据集和模型YOLO系列算法俯视视角下舰船目标检测YOLO系列算法俯视视角下舰船目标检测可视化结果 数据集和模型 数据和模型下载&#xff1a; YOLOv6俯视视角下舰船目标检测训练好的舰船目标检测模型舰船目标检测数据YOLOv7俯视视角下舰船…...

python进程间使用共享内存multiprocessing.shared_memory来通讯

python多个进程通讯使用共享内存 1、multiprocessing.shared_memory ​ 使用这个模块可从进程直接访问共享内存,该模块提供了一个 SharedMemory 类,用于分配和管理多核或对称多处理器(SMP)机器上进程间的共享内存。 ​ 为了协助管理不同进程间的共享内存生命周期,multi…...