我们尽力使MySQL Server遵循ANSI SQL标准和ODBC SQL标准,但在某些情况下,MySQL Server会以不同的方式执行操作。
MySQL Server 不支持 Sybase SQL 的 SELECT ... INTO TABLE 扩展语法。相反,MySQL Server 支持 INSERT INTO ... SELECT 的标准 SQL 语法,其基本上是相同的功能。
INSERT INTO tbl_temp2 (fld_id)
SELECT tbl_temp1.fld_order_id
FROM tbl_temp1 WHERE tbl_temp1.fld_order_id > 100;
另外,你还可以使用 SELECT ... INTO OUTFILE 或 CREATE TABLE ... SELECT。
你可以使用 SELECT ... INTO 与用户定义的变量一起使用。相同的语法也可以在存储过程中使用游标和本地变量。
如果你在表格中的更新语句中的表达式中访问了被更新的列,UPDATE 会使用该列的当前值。下面语句中的第二个赋值将 col2 设置为当前(更新后)的 col1 值,而不是原始的 col1 值。结果是 col1 和 col2 具有相同的值。这种行为与标准 SQL 不同。
UPDATE t1 SET col1 = col1 + 1, col2 = col1;
MySQL 对 FOREIGN KEY 约束的实现与 SQL 标准在以下关键方面存在差异:
为了提高性能,MySQL要求引用的列被索引。然而,MySQL不强制要求引用的列是唯一的或声明为 NOT NULL。引用非唯一键的外键约束不符合标准SQL,而是InnoDB的扩展。另一方面,NDB存储引擎要求任何作为外键引用的列必须有一个明确的唯一键(或主键)。
对于UPDATE或DELETE CASCADE等操作,对非唯一键或包含NULL值的外键引用的处理未定义得很好。建议您只使用引用 UNIQUE(包括 PRIMARY)和 NOT NULL 键的外键。
对于不支持外键的存储引擎(如MyISAM),MySQL服务器会解析并忽略外键规范。
MySQL解析但忽略“内联REFERENCES规范”(如SQL标准定义的),其中引用是作为列规范的一部分定义的。只有在作为单独的FOREIGN KEY规范的一部分指定时,MySQL才接受REFERENCES子句。
将列定义为使用REFERENCES tbl_name(col_name)子句没有实际效果,只是作为备忘录或注释,提醒您当前正在定义的列是要引用另一个表中的列。使用此语法时,需要注意以下几点:
MySQL不执行任何检查来确保col_name实际存在于tbl_name中(甚至不会验证tbl_name本身是否存在)。
MySQL不对tbl_name执行任何操作,例如根据对您正在定义的表中行的操作来删除行;换句话说,这种语法不会引发任何ON DELETE或ON UPDATE行为。(尽管您可以在REFERENCES子句中编写ON DELETE或ON UPDATE子句,但也会被忽略。)
这种语法创建了一个列,但不会创建任何类型的索引或键。
您可以将这样创建的列用作连接列,就像在这里显示的那样:
CREATE TABLE person (
id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
name CHAR(60) NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE shirt (
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 person(id),
PRIMARY KEY (id)
);
INSERT INTO person VALUES (NULL, 'Antonio Paz');
SELECT @last := LAST_INSERT_ID();
INSERT INTO shirt VALUES
(NULL, 'polo', 'blue', @last),
(NULL, 'dress', 'white', @last),
(NULL, 't-shirt', 'blue', @last);
INSERT INTO person VALUES (NULL, 'Lilliana Angelovska');
SELECT @last := LAST_INSERT_ID();
INSERT INTO shirt VALUES
(NULL, 'dress', 'orange', @last),
(NULL, 'polo', 'red', @last),
(NULL, 'dress', 'blue', @last),
(NULL, 't-shirt', 'white', @last);
SELECT * FROM person;
+----+---------------------+
| id | name |
+----+---------------------+
| 1 | Antonio Paz |
| 2 | Lilliana Angelovska |
+----+---------------------+
SELECT * FROM shirt;
+----+---------+--------+-------+
| 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 person p INNER JOIN shirt s
ON s.owner = p.id
WHERE p.name LIKE 'Lilliana%'
AND s.color <> 'white';
+----+-------+--------+-------+
| id | style | color | owner |
+----+-------+--------+-------+
| 4 | dress | orange | 2 |
| 5 | polo | red | 2 |
| 6 | dress | blue | 2 |
+----+-------+--------+-------+
当以这种方式使用时,“REFERENCES”子句不会显示在SHOW CREATE TABLE或DESCRIBE的输出中。
SHOW CREATE TABLE shirt\G
*************************** 1. row ***************************
Table: shirt
Create Table: CREATE TABLE `shirt` (
`id` smallint(5) unsigned NOT NULL auto_increment,
`style` enum('t-shirt','polo','dress') NOT NULL,
`color` enum('red','blue','orange','white','black') NOT NULL,
`owner` smallint(5) unsigned NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4
标准SQL使用C语法中的 /* this is a comment */ 来进行注释,MySQL服务器也支持这种语法。MySQL还支持扩展此语法的方式,以便将特定于MySQL的SQL嵌入到注释中。
标准SQL使用“--”作为开始注释的序列。而MySQL服务器使用#作为开始注释的字符。MySQL服务器也支持一种变体的--注释风格。即--开始注释序列必须后跟一个空格(或控制字符,如换行符)。此空格是必需的,以防止在自动生成的SQL查询中出现以下构造的问题,其中我们自动插入payment的值用于payment:
UPDATE account SET credit=credit-payment
考虑如果payment有一个负值(如-1),会发生什么情况:
UPDATE account SET credit=credit--1
credit--1是SQL中的一个有效表达式,但是--被解释为注释的开始,表达式的一部分被丢弃了。结果是一个语句的含义与原意完全不同:
UPDATE account SET credit=credit
该语句根本没有改变任何值。这说明允许以--开头的注释可能会产生严重的后果。
根据我们的实现,在MySQL服务器中,使用--作为注释起始符号时,后面需要加上一个空格才能被识别为注释的开始序列。因此,credit--1 是可以安全使用的。