如何将约束添加到 sql table 以便 table 正好有一行
How to add constraint to sql table so that table has exactly one row
初始创建参数table并在Postgres中添加一行。
这个 table 应该总是一行,否则 SQL 使用这个 table 的查询将产生不正确的结果。 DELETE
或 INSERT
到此 table 是不允许的,只允许 UPDATE
。
如何向这个 table 添加单行约束?
也许 DELETE
和 INSERT
触发器可以引发异常或者有更简单的方法吗?
我猜你不会在你的应用程序中使用 PostgreSQL root 用户,所以你可以简单地限制你的应用程序用户在 UPDATE
上的权限为此 table。
INSERT
或 DELETE
将导致 Insufficient privilege
异常。
下面将创建一个 table,您只能在其中插入一行。 id
列的任何更新都将导致错误,任何具有不同于 42 的值的插入也会导致错误。实际的 id
值实际上并不重要(除非您需要一些特殊含义).
create table singleton
(
id integer not null primary key default 42,
parameter_1 text,
parameter_2 text,
constraint only_one_row check (id = 42)
);
insert into singleton values (default);
要防止删除,您可以使用规则:
create or replace rule ignore_delete
AS on delete to singleton
do instead nothing;
你也可以使用规则让 insert
什么也不做,如果你想静静地做一个 insert
"fail"。如果没有规则,insert
会产生错误。如果您希望 delete
也产生错误,则需要创建一个触发器来简单地引发异常。
编辑
如果你想为插入或删除抛出错误,你需要一个触发器:
create table singleton
(
id integer not null primary key,
parameter_1 text,
parameter_2 text
);
insert into singleton (id) values (42);
create or replace function raise_error()
returns trigger
as
$body$
begin
RAISE EXCEPTION 'No changes allowed';
end;
$body$
language plpgsql;
create trigger singleton_trg
before insert or delete on singleton
for each statement execute procedure raise_error();
请注意,您必须在创建触发器之前插入单行,否则无法插入该行。
这仅部分适用于超级用户或 table 的所有者。两者都有权删除或禁用触发器。但这就是超级用户的本性——他无所不能。
要使任何 table 成为单例,只需添加此列:
just_me bool NOT NULL DEFAULT TRUE UNIQUE CHECK (just_me)
这只允许一行。加上触发器 .
但我 宁愿使用函数 而不是 table 来达到这个目的。更简单,更便宜。
CREATE OR REPLACE FUNCTION one_row()
RETURNS TABLE (company_id int, company text) LANGUAGE sql IMMUTABLE AS
$$SELECT 123, 'The Company'$$
ALTER FUNCTION one_row() OWNER TO postgres;
将所有者设置为允许更改的用户。
- Give a user permission to ALTER a function
没有其他人可以更改它 - 当然,超级用户除外。超级用户可以做任何事情。
您可以像使用 table:
一样使用此功能
SELECT * FROM one_row();
如果你需要一个"table",创建一个视图(其实内部是一个特殊的table):
CREATE VIEW one_row AS SELECT * FROM one_row();
初始创建参数table并在Postgres中添加一行。
这个 table 应该总是一行,否则 SQL 使用这个 table 的查询将产生不正确的结果。 DELETE
或 INSERT
到此 table 是不允许的,只允许 UPDATE
。
如何向这个 table 添加单行约束?
也许 DELETE
和 INSERT
触发器可以引发异常或者有更简单的方法吗?
我猜你不会在你的应用程序中使用 PostgreSQL root 用户,所以你可以简单地限制你的应用程序用户在 UPDATE
上的权限为此 table。
INSERT
或 DELETE
将导致 Insufficient privilege
异常。
下面将创建一个 table,您只能在其中插入一行。 id
列的任何更新都将导致错误,任何具有不同于 42 的值的插入也会导致错误。实际的 id
值实际上并不重要(除非您需要一些特殊含义).
create table singleton
(
id integer not null primary key default 42,
parameter_1 text,
parameter_2 text,
constraint only_one_row check (id = 42)
);
insert into singleton values (default);
要防止删除,您可以使用规则:
create or replace rule ignore_delete
AS on delete to singleton
do instead nothing;
你也可以使用规则让 insert
什么也不做,如果你想静静地做一个 insert
"fail"。如果没有规则,insert
会产生错误。如果您希望 delete
也产生错误,则需要创建一个触发器来简单地引发异常。
编辑
如果你想为插入或删除抛出错误,你需要一个触发器:
create table singleton
(
id integer not null primary key,
parameter_1 text,
parameter_2 text
);
insert into singleton (id) values (42);
create or replace function raise_error()
returns trigger
as
$body$
begin
RAISE EXCEPTION 'No changes allowed';
end;
$body$
language plpgsql;
create trigger singleton_trg
before insert or delete on singleton
for each statement execute procedure raise_error();
请注意,您必须在创建触发器之前插入单行,否则无法插入该行。
这仅部分适用于超级用户或 table 的所有者。两者都有权删除或禁用触发器。但这就是超级用户的本性——他无所不能。
要使任何 table 成为单例,只需添加此列:
just_me bool NOT NULL DEFAULT TRUE UNIQUE CHECK (just_me)
这只允许一行。加上触发器
但我 宁愿使用函数 而不是 table 来达到这个目的。更简单,更便宜。
CREATE OR REPLACE FUNCTION one_row()
RETURNS TABLE (company_id int, company text) LANGUAGE sql IMMUTABLE AS
$$SELECT 123, 'The Company'$$
ALTER FUNCTION one_row() OWNER TO postgres;
将所有者设置为允许更改的用户。
- Give a user permission to ALTER a function
没有其他人可以更改它 - 当然,超级用户除外。超级用户可以做任何事情。
您可以像使用 table:
一样使用此功能SELECT * FROM one_row();
如果你需要一个"table",创建一个视图(其实内部是一个特殊的table):
CREATE VIEW one_row AS SELECT * FROM one_row();