SQL 字符数据类型
在 PostgreSQL 及任何关系型数据库中,存储和管理文本信息是绝大多数应用程序的基础任务。从用户名和产品描述到文章内容和实际地址,文本数据无处不在。为你的字符串选择正确的数据类型对于数据库性能、存储效率和数据完整性相当重要。
本章将深入探讨 PostgreSQL 中可用的主要字符数据类型:VARCHAR、TEXT 和 CHAR。理解它们之间的区别、使用模式及其潜在影响,将使你在设计数据库表时能够做出明智的决策,确保文本数据得到高效且妥善的存储。
1. 了解 CHAR (定长字符串)
CHAR(n) 数据类型用于存储固定长度的字符串。当你将一列声明为 CHAR(10) 时,它将始终占用正好 10 个字符的空间。
- 不足则填充: 如果你插入的字符串短于 10 个字符,PostgreSQL 会在字符串末尾填充空格,以达到指定的长度。
- 超出则截断或报错: 如果你尝试插入长于 10 个字符的字符串,如果多出的字符全是空格,PostgreSQL 会将其静默截断为 10 个字符;但如果多出的是非空格字符,通常会导致报错(这是现代 PostgreSQL 的默认安全行为)。
CHAR 的关键特性在于其固定长度。这有时会使比较操作的处理速度略快,因为存储大小是可预测的。然而,如果你的数据长度经常变化且大多数都短于声明的最大长度,使用 CHAR 会导致严重的存储空间浪费。
1.1 语法与示例
CHAR 的语法非常简单:
column_name CHAR(n)其中 n 是一个整数,代表要存储的确切字符数。
示例 1:存储双字母州/省缩写
假设你需要存储美国州名的缩写,它们总是正好两个字符长(例如,'CA','NY','TX')。在这里,CHAR(2) 是完美的选择。
CREATE TABLE customers (
customer_id SERIAL PRIMARY KEY,
customer_name VARCHAR(100),
state_abbreviation CHAR(2) -- 强制始终为 2 个字符
);
INSERT INTO customers (customer_name, state_abbreviation) VALUES
('Alice Smith', 'CA'),
('Bob Johnson', 'NY'),
('Charlie Brown', 'TX');
-- 查询数据以查看存储的值和长度
SELECT customer_name, state_abbreviation, LENGTH(state_abbreviation) FROM customers;在这个例子中,state_abbreviation 将始终占用 2 个字符的空间。如果你尝试插入只包含一个字符的 'C',它在数据库内部会被填充存储为 'C '。
真实场景示例:固定长度的产品 SKU
许多库存系统使用固定长度的库存单位 (SKU) 代码。如果一家公司使用标准的 8 字符 SKU(例如,'PG001234','ELX98765'),那么 CHAR(8) 是合适的。
CREATE TABLE products (
product_id SERIAL PRIMARY KEY,
product_name VARCHAR(255),
sku CHAR(8) UNIQUE -- 强制 SKU 唯一且固定为 8 个字符
);
INSERT INTO products (product_name, sku) VALUES
('PostgreSQL 马克杯', 'PG000001'),
('大象毛绒玩具', 'EL000001');
-- 让我们尝试插入一个较短的字符串来演示自动填充:
INSERT INTO products (product_name, sku) VALUES ('短 SKU 商品', 'SHORT');
-- 'SHORT' 只有 5 个字符,它将在末尾被填充 3 个空格,变成 'SHORT '
SELECT product_name, sku, LENGTH(sku) FROM products WHERE product_name = '短 SKU 商品';
-- 你会发现虽然你输入的是 'SHORT',但 LENGTH(sku) 返回的是 82. 了解 VARCHAR (变长字符串)
VARCHAR(n) 数据类型用于存储具有用户定义的最大长度限制的变长字符串(Variable-Character)。
与 CHAR 不同,VARCHAR 不会用空格填充字符串。它只存储你实际提供的字符,外加少量的开销(通常是 1 到 4 个字节)来记录字符串的实际长度。这使得 VARCHAR 在存储长度变化显著的文本时,空间效率要高得多。
如果你尝试插入一个长度超过指定 n 的字符串,PostgreSQL 将报错并拒绝插入。默认情况下,VARCHAR 严格执行最大长度限制。
2.1 语法与示例
VARCHAR 的语法是:
column_name VARCHAR(n)其中 n 是一个整数,代表允许的最大字符数。
示例 1:存储客户姓名
客户姓名的长度差异很大。使用 VARCHAR(100) 允许姓名最长达到 100 个字符,但只会消耗每个特定姓名实际所需的空间。
CREATE TABLE users (
user_id SERIAL PRIMARY KEY,
username VARCHAR(50) UNIQUE, -- 用户名最多 50 个字符
email VARCHAR(255) NOT NULL, -- 电子邮件最多 255 个字符
bio VARCHAR(500) -- 个人简介最多 500 个字符
);
INSERT INTO users (username, email, bio) VALUES
('johndoe', 'john.doe@example.com', '狂热的数据库爱好者。'),
('alice_wonder', 'alice@example.com', '正在学习 PostgreSQL 基础。');
-- 如果尝试插入超过 50 个字符的用户名,将会导致错误:
-- INSERT INTO users (username, email) VALUES ('this_is_a_really_long_username_for_my_test_account_that_should_fail', 'longuser@example.com');
-- 报错信息: value too long for type character varying(50)
SELECT username, email, LENGTH(username), LENGTH(email) FROM users;请注意,LENGTH(username) 返回的是字符串的实际长度,而不是声明的最大长度 50。
真实场景示例:产品简短描述
电子商务网站需要存储产品描述。如果存在一个合理的上限长度,例如 VARCHAR(1000) 将是一个不错的选择。
CREATE TABLE products_ecommerce (
product_id SERIAL PRIMARY KEY,
product_name VARCHAR(255) NOT NULL,
short_description VARCHAR(1000), -- 最多 1000 个字符
price DECIMAL(10, 2)
);3. 了解 TEXT (无限制文本)
TEXT 数据类型用于存储任意长度的可变长度字符串。
在 PostgreSQL 中,TEXT 本质上就是没有显式长度限制的 VARCHAR。PostgreSQL 非常高效地存储 TEXT 数据,就像 VARCHAR 一样,它只消耗实际字符串内容所需的空间,加上一个很小的长度记录开销。
在 PostgreSQL 内部,没有指定长度的 VARCHAR(即单纯写 VARCHAR)与 TEXT 之间实际上没有功能上的区别。但是,为了代码的可读性和明确表达“这段文本没有长度限制”的意图,当你不希望在数据库层面强制执行长度上限时,通常首选使用 TEXT。
3.1 语法与示例
TEXT 的语法非常简单,不需要任何参数:
column_name TEXT示例 1:存储文章内容
对于博客文章、新闻或评论,长度可能从几个字到数万字不等,此时 TEXT 是最合适的选择。
CREATE TABLE articles (
article_id SERIAL PRIMARY KEY,
title VARCHAR(255) NOT NULL,
author VARCHAR(100),
content TEXT, -- 完整的文章内容,可能非常长
published_date TIMESTAMP DEFAULT NOW()
);
INSERT INTO articles (title, author, content) VALUES
('数据库在 AI 时代的未来', 'Evelyn Reed 博士', '在人工智能正在改变各行各业的时代,数据库在存储、管理和检索 AI 模型所需的海量数据方面发挥着关键作用。本文探讨了数据库技术不断演变的格局...');
SELECT title, LENGTH(content) AS content_length FROM articles;真实场景示例:法律文档存储
律师事务所可能需要将完整的合同或免责声明直接存储在数据库中。这些文档极其冗长,使得 TEXT 成为唯一实用的选择。
4. 核心对比:何时使用哪种类型?
选择 CHAR、VARCHAR 还是 TEXT 取决于你要存储的数据的具体特征。以下是它们的总结和推荐用例:
| 特性 | CHAR(n) | VARCHAR(n) | TEXT |
|---|---|---|---|
| 长度类型 | 定长 (Fixed-length) | 带最大限制的变长 | 无限制的变长 |
| 空格填充 | 会用空格填充至 n 字符 | 不会填充 | 不会填充 |
| 存储开销 | 始终占用 n 个字符的空间 | 实际长度 + 1至4字节(记录长度) | 实际长度 + 1至4字节(记录长度) |
| 截断行为 | 超过 n 且非空格则报错 | 超过 n 报错 | 永远不会因为长度报错 |
| 最佳用例 | 简短的、已知固定长度的代码 (如: 'M'/'F', 'US', 邮编) | 姓名、地址、标题、邮箱、有限制的简短描述 | 长篇文章、评论、大型 JSON/XML 文本、法律文档 |
4.1 深入选择指南
- 何时使用
CHAR(n): - 当数据绝对、始终具有已知的固定长度时。
- 例如: 两位数的国家代码、单字符标志位('Y'/'N')、特定且固定长度的识别码。
- 注意: 由于其空格填充行为如果不被完全理解有时会导致意外,它在现代通用文本存储中已较少使用。
- 何时使用
VARCHAR(n): - 当你需要存储长度可变的字符串,但同时又希望在数据库层面强制设置一个合理的长度上限时。
- 例如: 用户名(限制 50 字符防恶意输入)、电子邮件地址、文章标题。 这是大多数文本列的默认和首选。它可以防止异常庞大或错误的输入占用系统资源。
- 何时使用
TEXT: - 当你需要存储长度可变的字符串,并且没有实际的长度上限,或者不希望数据库去限制它时。
- 例如: 博客正文、详细的产品描述、用户评论反馈。 在 PostgreSQL 中,它在存储和处理变长字符串方面的效率与
VARCHAR一样高。
关于编码的注意事项:
PostgreSQL 支持各种字符集,推荐的默认设置是 UTF-8。在处理多字节字符(如中文、日文等)时,实际占用的字节数可能大于字符数(例如,在 UTF-8 中,一个中文字符通常占用 3 个字节)。CHAR(n) 和 VARCHAR(n) 中的 n 指的是字符的数量,而不是字节的数量。PostgreSQL 会在底层自动处理字符到字节的转换。