我有一个带有用户表的 PostgreSQL 9.3 数据库,该表以保留大小写的格式存储用户名。所有查询都将不区分大小写,因此我应该有一个支持它的索引。此外,无论大小写如何,用户名都必须是唯一的。
这是我想出的:
forum=> \d users
Table "public.users"
Column | Type | Modifiers
------------+--------------------------+------------------------
name | character varying(24) | not null
Indexes:
"users_lower_idx" UNIQUE, btree (lower(name::text))
以标准 SQL 语法表示:
CREATE TABLE users (
name varchar(24) NOT NULL
);
CREATE UNIQUE INDEX "users_lower_idx" ON users (lower(name));
有了这个模式,我已经满足了我的所有约束,尽管没有主键。 SQL 标准不支持功能性主键,因此我无法提升索引:
forum=> ALTER TABLE users ADD PRIMARY KEY USING INDEX users_lower_idx;
ERROR: index "users_lower_idx" contains expressions
LINE 1: ALTER TABLE users ADD PRIMARY KEY USING INDEX users_lower_id...
^
DETAIL: Cannot create a primary key or unique constraint using such an index.
但是,我已经有了 UNIQUE 约束,并且列已经标记为“NOT NULL”。如果我必须有一个主键,我可以像这样构建表:
CREATE TABLE users (
name varchar(24) PRIMARY KEY
);
CREATE UNIQUE INDEX "users_lower_idx" ON users (lower(name));
但是我会有两个索引,这对我来说似乎是浪费和不必要的。那么,除了“UNIQUE NOT NULL”之外,PRIMARY KEY 对 postgres 意味着什么特别的东西吗?我是否因为没有 PRIMARY KEY 而错过了什么?
最佳答案
首先,实际上每个表都应该有一个主键。
citext
附加模块提供同名的数据类型。 “ci”不区分大小写。根据文档:
The
citext
module provides a case-insensitive character string type,citext
. Essentially, it internally callslower
when comparing values. Otherwise, it behaves almost exactly liketext
.
它完全符合您描述的目的:
The
citext
data type allows you to eliminate calls to lower in SQL queries, and allows a primary key to be case-insensitive.
大胆强调我的。
请务必阅读 the manual about limitations第一的。每个数据库安装一次
CREATE EXTENSION citext;
文本
如果你不想走那条路,我建议你添加一个 serial
作为代理主键。
CREATE TABLE users (
user_id serial PRIMARY KEY
, username text NOT NULL
);
我会使用 text
而不是 varchar(24)
。如果您需要强制执行最大长度(稍后可能会更改),请使用 CHECK
约束。详情:
- Any downsides of using data type "text" for storing strings?
- Change PostgreSQL columns used in views
连同原始设计中的 UNIQUE
索引(没有类型转换):
CREATE UNIQUE INDEX users_username_lower_idx ON users (lower(username));
serial
的底层 integer
小而快,不必浪费时间在 lower()
或你的排序规则上数据库。这对于外键引用特别有用。与具有不同属性的一些自然主键相比,我更喜欢它。
这两种解决方案各有利弊。
关于sql - PRIMARY KEY 实际上表示什么,我的表需要一个吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25068868/