跳转到内容

十一级信息学实践(CBSE)/简单查询

来自维基教科书,开放世界中的开放书籍

注意:基于 语言章节MySQL 图书.

浏览数据库

[编辑 | 编辑源代码]

以下 SQL 命令提供有关当前服务器上的数据库的信息。包含此信息的 INFORMATION_SCHEMA 表是 SCHEMATA。

mysqlshow 命令行工具可以用来代替。

如果服务器使用 —skip-all-databases 选项启动,则无法显示数据库。

如果您没有“SHOW DATABASES”权限,您将只能看到您拥有某些权限的数据库。

列出数据库

[编辑 | 编辑源代码]

显示所有数据库

SHOW DATABASES;

SCHEMA 关键字可以用来代替 DATABASES。MySQL 不支持标准 SQL SCHEMAs,因此 SCHEMA 是数据库的同义词。它已添加以与其他 DBMS 兼容。

在数据库名称上添加过滤器

[编辑 | 编辑源代码]
SHOW DATABASES LIKE 'pattern';

此处的 LIKE 运算符与普通 SELECT 或 DML 语句中的工作方式相同。因此您可以列出所有名称以“my”开头的数据库

SHOW DATABASES LIKE'MY%';

添加复杂过滤器

[编辑 | 编辑源代码]

您可以使用 WHERE 子句添加更复杂的过滤器

SHOW DATABASES WHERE (conditions);

WHERE 子句允许您使用正则表达式、“<” 和 “>” 运算符、字符串函数或其他有用的表达式来过滤 SHOW DATABASES 返回的记录。

列出表和视图

[编辑 | 编辑源代码]

以下 SQL 命令提供有关数据库中包含的表和视图的信息。包含此信息的 INFORMATION_SCHEMA 表是 `TABLES` 和 `VIEWS`。

由于以下语句关于视图提供了很少的信息,如果您需要获取有关它们的元数据,您可能更愿意查询 VIEWS 表。

mysqlshow 命令行工具可以用来代替。

显示所有表

[编辑 | 编辑源代码]
USE database;
SHOW TABLES;
SHOW TABLES FROM database;

上面显示的两种形式是等效的。

应用过滤器

[编辑 | 编辑源代码]

您可以对表名应用过滤器,以仅显示名称与模式匹配的表。您可以使用 LIKE 运算符,就像您在 SELECT 或 DML 语句中一样

SHOW TABLES LIKE `pattern`;

此外,您可以使用 WHERE 子句对 SHOW TABLES 命令返回的任何列应用更复杂的过滤器。

SHOW TABLES WHERE condition;

(见下文)

额外信息

[编辑 | 编辑源代码]

默认情况下,SHOW TABLES 仅返回包含表名的单列。您可以使用 FULL 关键字获取更多信息。

SHOW FULL TABLES;

这将添加一个名为 `Table_type` 的列。它可以有 3 个值:`BASE TABLE` 用于表,`VIEW` 用于视图,`SYSTEM VIEW` 用于服务器创建的特殊表(通常仅用于 INFORMATION_SCHEMA 表)。

所以你只能列出表

SHOW FULL TABLES WHERE `Table_type`='BASE TABLE';

或者,您只能列出视图

SHOW FULL TABLES WHERE `Table_type`='VIEW';

仅显示打开的表

[编辑 | 编辑源代码]

您可以获取缓存中打开的非临时表(非视图)的列表。

SHOW OPEN TABLES;

此命令与 SHOW TABLES 具有相同的参数,除了 FULL(在这种情况下无用)。您无法从 INFORMATION_SCHEMA 获取此信息。

列出字段

[编辑 | 编辑源代码]

以下 SQL 命令提供有关表或视图中列的信息。包含此信息的 INFORMATION_SCHEMA 表是 COLUMNS。

mysqlshow 命令行工具可以用来代替。

DESCRIBE `table`;
DESCRIBE `database`.`table`;
DESCRIBE `table` 'filter';

DESC 可用作 DESCRIBE 的快捷方式。

`filter` 可以是列名。如果指定了列名,则仅显示该列。如果 `filter` 包含 `%` 或 `_` 字符,它将被评估为 LIKE 条件。例如,您可以列出所有以 `my` 开头的字段。

DESC `table` 'my%';

SHOW COLUMNS

[编辑 | 编辑源代码]
EXPLAIN `table`; --synonym
SHOW [FULL] FIELDS FROM `table`; -- synonym
SHOW COLUMNS FROM `table`; --synonym
SHOW COLUMNS FROM `table` FROM `database`;
SHOW COLUMNS FROM `table` LIKE 'pattern';
SHOW COLUMNS FROM `table` WHERE condition;

FIELDS 和 COLUMNS 是同义词。EXPLAIN 也是 SHOW COLUMNS / FIELDS 的同义词,但它不支持所有子句。

数据库名称可以在两种形式中指定

SHOW COLUMNS FROM `table` FROM `database`;

两者

SHOW COLUMNS FROM `database`.`table`;

额外信息

[编辑 | 编辑源代码]

使用 FULL 关键字,可以重试额外信息:列的排序规则、您对列拥有的权限以及注释。

列出索引

[编辑 | 编辑源代码]

以下 SQL 命令提供有关表中索引的信息。有关键的信息包含在 INFORMATION_SCHEMA 的 `COLUMNS` 表中。

可以使用 mysqlshow -k 命令行工具代替。

SHOW INDEX FROM `TABLE`;
SHOW INDEX FROM `TABLE` FROM `databases`;

KEYS 保留字可用作 INDEX 的同义词。不提供其他子句。

INFORMATION_SCHEMA

[编辑 | 编辑源代码]

information_schema 是 MySQL 5 及更高版本提供的虚拟数据库,其中包含有关服务器和数据库的元数据。

指定名称

[编辑 | 编辑源代码]

在本书中,我们将使用反引号 (`) 引用 MySQL 标识符(表名、字段、数据库等)。

反引号是 ASCII 96。它可以通过按 ALT+' 在 GNU/Linux 系统上键入。

大多数情况下,这是可选的。但是,这允许 MySQL 提供更好的错误消息。例如,此错误不太有用

mysql> SELECT user_id, group_id FROM user,group LIMIT 1;
ERROR 1064 (42000): 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 'group LIMIT 1' at line 1

但这个更好

mysql> SELECT user_id, group_id FROM `user`,`group` LIMIT 1;
ERROR 1146 (42S02): Table 'savannah.group' doesn't exist

好的,它只是一个缺失的 s

mysql>  SELECT user_id, group_id FROM `user`,`groups` LIMIT 1;
+---------+----------+
| user_id | group_id |
+---------+----------+
|     100 |        2 |
+---------+----------+
1 row in set (0.02 sec)

此语法允许用户在对象名称中使用保留字和一些非法字符。甚至可以通过两次键入它来使用反引号。

RENAME TABLE `user` TO ````

但是,这不是可移植的语法。SQL 标准建议使用双引号 (")。如果您想编写可移植的 SQL 引号,请不要引用标识符。但真的有像可移植 SQL 这样的东西吗?;)

定义:什么是 DDL、DML 和 DQL?

[编辑 | 编辑源代码]
  • DDL(数据定义语言)是指 CREATE、ALTER 和 DROP 语句
  • DML(数据操作语言)是指 INSERT、UPDATE 和 DELETE 语句
  • DQL(数据查询语言)是指 SELECT、SHOW 和 HELP 语句(查询)
  • DCL(数据控制语言)是指 GRANT 和 REVOKE 语句

用户变量

[编辑 | 编辑源代码]

会话变量

[编辑 | 编辑源代码]
  • 使用 := 赋值运算符在语句中设置变量的能力
  • 例如,(@total)用于在示例中计算总计,您必须先拥有 total 列,因为它必须在个别百分比计算之前计算
  • 会话变量在整个线程持续时间内设置。
  • 在绝大多数情况下,您会使用编程语言来做这种事情。
  • Mysql 变量在使用 Mysql 命令行时很有用。
  • 如果未返回任何记录,则用户变量将不会为该语句设置。
  • 在字段列表中设置的用户变量不能用作条件。
select @test := 2;
select @test + 1
  • 变量的值使用 SET 语句或带有 := 的 SELECT 语句设置
set @startdate='some_start_date', @enddate='some_end_date'
SELECT @toremember:=count(*) FROM membros;
select @numzero := count(*) from table1 where field=0; 
select @numdistinct := count(distinct field) from table1 where field <> 0 ; 
select @numzero @numdistinct;
  • 您可以将 SELECT 检索到的值复制到一个或多个变量中
SELECT INTO

全局变量

[编辑 | 编辑源代码]

全局变量对所有用户可见。

SHOW VARIABLES

[编辑 | 编辑源代码]

可以使用 AS 为表达式和列指定别名。别名用作表达式的列名,可用于 order by 或 having 子句。例如

SELECT 
    CONCAT(last_name,' ', first_name) AS full_name,
    nickname AS nick 
FROM
    mytable 
ORDER BY
    full_name

这些别名可以在 ORDER BY、GROUP BY 和 HAVING 子句中使用。它们不应在 WHERE 子句中使用。

表名可以使用 AS 为引用提供更短的名称。您可以省略 AS 字词并仍然使用别名。例如

SELECT
    COUNT(B.Booking_ID), U.User_Location 
FROM
    Users U
LEFT OUTER JOIN
    Bookings AS B
ON 
    U.User_ID    = B.Rep_ID AND
    B.Project_ID = '10'
GROUP BY
    (U.User_Location)

别名在您使用自连接时起着至关重要的作用。例如,people 表已称为 p 和 c 别名!

SELECT
    p.name                                   AS parent,
    c.name                                   AS child,
    MIN((TO_DAYS(NOW())-TO_DAYS(c.dob))/365) AS minage
FROM
    people AS p 
LEFT JOIN
    people AS c 
ON
    p.name=c.parent WHERE c.name IS NOT NULL
GROUP BY
    parent HAVING minage > 50 ORDER BY p.dob;

SELECT

[edit | edit source]

select 语法如下

SELECT *
FROM table
WHERE condition
GROUP BY grouping field
HAVING group condition
ORDER BY order
LIMIT limit, offset

字段列表

[edit | edit source]

您必须在 SELECT 子句中指定要检索的数据

SELECT DATABASE() -- returns the current db's name
SELECT CURRENT_USER() -- returns your username
SELECT 1+1 -- returns 2

这里允许使用任何 SQL 表达式。

您还可以从表中检索所有字段

SELECT * FROM `stats`

如果您只选择必要的字段,查询将更快。

表的名称

[edit | edit source]

如果您要从表或视图中检索结果,通常您会在 FORM 子句中指定表的名称

SELECT id FROM `stats`—retrieve a field called id from a table called stats

或者

SELECT MAX(id) FROM `stats`
SELECT id*2 FROM `stats`

您也可以使用 `db_name`.`table_name` 语法

SELECT id FROM `sitedb`.`stats`

但是您也可以在 SELECT 子句中指定表的名称

SELECT `stats`.`id`—retrieve a field called id from a table
SELECT `sitedb`.`stats`.`id`

WHERE

[edit | edit source]

您可以设置一个过滤器来决定要检索哪些记录。

例如,您可以只检索 id 为 42 的记录

SELECT * FROM `stats` WHERE `id`=42

或者您可以读取多条记录

SELECT * FROM `antiques` WHERE buyerid IS NOT NULL

GROUP BY

[edit | edit source]

您可以按一个或多个字段对所有记录进行分组。对于在该字段具有相同值的记录,将被分组到一个计算记录中。您只能选择分组记录和一些聚合函数的结果,这些函数将在每个组的所有记录上计算。

例如,以下将对表 `users` 中的所有记录按字段 `city` 进行分组。对于居住在同一城市的每组用户,将返回最大年龄、最小年龄和平均年龄

SELECT city, MAX(age), MIN(age), AVG(age) GROUP BY `city`,

在以下示例中,用户按城市和性别分组,这样我们就可以知道每个城市中男性/女性用户的最大、最小和平均年龄

SELECT city, sex, MAX(age), MIN(age), AVG(age) GROUP BY `city`, `sex`

HAVING

[edit | edit source]

HAVING 子句声明对由 GROUP BY 子句计算的记录的过滤器。它不同于 WHERE 子句,WHERE 子句在 GROUP BY 之前操作。以下是发生的事情

  1. 与 WHERE 子句匹配的记录将被检索
  2. 这些记录用于根据 GROUP BY 子句中定义的计算新记录
  3. 与 HAVING 条件匹配的新记录将被返回

这意味着 WHERE 决定什么记录用于组成新的计算记录。

HAVING 决定返回哪些计算记录,因此它可以对聚合函数的结果进行操作。HAVING 没有优化,不能使用索引。

HAVING 的错误使用

SELECT city, sex, MAX(age), MIN(age), AVG(age) GROUP BY `city` HAVING sex='m'

这可能会导致错误的结果。MAX(age) 和其他聚合计算使用所有值进行,即使记录的 sex 值为 'f'。这不太可能是预期结果。

HAVING 的错误使用

SELECT city, sex, MAX(age), MIN(age), AVG(age) GROUP BY `city`, `sex` HAVING sex='m'

这是正确的,并返回预期结果,但此查询的执行没有优化。WHERE 子句可以也应该使用,因为这样 MySQL 就不会计算以后被排除的记录。

HAVING 的正确使用

SELECT city, sex, MAX(age), MIN(age), AVG(age) GROUP BY `city` HAVING MAX(age) > 80

它必须对所有记录进行分组,因为它在执行 GROUP BY 子句之前无法确定每个城市的最高年龄。之后,它只返回 MAX(age)>80 的记录。

ORDER BY

[edit | edit source]

您可以为检索的记录设置任意顺序。顺序可以是字母顺序或数字顺序。

SELECT * FROM `stats` ORDER BY `id`

默认情况下,顺序是 ASCENDING。您还可以指定顺序必须是 DESCENDING

SELECT * FROM `stats` ORDER BY `id` ASC—default
SELECT * FROM `stats` ORDER BY `id` DESC—inverted

NULL 值被视为小于任何其他值。

您也可以指定字段位置,而不是字段名称

SELECT `name`, `buyerid` FROM `antiques` ORDER BY 1 -- name
SELECT `name`, `buyerid` FROM `antiques` ORDER BY 2 -- buyerid
SELECT `name`, `buyerid` FROM `antiques` ORDER BY 1 DESC

允许使用 SQL 表达式

SELECT `name` FROM `antiques` ORDER BY REVERSE(`name`)

您可以以随机顺序检索记录

SELECT `name` FROM `antiques` ORDER BY RAND()

如果指定了 GROUP BY 子句,则结果将按 GROUP BY 中命名的字段排序,除非存在 ORDER BY 子句。您甚至可以在 GROUP BY 子句中指定顺序是升序还是降序

SELECT city, sex, MAX(age) GROUP BY `city` ASC, `sex` DESC

如果您有 GROUP BY,但您不希望记录排序,可以使用 ORDER BY NULL

SELECT city, sex, MAX(age) GROUP BY `city`, `sex` ORDER BY NULL

LIMIT

[edit | edit source]

您可以指定要读取的最大行数

SELECT * FROM `antiques` ORDER BY id LIMIT 10

此语句最多返回 10 行。如果不存在 10 行,则返回找到的行数。limit 子句通常与 ORDER BY 一起使用。

您可以获取给定数量的随机记录

SELECT * FROM `antiques` ORDER BY rand() LIMIT 1 -- one random record
SELECT * FROM `antiques` ORDER BY rand() LIMIT 3

您可以指定在开始返回找到的记录之前应该跳过多少行。第一条记录是 0,而不是 1

SELECT * FROM `antiques` ORDER BY id LIMIT 10
SELECT * FROM `antiques` ORDER BY id LIMIT 0, 10—synonym

您可以使用 LIMIT 子句来获取结果的分页

SELECT * FROM `antiques` ORDER BY id LIMIT 0, 10—first page
SELECT * FROM `antiques` ORDER BY id LIMIT 10, 10—second page
SELECT * FROM `antiques` ORDER BY id LIMIT 20, 10—third page

此外,还接受以下语法

SELECT * FROM `antiques` ORDER BY id LIMIT 10 OFFSET 10

您可以使用 LIMIT 来检查查询的语法,而无需等待它返回结果

SELECT ... LIMIT 0

优化技巧

  • SQL_CALC_FOUND_ROWS 可以加快 LIMIT 的速度。
  • LIMIT 特别适用于使用 ORDER BY、DISTINCT 和 GROUP BY 的 SELECT,因为它们的计算不必涉及所有行。
  • 如果查询通过服务器将结果内部复制到临时表中来解决,则 LIMIT 有助于 MySQL 计算表所需的内存量。

DISTINCT

[edit | edit source]

DISTINCT 关键字可用于从结果集中删除所有重复行

SELECT DISTINCT * FROM `stats`—no duplicate rows
SELECT DISTINCTROW * FROM `stats`—synonym
SELECT ALL * FROM `stats`—duplicate rows returned (default)

您可以使用它来获取包含在一个字段中的所有值的列表

SELECT DISTINCT `type` FROM `antiques` ORDER BY `type`

或者您可以使用它来获取一些值的现有组合

SELECT DISTINCT `type`, `age` FROM `antiques` ORDER BY `type`

如果要 SELECT 的字段之一是 PRIMARY KEY 或具有 UNIQUE 索引,则 DISTINCT 无用。此外,在与 GROUP BY 子句结合使用时,使用 DISTINCT 也是无用的。

IN 和 NOT IN

[edit | edit source]
SELECT id
FROM stats
WHERE position IN ('Manager', 'Staff')
SELECT ownerid, 'is in both orders & antiques'
FROM orders, antiques WHERE ownerid = buyerid
UNION
SELECT buyerid, 'is in antiques only'
FROM antiques WHERE buyerid NOT IN (SELECT ownerid FROM orders)

EXISTS 和 ALL

[edit | edit source]

(兼容:Mysql 4+)

SELECT ownerfirstname, ownerlastname
FROM owner 
WHERE EXISTS (SELECT * FROM antiques WHERE item = 'chair')
SELECT buyerid, item 
FROM antiques
WHERE price = ALL (SELECT price FROM antiques)

优化提示

[edit | edit source]

有一些提示您可能希望提供给服务器以更好地优化 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]
   ...

HIGH_PRIORITY

通常,DML 命令 (INSERT、DELETE、UPDATE) 优先级高于 SELECT。如果您指定 HIGH_PRIORITY,则 SELECT 的优先级将高于 DML 语句。

STRAIGHT_JOIN 强制 MySQL 按命名顺序评估 JOIN 的表,从最左边开始。

SQL_SMALL_RESULT 仅在使用 DISTINCT 或 GROUP BY 时有用。告诉优化器查询将返回少量行。

SQL_BIG_RESULT 仅在使用 DISTINCT 或 GROUP BY 时有用。告诉优化器查询将返回许多行。

SQL_BUFFER_RESULT 强制 MySQL 将结果复制到临时表中。这有助于尽快移除 LOCK。

SQL_CACHE 强制 MySQL 将结果复制到查询缓存中。仅在 query_cache_type 的值为 DEMAND 或 2 时才有效。

SQL_NO_CACHE 告诉 MySQL 不要缓存结果。如果查询很少发生或结果经常更改,这将很有用。

SQL_CALC_FOUND_ROWS 如果您使用 LIMIT 子句,这将很有用。告诉服务器计算如果没有 LIMIT 将返回多少行。您可以使用另一个查询检索该数字

SELECT SQL_CALC_FOUND_ROWS * FROM `stats` LIMIT 10 OFFSET 100;
SELECT FOUND_ROWS();

UNION 和 UNION All

[edit | edit source]

(兼容:Mysql 4+)

以下查询将返回两个表中的所有记录。

SELECT * FROM English 
UNION ALL
SELECT * FROM Hindi

UNIONUNION DISTINCT.
相同。如果您只键入 UNION,则表示您正在请求不同的记录。如果您想要所有记录,您必须使用UNION ALL.

SELECT word FROM word_table WHERE id = 1
UNION
SELECT word FROM word_table WHERE id = 2
(SELECT magazine FROM pages)
UNION DISTINCT
(SELECT magazine FROM pdflog)
ORDER BY magazine
(SELECT ID_ENTRY FROM table WHERE ID_AGE = 1)
UNION DISTINCT 
(SELECT ID_ENTRY FROM table WHERE ID_AGE=2)

数据操作

[edit | edit source]

INSERT

[edit | edit source]

语法如下

将 value1 插入 Column1,将 value2 插入 Column2,将 value3 插入 Column3

INSERT INTO TableName (Column1, Column2, Column3)
VALUES (value1, value2, value3)

插入一条记录(值按列在数据库中出现的顺序插入)

INSERT INTO TableName
VALUES (value1, value2, value3)

插入两条记录

INSERT INTO TableName
VALUES (value1, value2, value3), (value4, value5, value6)
INSERT INTO antiques VALUES (21, 01, 'Ottoman', 200.00);
INSERT INTO antiques (buyerid, sellerid, item) VALUES (01, 21, 'Ottoman');

您也可以插入来自其他表的“选定”记录。

INSERT INTO table1(field1, field2)
SELECT field1, field2
FROM table2
INSERT INTO World_Events SELECT * FROM National_Events

性能提示

  • 要插入多行,请考虑使用 LOAD DATA INFILE。
  • 如果批量 INSERT 太慢,并且它们对索引的非空表进行操作,也许您应该增加 bulk_insert_buffer_size 的值。
  • 在执行批量插入之前,您可能需要禁用 keys。
  • 锁定表也可以加快 INERT 速度。

语法是

UPDATE table SET field = newvalue WHERE criteria ORDER BY field LIMIT n

示例如下:

UPDATE owner SET ownerfirstname = 'John'
  WHERE ownerid = (SELECT buyerid FROM antiques WHERE item = 'Bookcase');

UPDATE antiques SET price = 500.00 WHERE item = 'Chair';

UPDATE order SET discount=discount * 1.05

UPDATE tbl1 JOIN tbl2 ON tbl1.ID = tbl2.ID
  SET tbl1.col1 = tbl1.col1 + 1
  WHERE tbl2.status='Active'

UPDATE tbl SET names = REPLACE(names, 'aaa', 'zzz')

UPDATE products_categories AS pc
  INNER JOIN products AS p ON pc.prod_id = p.id
  SET pc.prod_sequential_id = p.sequential_id

UPDATE table_name SET col_name =
  REPLACE(col_name, 'host.domain.com', 'host2.domain.com')
UPDATE posts SET deleted=True
  ORDER BY date LIMIT 1

使用 ORDER BY,您可以在更新行之前对它们进行排序,并且只更新给定数量的行 (LIMIT)。

目前无法在对同一表执行子查询时更新表。例如,如果我想重置我在 SPIP 中忘记的密码

mysql> UPDATE spip_auteurs SET pass =
 (SELECT pass FROM spip_auteurs WHERE login='paul') where login='admin';
ERROR 1093 (HY000): You can't specify target table 'spip_auteurs' for update in FROM clause

待办事项:[1] 描述了一种我无法在 MySQL 4.1 中使用的解决方法。目前,解决方法是不使用 2 个子查询,可能需要使用事务。

性能提示

  • UPDATE 的速度取决于更新了多少索引。
  • 如果您更新使用动态格式的 MyISAM 表,如果您使行变大,它们可能会被拆分为多个部分。这会导致读取开销。因此,如果您的应用程序经常执行此操作,您可能需要定期运行 OPTIMIZE TABLE 语句。
  • 在 LOCKed 表上一起执行许多 UPDATE 比单独执行它们要快。

REPLACE 的工作原理与 INSERT 完全相同,区别在于,如果表中的一条旧记录对于 PRIMARY KEY 或 UNIQUE 索引具有与新记录相同的值,则在插入新记录之前会删除旧记录。

使用 IGNORE,无效值将调整为最接近的值并插入;会生成警告,但语句不会中止。

在 MySQL 4.0.1 之前,INSERT ... SELECT 隐式地以 IGNORE 模式运行。从 MySQL 4.0.1 开始,请显式指定 IGNORE 以忽略会导致重复键冲突的记录。

DELETE [QUICK] FROM table1
TRUNCATE table1
  • 如果您不使用 WHERE 子句与 DELETE 一起使用,所有记录都将被删除。
  • 它在大型表中可能非常慢,尤其是在表具有许多索引的情况下。
  • 如果表具有许多索引,您可以增加缓存的大小以尝试使 DELETE 速度更快 (key_buffer_size 变量)。
  • 对于索引的 MyISAM 表,在某些情况下,如果您指定 QUICK 关键字 (DELETE QUICK FROM ...),则 DELETE 速度更快。这仅适用于 DELETEed 索引值将被重复使用的情况。
  • TRUNCATE 会通过 DROP 和重新 CREATE 表来快速删除所有行(并非所有存储引擎都支持此操作)。
  • TRUNCATE 不是事务安全的,也不是锁安全的。
  • DELETE 会告诉您删除了多少行,但 TRUNCATE 不会。
  • 在删除了许多行(约 30%)之后,OPTIMIZE TABLE 命令应该会使下一个语句更快。
DELETE FROM `antiques`
  WHERE item = 'Ottoman'
  ORDER BY `id`
  LIMIT 1

您可以在删除行之前对它们进行排序,然后只删除给定数量的行。

表操作

[编辑 | 编辑源代码]

创建表

[编辑 | 编辑源代码]

创建表的语法是:Create table tablename (FieldName1 DataType,
FieldName2 DataType)

"select" 查询返回的行可以保存为一个新表。数据类型将与旧表相同。例如,CREATE TABLE LearnHindi
select english.tag, english.Inenglish as English, hindi.Inhindi as Hindi
FROM English, Hindi
WHERE english.tag = hindi.tag

更改表

[编辑 | 编辑源代码]

ALTER TABLE 命令可用于在您想要添加/删除/修改列和/或索引时使用;或者,它可用于更改其他表属性。

添加列

ALTER TABLE awards
ADD COLUMN AwardCode int(2)

修改列

ALTER TABLE awards
CHANGE COLUMN AwardCode VARCHAR(2) NOT NULL
ALTER TABLE awards
MODIFY COLUMN AwardCode VARCHAR(2) NOT NULL

删除列

ALTER TABLE awards
DROP COLUMN AwardCode

重新排序表中的记录

ALTER TABLE awards ORDER BY id

(此操作仅受某些存储引擎支持;它可能会使某些查询更快)

重命名表

[编辑 | 编辑源代码]

要重命名表,您必须对旧表名(或所有表)具有 ALTER 和 DROP 权限,以及对新表名(或所有表)具有 CREATE 和 INSERT 权限。

您可以使用 ALTER TABLE 来重命名表

RENAME TABLE `old_name` TO `new_name`

您可以使用单个命令重命名多个表

RENAME TABLE `old1` TO `new1`, `old2` TO `new2`, ...

RENAME 是一个快捷方式。您也可以使用 ALTER TABLE 语句

ALTER TABLE `old` RENAME `new`

使用 ALTER TABLE,您每个语句只能重命名一个表,但它是重命名临时表的唯一方法。

删除表

[编辑 | 编辑源代码]
DROP TABLE `awards`

将完全删除表及其包含的所有记录。

您也可以使用单个语句删除多个表

DROP TABLE `table1`, `table2`, ...

有一些可选的关键字

DROP TEMPORARY TABLE `table`;
DROP TABLE `table` IF EXISTS;

必须指定 TEMPORARY,才能删除临时表。IF EXISTS 告诉服务器,如果表不存在,则不应引发错误。

使用 NULL

[编辑 | 编辑源代码]

Null 是 SQL 中的一种特殊逻辑值。大多数编程语言具有 2 个逻辑值:True 和 False。SQL 也具有 NULL,表示“未知”。可以设置 NULL 值。

NULL 是一个非值,因此它可以分配给 TEXT 列、INTEGER 列或任何其他数据类型。只有在列被声明为 NOT NULL 时,它才不能包含 NULL(请参见 ALTER TABLE)。

INSERT into Singer
       (F_Name, L_Name, Birth_place, Language) 
       values 
       ("", "Homer", NULL, "Greek"),
       ("", "Sting", NULL, "English"),
       ("Jonny", "Five", NULL, "Binary");

不要引用 NULL。如果您引用 Null,那么您就是命名为 NULL 的人。由于某种奇怪的原因,NULL 在 Varchar 字段中的 Windows XP 上不会在视觉上显示,但在 Fedora 版本中会显示,因此 mysql 的版本可能会产生不同的输出。在这里,我们将 Sting 和 Homer 的名字设置为零长度字符串“”,因为我们知道他们没有名字,但我们知道我们不知道他们的出生地的位置。要检查 NULL,请使用

SELECT * from Singer WHERE Birth_place IS NULL;
or
SELECT * from Singer WHERE Birth_place IS NOT NULL;
or
SELECT * from Singer WHERE isNull(Birth_place)

请记住,COUNT 从不计算 NULL。

select count(Birth_place) from Singer;
0
and sum(NULL) gives a NULL answer.

如果至少有一个比较项是 NULL,则正常操作(比较、表达式等)将返回 NULL

SELECT (NULL=NULL) OR (NULL<>NULL) OR (NOT NULL) OR (1<NULL) OR (1>NULL) OR (1 + NULL) OR (1 LIKE NULL)

因为括号中的所有表达式都返回 NULL。这绝对合乎逻辑:如果您不知道 NULL 所表示的值,那么您不知道它是否 =1 或 <>1。请注意,即使 (NULL=NULL and (NOT NULL) 返回 NULL。

处理 NULL

[编辑 | 编辑源代码]

函数 'COALESCE' 可以简化对空值的处理。例如,要通过将空值视为零来避免显示空值,您可以键入

SELECT COALESCE(colname,0) from table where COALESCE(colname,0) > 1;

在日期字段中,将 NULL 视为当前日期

ORDER BY (COALESCE(TO_DAYS(date),TO_DAYS(CURDATE()))-TO_DAYS(CURDATE()))
EXP(SUM(LOG(COALESCE(*the field you want to multiply*,1))) 

coalesce() 函数是为了防止尝试计算空值的对数,它可能是可选的,具体取决于您的情况。

SELECT t4.gene_name, COALESCE(g2d.score,0), 
COALESCE(dgp.score,0), COALESCE(pocus.score,0) 
FROM t4 
LEFT JOIN g2d ON t4.gene_name=g2d.gene_name 
LEFT JOIN dgp ON t4.gene_name=dgp.gene_name 
LEFT JOIN pocus ON t4.gene_name=pocus.gene_name;

在您的 SELECT 语句中使用 IFNULL() 是为了将 NULL 设为任何您想要的 value。

IFNULL(expr1,expr2)

如果 expr1 不是 NULL,IFNULL() 将返回 expr1,否则返回 expr2。

IFNULL() 返回一个数字或字符串值,具体取决于它使用的上下文。

mysql> SELECT IFNULL(1,0);
-> 1
mysql> SELECT IFNULL(NULL,10);
-> 10
mysql> SELECT IFNULL(1/0,10);
-> 10
mysql> SELECT IFNULL(1/0,'yes');
-> 'yes'

NULL 处理可能非常反直觉,如果您的 delete 语句中有一个错误的函数返回 null,则可能会导致问题。例如,以下查询将删除所有条目。

DELETE FROM my_table WHERE field > NULL (or function returning NULL)

如果您希望在进行 ORDER BY 时将 NULL 值显示在最后,请尝试以下操作

SELECT * FROM my_table ORDER BY ISNULL(field), field [ ASC | DESC ]

保留字

[编辑 | 编辑源代码]

困难的列名,例如 `DATE`—使用反引号。如果使用“date”作为列名,请将其用反引号 ` 括起来,如下所示

CREATE TABLE IF NOT EXISTS stocks (
  pkey int NOT NULL auto_increment,
  `date` date,
  ticker varchar(5),
  open decimal (9,2),
  high decimal (9,2),
  low decimal (9,2),
  close decimal (9,2),
  volume int,
  timeEnter timestamp(14),
  PRIMARY KEY (pkey)
);

数据类型

[编辑 | 编辑源代码]

VARCHAR 是 CHARACTER VARYING 的简写。'n' 表示最大列长度(最多 255 个字符)char(n) 与 varchar(n) 类似,唯一的区别是 char 将在数据库中占用固定长度的空间,而 varchar 将需要空间来存储实际文本。例如,VARCHAR(10) 列可以保存最大长度为 10 个字符的字符串。实际所需的存储空间是字符串的长度 (L),加上 1 个字节来记录字符串的长度。对于字符串 'abcd',L 是 4,存储需求是 5 个字节。

一个 BLOB 或 TEXT 列,最大长度为 65,535 个字符。

指定 n 值没有任何效果。无论为 n 提供什么值,存储的最大(无符号)值为 429 crores。如果要添加负数,请在旁边添加 "signed" 关键字。

decimal(n,m) decimal(4,2) 表示最多可以保存 99.99(而不是您可能期望的 9999.99)的数字。四位数字,最后两位保留为小数。

在三种类型 DATETIME、DATE 和 TIMESTAMP 中,当您只需要日期值,而不需要时间部分时,使用 DATE 类型。MySQL 以 'YYYY-MM-DD' 格式检索和显示 DATE 值。当您需要包含日期和时间信息的价值时,使用 DATETIME 类型。DATETIME 和 TIMESTAMP 之间的区别在于 TIMESTAMP 范围限制在 1970-2037 年(见下文)。

TIME 可用于仅存储一天中的时间(HH:MM:SS),而无需日期。它也可以用于表示时间间隔(例如:-02:00:00 表示“过去两小时”)。范围:'-838:59:59' => '838:59:59'。

YEAR 可用于仅存储年份数字。

如果操纵日期,则必须指定实际日期,而不仅仅是时间 - 也就是说,MySQL 不会自动使用今天作为当前日期。相反,MySQL 甚至会将 HH:MM:SS 时间解释为 YY:MM:DD 值,这可能是无效的。

以下示例显示了基于 Unix 的时间戳的精确日期范围,该时间戳从 Unix 纪元开始,并在 通常的限制(2038)之前的第一个新年之前结束。

mysql> SET time_zone = '+00:00'; -- GMT
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT FROM_UNIXTIME(-1);
+-------------------+
| FROM_UNIXTIME(-1) |
+-------------------+
| NULL              |
+-------------------+
1 row in set (0.00 sec)

mysql> SELECT FROM_UNIXTIME(0); -- "Epoch"
+---------------------+
| FROM_UNIXTIME(0)    |
+---------------------+
| 1970-01-01 00:00:00 |
+---------------------+
1 row in set (0.00 sec)

mysql> SELECT FROM_UNIXTIME(2145916799);
+---------------------------+
| FROM_UNIXTIME(2145916799) |
+---------------------------+
| 2037-12-31 23:59:59       |
+---------------------------+
1 row in set (0.00 sec)

mysql> SELECT FROM_UNIXTIME(2145916800);
+---------------------------+
| FROM_UNIXTIME(2145916800) |
+---------------------------+
| NULL                      |
+---------------------------+
1 row in set (0.00 sec)

集合和枚举

[编辑 | 编辑源代码]

SET 数据类型可以保存来自创建表时指定的预定义字符串列表的任意数量的字符串。SET 数据类型类似于 ENUM 数据类型,因为它们都使用预定义的字符串集,但 ENUM 数据类型限制您使用预定义字符串集中单个成员,而 SET 数据类型允许您将预定义字符串集中所有成员中的任何成员一起存储,从没有到全部。

运算符

[编辑 | 编辑源代码]

MySQL 使用一些标准 SQL 运算符和一些非标准运算符。它们可以用于编写涉及常量值、变量、字段中包含的值和/或其他表达式的表达式。

优先级

[编辑 | 编辑源代码]

运算符优先级

[编辑 | 编辑源代码]

运算符优先级表

INTERVAL
BINARY, COLLATE
!
- (unary minus), ~ (unary bit inversion)
^
*, /, DIV, %, MOD
-, +
<<, >>
&
|
=, <=>, >=, >, <=, <, <>, !=, IS, LIKE, REGEXP, IN
BETWEEN, CASE, WHEN, THEN, ELSE
NOT
&&, AND
XOR
||, OR
:=

修饰符

  • PIPES_AS_CONCAT - 如果启用了此 SQL 模式,则 || 优先于 ^,但 - 和 ~ 优先于 ||。
  • HIGH_NOT_PRECEDENCE - 如果启用了此 SQL 模式,则 NOT 与 ! 具有相同的优先级。

使用括号

[编辑 | 编辑源代码]

可以使用括号强制 MySQL 在不依赖运算符优先级的情况下,先评估一个子表达式,然后再评估另一个子表达式。

SELECT (1 + 1) * 5 -- returns 10

即使括号不会影响优先级,也可以使用括号使表达式对人类更易读。

SELECT 1 + (2 * 5) -- the same as 1 + 2 * 5

赋值运算符

[编辑 | 编辑源代码]

可以使用 = 运算符将值赋给列。

UPDATE `myTable` SET `uselessField`=0

当您要将值赋给变量时,必须使用 := 运算符,因为使用 = 会造成歧义(是赋值还是比较?)。

SELECT @myvar := 1

也可以使用 SELECT INTO 将值赋给一个或多个变量。

比较运算符

[编辑 | 编辑源代码]

如果要检查两个值是否相等,必须使用 = 运算符。

SELECT True = True—returns 1
SELECT True = False—returns 0

如果要检查两个值是否不同,可以使用<> 或 != 运算符,它们的含义相同。

SELECT True <> False—returns 1
SELECT True != True—returns 0

<> 在 = 返回 0 的地方返回 1,反之亦然。

IS 和 NULL 安全比较

[编辑 | 编辑源代码]

当将 NULL 值与非 NULL 值进行比较时,您将获得 NULL。如果要检查某个值是否为 null,可以使用 IS。

SELECT (NULL IS NULL) -- returns 1
SELECT (1 IS NULL) -- returns 0
SELECT (True IS True) -- returns an error!

可以检查某个值是否为非 NULL。

SELECT (True IS NOT NULL) -- returns 1

还有一个相等运算符,它将 NULL 视为正常值,因此如果两个值都为 NULL,则返回 1(非 NULL),如果其中一个值为 NULL,则返回 0(非 NULL)。

SELECT col1 <=> col2 FROM myTable

没有 NULL 安全的不等运算符,但可以键入以下内容。

SELECT NOT (col1 <=> col2) FROM myTable

IS 和布尔比较

[编辑 | 编辑源代码]

IS 和 IS NOT 也可用于布尔比较。可以将它们与保留字 TRUE、FALSE 和 UNKNOWN(它只是 NULL 的同义词)一起使用。

SELECT 1 IS TRUE—returns 1
SELECT 1 IS NOT TRUE—returns 0
SELECT 1 IS FALSE—returns 0
SELECT (NULL IS NOT FALSE) -- returns 1: unknown is not false
SELECT (NULL IS UNKNOWN) -- returns 1
SELECT (NULL IS NOT UNKNOWN) -- returns 0

大于、小于...

[编辑 | 编辑源代码]

可以检查某个值是否大于另一个值。

SELECT 100 > 0 -- returns 1
SELECT 4 > 5 -- return 0

也可以检查某个值是否小于另一个值。

SELECT 1 < 2 -- returns 1
SELECT 2 < 2 -- returns 0

这种比较也适用于 TEXT 值。

SELECT 'a' < 'b' -- returns 1

通常,TEXT 比较使用字母顺序。但是,确切规则由所使用的校对定义。校对定义了给定字符集的排序规则。例如,一个校对可能区分大小写,而另一个校对可能不区分大小写。

可以检查某个值是否等于或大于另一个值。例如,以下查询含义相同。

SELECT `a` >= `b` FROM `myTable`
SELECT NOT (`a` < `b`) FROM `myTable`

类似地,可以检查某个值是否小于或等于另一个值。

SELECT `a` <= `b` FROM `myTable`

如果要检查某个值是否包含在给定范围内,可以使用 BETWEEN ... AND ... 运算符。AND 没有其通常的含义。示例。

SELECT 20 BETWEEN 10 AND 100—returns 1

BETWEEN 后的值和 AND 后的值都包含在范围内。

也可以使用 NOT BETWEEN 检查某个值是否不包含在范围内。

SELECT 8 NOT BETWEEN 5 AND 10—returns 0

可以使用 IN 运算符检查某个值是否包含在值列表中。

SELECT 5 IN (5, 6, 7) -- returns 1
SELECT 1 IN (5, 6, 7) -- returns 0

不应在列表中同时包含数字和字符串,否则结果可能不可预测。如果存在数字,则应将它们引用。

SELECT 4 IN ('a', 'z', '5')

IN 运算符中包含的值数量没有理论限制。

也可以使用 NOT IN。

SELECT 1 NOT IN (1, 2, 3) -- returns 0

逻辑运算符

[edit | edit source]

MySQL 布尔逻辑

[edit | edit source]

MySQL 没有真正的 BOOLEAN 数据类型。

FALSE 是 0 的同义词。在布尔上下文中,空字符串被视为 FALSE。

TRUE 是 1 的同义词。在布尔上下文中,所有非 NULL 和非 FALSE 数据都被视为 TRUE。

UNKNOWN 是 NULL 的同义词。特殊日期 0/0/0 是 NULL。

NOT 是唯一一个只有一个操作数的操作符。如果操作数为 TRUE,它返回 0;如果操作数为 FALSE,它返回 1;如果操作数为 NULL,它返回 NULL。

SELECT NOT 1 -- returns 0
SELECT NOT FALSE—returns 1
SELECT NOT NULL—returns NULL
SELECT NOT UNKNOWN—returns NULL

! 是 NOT 的同义词。

SELECT !1

如果两个操作数都为 TRUE,AND 返回 1,否则返回 0;如果其中一个操作数为 NULL,则返回 NULL。

SELECT 1 AND 1 -- returns 1
SELECT 1 AND  -- return 0
SELECT  AND NULL—returns NULL

&& 是 AND 的同义词。

SELECT 1 && 1

如果至少一个操作数为 TRUE,OR 返回 TRUE,否则返回 FALSE;如果其中一个操作数为 NULL,则返回 NULL。

SELECT TRUE OR FALSE—returns 1
SELECT 1 OR 1 -- returns 1
SELECT FALSE OR FALSE—returns 0
SELECT NULL OR TRUE—returns NULL

|| 是 OR 的同义词。

SELECT 1 || 0

XOR(异或)如果只有一个操作数为 TRUE 而另一个操作数为 FALSE,则返回 1;如果两个操作数都为 TRUE 或都为 FALSE,则返回 0;如果其中一个操作数为 NULL,则返回 NULL。

SELECT 1 XOR 0 -- returns 1
SELECT FALSE XOR TRUE—returns 1
SELECT 1 XOR TRUE—returns 0
SELECT 0 XOR FALSE—returns 0
SELECT NULL XOR 1 -- returns NULL

同义词

[edit | edit source]

AND 可以写成 &&
OR 可以写成 ||
NOT 可以写成 !

只有 NOT(通常)与它的同义词具有不同的优先级。有关详细信息,请参阅运算符优先级。

算术运算符

[edit | edit source]

MySQL 支持执行所有基本算术运算的操作数。

如果需要,可以使用 '+' 键入正值。

SELECT +1 -- return 1

可以使用 '-' 键入负值。- 是一个反转操作符。

SELECT -1 -- returns -1
SELECT -+1 -- returns -1
SELECT—1 -- returns 1

可以使用 '+' 进行求和。

SELECT 1 + 1 -- returns 2

可以使用 '-' 进行减法。

SELECT True - 1 -- returns 0

可以使用 '*' 乘以一个数字。

SELECT 1 * 1 -- returns 1

可以使用 '/' 进行除法。返回一个 FLOAT 数字。

SELECT 10 / 2 -- returns 5.0000
SELECT 1 / 1 -- returns 1.0000
SELECT 1 / 0 -- returns NULL (not an error)

可以使用 DIV 进行整数除法。结果数字为 INTEGER。没有余数。这在 MySQL 4.1 中添加。

SELECT 10 DIV 3 -- returns 3

可以使用 '%' 或 MOD 获取除法的余数。

SELECT 10 MOD 3 -- returns 1

使用 + 转换数据

[edit | edit source]

可以通过以下方式将 INTEGER 转换为 FLOAT。

SELECT 1 + 0.0 -- returns 1.0
SELECT 1 + 0.000—returns 1.000
SELECT TRUE + 0.000—returns 1.000

不能通过添加 0.0 来将字符串转换为 FLOAT 值,但可以将其转换为 INTEGER。

SELECT '1' + 0 -- returns 1
SELECT '1' + FALSE—returns 1
SELECT '' + ''—returns 0

文本运算符

[edit | edit source]

MySQL 中没有连接运算符。

算术运算符将值转换为数字,然后执行算术运算,因此不能使用 + 连接字符串。

可以使用 CONCAT() 函数代替。

LIKE 运算符可用于检查字符串是否与模式匹配。一个简单的例子

SELECT * FROM articles WHERE title LIKE 'hello world'

模式匹配通常不区分大小写。有两个例外:

  • 当对已使用 BINARY 标志(参见 CREATE TABLE)声明的列执行 LIKE 比较时;
  • 当表达式包含 BINARY 子句时。
SELECT * 'test' LIKE BINARY 'TEST' -- returns 0

对于 LIKE 比较,可以使用两个特殊字符:

  • _ 表示“任何字符”(但必须是 1 个字符,不能是 0 个或 2 个)。
  • % 表示“任何字符序列”(甚至是 0 个字符或 1000 个字符)。

请注意,“\” 也会转义引号('),这种行为无法通过 ESCAPE 子句更改。此外,转义字符不会转义自身。

LIKE 的常见用法

  • 查找以“hello”一词开头的标题
SELECT * FROM articles WHERE title LIKE 'hello%'
  • 查找以“world”一词结尾的标题
SELECT * FROM articles WHERE title LIKE '%world'
  • 查找包含“gnu”一词的标题
SELECT * FROM articles WHERE title LIKE '%gnu%'

这些特殊字符可能包含在模式本身中:例如,您可能需要搜索“_”字符。在这种情况下,您需要“转义”该字符。

SELECT * FROM articles WHERE title LIKE '\_%' -- titles starting with _
SELECT * FROM articles WHERE title LIKE '\%%' -- titles starting with %

有时,您可能希望使用与“\”不同的转义字符。例如,您可以使用“/”。

SELECT * FROM articles WHERE title LIKE '/_%' ESCAPE '/'

使用 = 运算符时,会忽略尾随空格。使用 LIKE 时,会考虑尾随空格。

SELECT 'word' = 'word ' -- returns 1
SELECT 'word' LIKE 'word ' -- returns 0

LIKE 也适用于数字。

SELECT 123 LIKE '%2%' -- returns 1

如果要检查模式是否不匹配,可以使用 NOT LIKE。

SELECT 'a' NOT LIKE 'b' -- returns 1

SOUNDS LIKE

[edit | edit source]

可以使用 SOUNDS LIKE 检查两个文本值的发音是否相同。SOUNDS LIKE 使用 SOUNDEX 算法,该算法基于英语规则,非常近似(但简单且因此速度很快)。

SELECT `word1` SOUNDS LIKE `word2` FROM `wordList`—short form
SELECT SOUNDEX(`word1`) = SOUNDEX(`word2`) FROM `wordList`—long form

SOUNDS LIKE 是 MySQL 对 SQL 的特定扩展。它是在 MySQL 4.1 中添加的。

正则表达式

[edit | edit source]

可以使用 REGEXP 使用正则表达式检查字符串是否与模式匹配。

SELECT 'string' REGEXP 'pattern'

可以使用 RLIKE 作为 REGEXP 的同义词。

位运算符

[edit | edit source]

位非

SELECT ~0 -- returns 18446744073709551615
SELECT ~1 -- returns 18446744073709551614

位与

SELECT 1 & 1 -- returns 1
SELECT 1 & 3 -- returns 1
SELECT 2 & 3 -- returns 2

位或

SELECT 1 | 0 -- returns 1
SELECT 3 | 0 -- returns 3
SELECT 4 | 2 -- returns 6

位异或

SELECT 1 ^ 0 -- returns 1
SELECT 1 ^ 1 -- returns 0
SELECT 3 ^ 1 -- returns 2

左移

SELECT 1 << 2 -- returns 4

右移

SELECT 1 >> 2 -- 0

导入/导出

[edit | edit source]

除了 mysqldump(参见 MySQL/Administration)之外,还可以使用以下命令导出原始数据:

SELECT ... FROM table INTO OUTFILE 'path'
LOAD DATA INFILE 'path' INTO TABLE table

示例

SELECT * FROM destinataire INTO OUTFILE '/tmp/test' WHERE id IN (41, 141, 260, 317, 735, 888, 1207, 2211);
# in another database/computer/etc.:
LOAD DATA INFILE '/tmp/test' INTO TABLE destinataire;

请注意,MySQL 守护进程本身会写入文件,而不是您运行 MySQL 客户端的用户。该文件将存储在服务器上,而不是您的主机上。此外,服务器将需要对您指定的路径具有写入访问权限(通常,服务器_不能_写入您的主目录,例如)。因此,我们在示例中(不安全地)使用了 /tmp

练习

[edit | edit source]

练习 SELECT

[edit | edit source]

表 `list`

[edit | edit source]
ID Name Surname FlatHave FlatWant
1 Shantanu Oak Goregaon 
2 Shantanu Oak Andheri  
3 Shantanu Oak   Dadar
4 Ram Joshi   Goregaon
5 Shyam Sharma   Andheri
6 Ram 奈克 西翁 
7 萨米尔 沙阿 帕尔勒  
8 Ram Joshi Dadar  
9 Shyam Sharma Dadar  

练习 I - 问题

[编辑 | 编辑源代码]
  • 谁在“戈雷冈”有一套公寓,谁想买一套?
  • 谁在“帕尔勒”有一套公寓,谁想买一套?
  • “尚塔努·奥克”在哪拥有公寓,他想去哪里买一套?
  • 迄今为止记录了多少条目?
  • 有多少公寓出售?
  • 我们的客户姓名是什么?
  • 我们有多少客户?
  • 列出姓名以“S”开头的客户?
  • 按字母顺序重新排列列表。

练习 I - 答案

[编辑 | 编辑源代码]
  • select * from list where FlatHave = "Goregaon" and FlatWant = "Goregaon"
  • select * from list where FlatHave = "Parle" and FlatWant = "Parle"
  • select FlatHave,FlatWant from list where Name = "Shantanu" and Surname = "Oak"
  • select count(*) from list
  • select count(FlatHave) from list where FlatHave is not null
  • select distinct Name, Surname from list
  • select count(distinct Name, surname) from list
  • select * from list where Name like "S%"
  • select Surname, Name, FlatHave, FlatWant from list order by Name

表 `grades`

[编辑 | 编辑源代码]
ID Name 数学 物理 文学
1 约翰 68 37 54
2 吉姆 96 89 92
3 比尔 65 12 57
4 杰里 69 25 82

练习 II - 问题

[编辑 | 编辑源代码]
  • 所有数学成绩超过 90 分的学生列表

  • 所有科目成绩都超过 85 分的学生列表?
  • 声明结果:打印所有学生的成绩,带有结果列。
  • 找出所有学生的总分。
  • 每个科目的班级平均分是多少?
  • 数学最低分是多少?
  • 数学最高分是多少?
  • 谁的数学成绩最高?

练习 II - 答案

[编辑 | 编辑源代码]

注意:许多问题有多个正确答案。

  • SELECT * FROM grades WHERE math > 90
  • SELECT name FROM grades WHERE math > 85 AND physics > 85 AND literature > 85
  • SELECT *, IF( (math <= 35 OR physics <= 35 OR literature <= 35), 'fail', 'pass') AS result FROM grades ORDER BY result DESC
  • SELECT name, math+physics+literature FROM grades
  • SELECT AVG(math), AVG(physics), AVG(literature) FROM grades
  • SELECT MIN(math) FROM grades
  • SELECT MAX(math) FROM grades
  • SELECT * FROM students ORDER BY math DESC LIMIT 1

查找重复项

[编辑 | 编辑源代码]
SELECT Vendor, ID, Count(1) as dupes
FROM table_name
GROUP BY Vendor, ID HAVING Count(1) >1
SELECT txt, COUNT(*)
FROM dupes
GROUP BY txt HAVING COUNT(*) > 1;
SELECT id, COUNT( id ) AS cnt, 
FROM myTable
GROUP BY id HAVING cnt > 1

删除重复条目。

[编辑 | 编辑源代码]

假设以下表格和数据。

CREATE TABLE IF NOT EXISTS dupTest
(pkey int(11) NOT NULL auto_increment,
an int, b int, c int, timeEnter timestamp(14),
PRIMARY KEY (pkey));

insert into dupTest (a,b,c) values (1,2,3),(1,2,3),
(1,5,4),(1,6,4);

注意,前两行在列 a 和 b 中包含重复项。它包含其他重复项;但是,保留其他重复项。

ALTER IGNORE TABLE dupTest ADD UNIQUE INDEX(a,b);

华夏公益教科书