📄 manual_tutorial.html
字号:
+---------+
| article |
+---------+
| 4 |
+---------+
</pre>
<h3><a NAME="example-Maximum-row" HREF="manual_toc.html#example-Maximum-row">8.3.2
拥有某个列的最大值的行</a></h3>
<p>“找出最贵的文章的编号、商人和价格”</p>
<p>在ANSI-SQL中这很容易用一个子查询做到: </p>
<pre>SELECT article, dealer, price
FROM shop
WHERE price=(SELECT MAX(price) FROM shop)
</pre>
<p>在<strong>MySQL</strong>中(还没有子查询)就用2步做到:
<ol>
<li>用一个<code>SELECT</code>语句从表中得到最大值。 </li>
<li>使用该值编出实际的查询: <pre>SELECT article, dealer, price
FROM shop
WHERE price=19.95
</pre>
</li>
</ol>
<p>另一个解决方案是按价格降序排序所有行并用<strong>MySQL</strong>特定<code>LIMIT</code>子句只得到的第一行:
</p>
<pre>SELECT article, dealer, price
FROM shop
ORDER BY price DESC
LIMIT 1
</pre>
<p><strong>注意</strong>:如果有多个最贵的文章( 例如每个19.95)<code>,LIMIT</code>解决方案仅仅显示他们之一!
</p>
<h3><a NAME="example-Maximum-column-group" HREF="manual_toc.html#example-Maximum-column-group">8.3.3
列的最大值:按组:只有值</a></h3>
<p>“每篇文章的最高的价格是什么?” </p>
<pre>SELECT article, MAX(price) AS price
FROM shop
GROUP BY article
+---------+-------+
| article | price |
+---------+-------+
| 0001 | 3.99 |
| 0002 | 10.99 |
| 0003 | 1.69 |
| 0004 | 19.95 |
+---------+-------+
</pre>
<h3><a NAME="example-Maximum-column-group-row" HREF="manual_toc.html#example-Maximum-column-group-row">8.3.4
拥有某个字段的组间最大值的行</a></h3>
<p>“对每篇文章,找出有最贵的价格的交易者。” </p>
<p>在<code>ANSI SQL</code>中,我可以用这样一个子查询做到: </p>
<pre>SELECT article, dealer, price
FROM shop s1
WHERE price=(SELECT MAX(s2.price)
FROM shop s2
WHERE s1.article = s2.article)
</pre>
<p>在<strong>MySQL</strong>中,最好是分几步做到:
<ol>
<li>得到一个表(文章,maxprice)。见<a HREF="manual_Tutorial.html#example-Maximum-column-group-row">8.3.4
拥有某个域的组间最大值的行</a>。 </li>
<li>对每篇文章,得到对应于存储最大价格的行。 </li>
</ol>
<p>这可以很容易用一个临时表做到: </p>
<pre>CREATE TEMPORARY TABLE tmp (
article INT(4) UNSIGNED ZEROFILL DEFAULT '0000' NOT NULL,
price DOUBLE(16,2) DEFAULT '0.00' NOT NULL);
LOCK TABLES article read;
INSERT INTO tmp SELECT article, MAX(price) FROM shop GROUP BY article;
SELECT article, dealer, price FROM shop, tmp
WHERE shop.article=tmp.articel AND shop.price=tmp.price;
UNLOCK TABLES;
DROP TABLE tmp;
</pre>
<p>如果你不使用一个<code>TEMPORARY</code>表,你也必须锁定“tmp”表。 </p>
<p>“它能一个单个查询做到吗?” </p>
<p>是的,但是只有使用我称之为“MAX-CONCAT诡计”的一个相当低效的诡计:
</p>
<pre>SELECT article,
SUBSTRING( MAX( CONCAT(LPAD(price,6,'0'),dealer) ), 7) AS dealer,
0.00+LEFT( MAX( CONCAT(LPAD(price,6,'0'),dealer) ), 6) AS price
FROM shop
GROUP BY article;
+---------+--------+-------+
| article | dealer | price |
+---------+--------+-------+
| 0001 | B | 3.99 |
| 0002 | A | 10.99 |
| 0003 | C | 1.69 |
| 0004 | D | 19.95 |
+---------+--------+-------+
</pre>
<p>最后例子当然能通过在客户程序中分割连结的列使它更有效一点。
</p>
<h3><a NAME="example-Foreign_keys" HREF="manual_toc.html#example-Foreign_keys">8.3.5
使用外键</a></h3>
<p>不需要外键联结2个表。 </p>
<p><code>MySQL</code>唯一不做的事情是<code>CHECK</code>以保证你使用的键确实在你正在引用表中存在,并且它不自动从有一个外键定义的表中删除行。如果你象平常那样使用你的键值,它将工作得很好!
</p>
<pre>CREATE TABLE persons (
id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
name CHAR(60) NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE shirts (
id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
style ENUM('t-shirt', 'polo', 'dress') NOT NULL,
color ENUM('red', 'blue', 'orange', 'white', 'black') NOT NULL,
owner SMALLINT UNSIGNED NOT NULL REFERENCES persons,
PRIMARY KEY (id)
);
INSERT INTO persons VALUES (NULL, 'Antonio Paz');
INSERT INTO shirts VALUES
(NULL, 'polo', 'blue', LAST_INSERT_ID()),
(NULL, 'dress', 'white', LAST_INSERT_ID()),
(NULL, 't-shirt', 'blue', LAST_INSERT_ID());
INSERT INTO persons VALUES (NULL, 'Lilliana Angelovska');
INSERT INTO shirts VALUES
(NULL, 'dress', 'orange', LAST_INSERT_ID()),
(NULL, 'polo', 'red', LAST_INSERT_ID()),
(NULL, 'dress', 'blue', LAST_INSERT_ID()),
(NULL, 't-shirt', 'white', LAST_INSERT_ID());
SELECT * FROM persons;
+----+---------------------+
| id | name |
+----+---------------------+
| 1 | Antonio Paz |
| 2 | Lilliana Angelovska |
+----+---------------------+
SELECT * FROM shirts;
+----+---------+--------+-------+
| id | style | color | owner |
+----+---------+--------+-------+
| 1 | polo | blue | 1 |
| 2 | dress | white | 1 |
| 3 | t-shirt | blue | 1 |
| 4 | dress | orange | 2 |
| 5 | polo | red | 2 |
| 6 | dress | blue | 2 |
| 7 | t-shirt | white | 2 |
+----+---------+--------+-------+
SELECT s.* FROM persons p, shirts s
WHERE p.name LIKE 'Lilliana%'
AND s.owner = p.id
AND s.color &lt;&gt; 'white';
+----+-------+--------+-------+
| id | style | color | owner |
+----+-------+--------+-------+
| 4 | dress | orange | 2 |
| 5 | polo | red | 2 |
| 6 | dress | blue | 2 |
+----+-------+--------+-------+
</pre>
<h2><a NAME="Database_use" HREF="manual_toc.html#Database_use">8.4
创造并使用一个数据库</a></h2>
<p>既然你知道怎样输入命令,现在是存取一个数据库的时候了。 </p>
<p>假定在你的家(你的“动物园”)中有很多宠物,并且你想追踪关于他们各种各样类型的信息。你可以通过创建表来保存你的数据并根据所需要的信息装载他们做到,然后你可以通过从表中检索数据来回答关于你的动物不同种类的问题。本节显示如何做到所有这些事情:
<ul>
<li>怎样创建一个数据库</li>
<li>怎样创建一个数据库表</li>
<li>怎样装载数据到数据库表</li>
<li>怎样以各种方法从表中检索数据</li>
<li>怎样使用多个表</li>
</ul>
<p>动物园数据库将会是简单的(故意的),但是不难把它想象成可能用到相似类型数据库的真实世界情况。例如,这样的一个数据库能被一个农夫用来追踪家畜,或由一个兽医追踪病畜记录。
</p>
<p>使用<code>SHOW</code>语句找出在服务器上当前存在什么数据库: </p>
<pre>mysql> SHOW DATABASES;
+----------+
| Database |
+----------+
| mysql |
| test |
| tmp |
+----------+
</pre>
<p>数据库列表可能在你的机器上是不同的,但是<code>mysql</code>和<code>test</code>数据库很可能的在其间。<code>mysql</code>是必需的,因为它描述用户存取权限,<code>test</code>数据库经常作为一个工作区提供给用户试试身手。
</p>
<p>如果<code>test</code>数据库存在,尝试存取它: </p>
<pre>mysql> USE test
Database changed
</pre>
<p>注意,<code>USE</code>,类似<code>QUIT</code>,不需要一个分号。(如果你喜欢,你可以用一个分号终止这样的语句;这无碍)<code>USE</code>语句在使用上也有另外一个特殊的地方:它必须在一个单行上给出。
</p>
<p>你可列在后面的例子中使用<code>test</code>数据库(如果你能访问它),但是你在该数据库创建的任何东西可以被与访问它的其他人删除,为了这个原因,你可能应该询问你的<strong>MySQL</strong>管理员许可你自己使用的一个数据库。假定你想要调用你的<code>menagerie</code>,管理员需要执行一个这样的命令:
</p>
<pre>mysql> GRANT ALL ON menagerie.* TO your_mysql_name;
</pre>
<p>这里<code>your_mysql_name</code>是分配给你的<strong>MySQL</strong>用户名。 </p>
<h3><a NAME="Creating_database" HREF="manual_toc.html#Creating_database">8.4.1
创建并选用一个数据库</a></h3>
<p>如果在设置你的权限时,管理员为你创建了数据库,你可以开始使用它。否则,你需要自己创建它:
</p>
<pre>mysql> CREATE DATABASE menagerie;
</pre>
<p>在Unix下,数据库名字是区分大小写的(不像SQL关键词),因此你必须总是以<code>menagerie</code>引用你的数据库,不是<code>Menagerie</code>、<code>MENAGERIE</code>或一些其他变种。对表名也是这样的。(在Windows下,该限制不适用,尽管你必须在一个给定的查询中使用同样的大小写来引用数据库和表。)</p>
<p>创建了一个数据库并不选定以使用它,你必须明确地做这件事。为了使<code>menagerie</code>称为当前的数据库,使用这个命令:
</p>
<pre>mysql> USE menagerie
Database changed
</pre>
<p>你的数据库只需要创建一次,但是你必须在每次启动一个<code>mysql</code>会话时为使用而选择它。你可以由发出上面一个<code>USE</code>语句做到。另外,当你调用时<code>mysql</code>,你可在命令行上选择数据库,就在你可能需要提供的任何连接参数之后指定其名字。例如:
</p>
<pre>shell> mysql -h host -u user -p menagerie
Enter password: ********
</pre>
<p>注意,<code>menagerie</code>不是你在刚才所示命令的口令。如果你想要在命令行上在<code>-p</code>选项后提供你的口令,你必须做到没有多余的空格(例如,如<code>-pmypassword</code>,不是<code>-p
mypassword</code>)。然而,不建议把你的口令放在命令行上,因为这样做把它暴露出来,能被在你的机器上登录的其他用户窥探到。
</p>
<h3><a NAME="Creating_tables" HREF="manual_toc.html#Creating_tables">8.4.2
创建一个数据库表</a></h3>
<p>创建数据库是容易的部分,但是在这时它是空的,正如<code>SHOW
TABLES</code>将告诉你: </p>
<pre>mysql> SHOW TABLES;
Empty set (0.00 sec)
</pre>
<p>较难的部分是决定你的数据库结构应该是什么:你将需要什么数据库表,和在他们中有什么样的列。
</p>
<p>你将需要一个包含你每个宠物的记录的表。它可称为<code>pet</code>表,并且它应该包含,最少,每个动物的名字。因为名字本身不是很有趣,表应该包含另外的信息。例如,如果在你豢养宠物的家庭有超过一个人,你可能想要列出每个动物的主人。你可能也想要记录例如种类和性别的一些基本的描述信息。
</p>
<p>年龄呢?那可能有趣,但是在一个数据库中存储不是一件好事情。年龄随着时间流逝而变化,这意味着你将要不断地更新你的记录。相反,
存储一个固定值例如生日比较好,那么,无论何时你需要年龄,你可以以当前日期和出生日期之间的差别来计算它。<strong>MySQL</strong>为日期运算提供了函数,因此这并不困难。存储出生日期而非年龄也有其他优点:
<ul>
<li>你可以将数据库用于这样的任务例如生成即将到来的宠物生日的提示。(如果你认为这类查询是点蠢,注意,这与在一个商务数据库来标示你不久要给它发出生日祝贺的客户的环境中是同一个问题,因为计算机帮助私人联络。)</li>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -