如何将约束添加到 sql table 以便 table 正好有一行

How to add constraint to sql table so that table has exactly one row

初始创建参数table并在Postgres中添加一行。

这个 table 应该总是一行,否则 SQL 使用这个 table 的查询将产生不正确的结果。 DELETEINSERT 到此 table 是不允许的,只允许 UPDATE

如何向这个 table 添加单行约束?
也许 DELETEINSERT 触发器可以引发异常或者有更简单的方法吗?

我猜你不会在你的应用程序中使用 PostgreSQL root 用户,所以你可以简单地限制你的应用程序用户在 UPDATE 上的权限为此 table。

INSERTDELETE 将导致 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();