ukl*_*kll 7 postgresql constraint
出于日志目的,在我设计的一个表中,我想存储用户登录时的IP信息。
当用户登录时,应存储 IPv4、IPv6 或两个 IP 地址。但我想设置一个不能为 NULL 的约束。
是否可以在带有约束的标准 SQL 中执行此操作,还是应该在 PostgreSQL 或业务层中使用 PL/pgSQL 执行此操作?
joa*_*olo 16
让我们假设您的表的结构是这样的:
CREATE TABLE log_logins
(
user_id INTEGER NOT NULL,
login_time TIMESTAMP NOT NULL DEFAULT now(),
ip_v4 TEXT /* or any other representation */,
ip_v6 TEXT /* or any other representation */,
PRIMARY KEY (user_id, login_time)
) ;
Run Code Online (Sandbox Code Playgroud)
您可以添加一个CHECK
保证其中之一ip_v4
或ip_v6
不为空的,但不能同时添加一个(对我来说同时拥有 v4 地址和 v6 地址是没有意义的;您通常不会同时使用这两种协议) . 这将通过以下语句完成:
ALTER TABLE log_logins
ADD CONSTRAINT one_and_only_one_of_ip_v4_or_ip_v6
CHECK ((ip_v4 IS NULL) <> (ip_v6 IS NULL));
Run Code Online (Sandbox Code Playgroud)
如果同时拥有 v4 和 v6 地址是合理的,则使用的约束将是:
ALTER TABLE log_logins
ADD CONSTRAINT at_least_one_of_ip_v4_or_ip_v6
CHECK ((ip_v4 IS NOT NULL) OR (ip_v6 IS NOT NULL));
Run Code Online (Sandbox Code Playgroud)
或者,查看RhodiumToad/ip4r 扩展。如果您使用它,您可以以紧凑而高效的方式表示ip4
, ip6
or ipaddress
(可以包含 IPv4 或 IPv6 地址),并在 IP 地址和 IP 地址范围上拥有一组运算符。我实际上会推荐它。
尽管 PostgreSQL 包含inet
可用于存储 Internet 地址(与网络掩码一起)的数据类型,但ip4r
如果您只需要一个 IP 地址(没有网络掩码),则该扩展提供了一些优势。优点之一是更紧凑的表示,如果要记录的数据量很大,这可能会起作用。如果您需要使用ip ranges
. 一个用例是将log_logins
表的 IP 列连接到另一个包含(任意)IP 范围及其对应的国家/地区的表。
是的。这是。只需在表上设置约束即可。
CREATE TEMP TABLE foo (
userid serial PRIMARY KEY,
ipv4 inet CHECK (family(ipv4) = 4),
ipv6 inet CHECK (family(ipv6) = 6),
CHECK (ipv4 IS NOT NULL OR ipv6 IS NOT NULL)
);
Run Code Online (Sandbox Code Playgroud)
或者,您可以只使用inet
支持 ipv4 或 ipv6的相同类型 ( ) ..
CREATE TEMP TABLE foo (
userid serial PRIMARY KEY,
userip inet NOT NULL
);
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
4074 次 |
最近记录: |