1 用户定义变量 的使用
可以使用MySQL用户定义的变量来存储查询结果,而无需在客户端使用临时变量。以下是一个如何使用用户定义的变量来找到价格最高和最低的商品的示例:
mysql> SELECT @min_price:=MIN(price),@max_price:=MAX(price) FROM shop;
mysql> SELECT * FROM shop WHERE price=@min_price OR price=@max_price;
+---------+--------+-------+
| article | dealer | price |
+---------+--------+-------+
| 0003 | D | 1.25 |
| 0004 | D | 19.95 |
+---------+--------+-------+
可以在MySQL中使用用户定义的变量来存储结果,而无需在客户端中使用临时变量。这可以在执行复杂的查询和操作时提供便利,尤其是在需要跨多个语句记住某个值时。
例如,要找到价格最高和最低的商品,您可以使用用户定义的变量来存储这些值。
2 外键 的使用
MySQL 支持外键,它允许跨表交叉引用相关数据,并支持外键约束,这有助于保持相关数据的一致性。
外键涉及一个包含初始列值的父表和一个具有列值的子表,这些列值引用父表的列值。外键约束是在子表上定义的。
以下示例通过单列外来关键词关联父表和子表,并展示外键约束如何强制实施引用完整性。
使用以下 SQL 语句创建父表和子表:
CREATE TABLE parent (
id INT NOT NULL,
PRIMARY KEY (id)
) ENGINE=INNODB;
CREATE TABLE child (
id INT,
parent_id INT,
INDEX par_ind (parent_id),
FOREIGN KEY (parent_id)
REFERENCES parent(id)
) ENGINE=INNODB;
要向父表中插入一行,您可以使用以下SQL语句
mysql> INSERT INTO parent (id) VALUES ROW(1);
要验证数据是否已成功插入,您可以通过选择父表中的所有行来进行确认。使用以下SQL查询可以实现这一点:
mysql> TABLE parent;
+----+
| id |
+----+
| 1 |
+----+
要使用SQL语句向子表中插入一行,并且假设您已经知道要引用的父表的id(在这个例子中,我们假设父表的id是1,这通常是从上一步插入操作后返回的或者通过查询得到的),您可以这样做:
mysql> INSERT INTO child (id,parent_id) VALUES ROW(1,1);
由于parent_id值为1在父表中存在,所以之前的插入操作是成功的。这是外键约束的预期行为:只有当子表中的parent_id对应于父表中实际存在的id时,才允许插入或更新操作。
为了展示当尝试插入一个不存在的parent_id时会发生什么,我们可以尝试插入一个具有无效parent_id的记录到子表中。例如,如果父表中没有id为99的记录,以下插入操作将会失败:
mysql> INSERT INTO child (id,parent_id) VALUES ROW(2,2);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails
(`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`)
REFERENCES `parent` (`id`))
尝试删除父表中先前插入的行可能会失败,因为存在外键约束。如果子表中还有记录引用了父表中的某个id,那么直接删除父表中的这条记录会违反外来关键词约束。如下所示:
mysql> DELETE FROM parent WHERE id = 1;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails
(`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`)
REFERENCES `parent` (`id`))
当父表中的键值被子表引用时,对父表进行的操作(如删除或更新)会受到外键约束的影响。如果在子表中有与父表相匹配的记录,那么操作的结果将取决于FOREIGN KEY子句中ON UPDATE和ON DELETE子句所指定的参照动作。
如果在定义外键约束时省略了ON DELETE和ON UPDATE子句(如当前子表的定义),那么它的行为与指定RESTRICT选项相同。RESTRICT会阻止那些会影响父表中被子表所引用的键值的操作。
为了演示ON DELETE和ON UPDATE参照动作,我们可以先删除当前的子表,然后重新创建它,并在创建时包含带有CASCADE选项的ON UPDATE和ON DELETE子句。CASCADE选项会在删除或更新父表中的记录时,自动删除或更新子表中与之匹配的记录。
DROP TABLE child;
CREATE TABLE child (
id INT,
parent_id INT,
INDEX par_ind (parent_id),
FOREIGN KEY (parent_id)
REFERENCES parent(id)
ON UPDATE CASCADE
ON DELETE CASCADE
) ENGINE=INNODB;
要向子表中插入一些行,您可以使用类似于以下的INSERT INTO语句。
mysql> INSERT INTO child (id,parent_id) VALUES ROW(1,1), ROW(2,1), ROW(3,1);
要验证数据是否已成功插入,可以如下所示:
mysql> TABLE child;
+------+-----------+
| id | parent_id |
+------+-----------+
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
+------+-----------+
要更新父表中的ID,将其从1更改为2,您可以使用以下的SQL UPDATE 语句:
mysql> UPDATE parent SET id = 2 WHERE id = 1;
为了验证父表中的ID是否已成功从1更新为2,您可以通过选择父表中的所有行来检查更新是否生效。以下是一个SQL查询示例,用于检索父表中的所有记录:
mysql> TABLE parent;
+----+
| id |
+----+
| 2 |
+----+
为了验证ON UPDATE CASCADE参照动作是否已更新了子表,
mysql> TABLE child;
+------+-----------+
| id | parent_id |
+------+-----------+
| 1 | 2 |
| 2 | 2 |
| 3 | 2 |
+------+-----------+
为了正确演示 ON DELETE CASCADE 参照动作,应该从父表中删除具有特定主键值的记录,并观察子表中所有引用该主键的记录是否也被自动删除。如下所示:
mysql> DELETE FROM parent WHERE id = 2;
如果子表中的所有记录都是与 parent_id = 2 相关联的,那么当您在父表中删除对应ID为2的记录时,ON DELETE CASCADE 参照动作确实会导致子表中的所有记录都被删除。这是因为所有子表记录都通过 parent_id 外键依赖于父表中ID为2的记录。
mysql> TABLE child;
Empty set (0.00 sec)
3 用两个关键字进行搜索
当在数据库中执行查询时,单个关键词的 OR 操作和 AND 操作通常都可以得到很好的优化。但是,当涉及到在两个不同的关键词上使用 OR 进行搜索时,情况就会变得复杂一些。
SELECT field1_index, field2_index FROM test_table
WHERE field1_index = '1' OR field2_index = '1'
当需要在两个不同的关键词上进行搜索并且这些搜索条件之间使用 OR 连接时,一个有效的策略是使用 UNION 来组合两个单独的 SELECT 语句的输出。这种方法允许每个 SELECT 语句只关注一个关键词,并可以针对该关键词进行优化。
使用 UNION 的好处是,每个单独的 SELECT 都可以利用索引(如果适用),并且每个查询都可以在单独的子查询中独立地进行优化。然后,UNION 操作将两个查询的结果合并成一个结果集,这个结果集满足原始 OR 查询的条件。
SELECT field1_index, field2_index
FROM test_table WHERE field1_index = '1'
UNION SELECT field1_index, field2_index
FROM test_table WHERE field2_index = '1';