Skip to content

MySQL - 字面量

在 SQL 中,字面量是一个固定、常量值。它表示其自身,例如数字 123 或字符串 'Hello, World!'。字面量用于 SQL 语句中,提供用于比较、插入或赋值的明确值。

虽然字面量是基础的,但理解这一点至关重要:在应用程序代码中,您几乎总是应该使用带有占位符的预处理语句,而不是将字面量直接嵌入到查询字符串中。这是防范 SQL 注入攻击最重要的一道防线。

字符串字面量是包含在单引号 (') 或双引号 (") 中的字符序列。单引号是标准且更具可移植性。

SELECT 'This is a string literal.';
SELECT "This also works, but single quotes are preferred.";

要在字符串中包含引号字符,必须对其进行转义。您可以通过双写引号字符或使用反斜杠 (\) 来实现。

SELECT 'It''s a beautiful day.'; -- 双写单引号
SELECT 'You can also use a backslash \' like this.'; -- 反斜杠转义

您可以使用引入器语法 (_charset) 为字符串字面量指定字符集:

SELECT _utf8mb4'Hello, world!';

数字字面量表示数字。它们可以是整数、小数或科学计数法。

  • 整数:100,-50
  • 小数/浮点数:123.45,-0.01
  • 科学计数法:1.23E4 (即 1.23 * 10^4 = 12300)
SELECT 42; -- 一个整数
SELECT 98.6; -- 一个小数
SELECT 1.5E-3; -- 科学计数法 (0.0015)

日期和时间值通常以特定格式的字符串表示。MySQL 灵活多样,但标准格式更受推荐。

  • DATE:'YYYY-MM-DD',例如 '2023-10-27'
  • TIME:'HH:MM:SS',例如 '14:30:00'
  • DATETIME 或 TIMESTAMP:'YYYY-MM-DD HH:MM:SS',例如 '2023-10-27 14:30:00'

您也可以使用关键字来表示时间字面量:

SELECT DATE '2023-10-27';
SELECT TIME '14:30:00';
SELECT TIMESTAMP '2023-10-27 14:30:00';

通常最好使用 NOW()、CURDATE() 和 CURTIME() 等函数来获取当前值。

MySQL 没有原生的 BOOLEAN 类型。它使用 TINYINT(1) 代替。关键字 TRUE 和 FALSE 分别只是整数 1 和 0 的别名。它们不区分大小写。

SELECT TRUE, FALSE; -- 返回 1, 0
SELECT true, false; -- 也返回 1, 0

NULL 字面量表示缺失或未知的值。它与零 (0) 或空字符串 ('') 不同。NULL 不区分大小写。

SELECT NULL; -- 表示一个未知值
SELECT NULL, null, NuLl; -- 都是相同的

任何与 NULL 进行的算术运算结果都为 NULL (例如,5 + NULL 是 NULL)。与 NULL 的比较需要使用 IS NULL 或 IS NOT NULL 运算符。

这些用于逐字节指定值,对二进制数据很有用。

  • 十六进制:X'hex_string' 或 0x... 语法。例如:X'4A6F686E' 表示 ASCII 字符串 ‘John’。
  • 位值:b'binary_string' 或 0b... 语法。例如:b'1011' 表示数字 11。
SELECT X'4D7953514C'; -- 返回字符串 'MySQL'
SELECT 0b1101; -- 返回整数 13

虽然您在 SQL 客户端中编写查询时会直接使用字面量,但在涉及用户输入的应用程序代码中避免使用它们至关重要。将用户输入连接到 SQL 字符串中是 SQL 注入发生的方式。

// PHP 示例
$user_id = $_GET['id']; // e.g., '105'
$sql = "SELECT * FROM users WHERE id = $user_id;"; // 非常危险!

如果恶意用户提供一个 ID 像 105; DROP TABLE users;,您的查询将变得灾难性。

使用预处理语句,SQL 查询结构和数据值是分开发送到数据库服务器的。数据库引擎知道占位符值是数据,而不是可执行代码。

// PHP 示例,使用 PDO
$user_id = $_GET['id']; // e.g., '105'
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$user_id]);
$user = $stmt->fetch();

在这个安全版本中,即使提供了恶意字符串,它也会被视为一个要搜索的字面字符串,而不是一个要执行的命令。