【发布时间】:2015-04-03 18:48:48
【问题描述】:
初始创建参数表并在Postgres中添加一行。
此表应始终只有一行,否则使用此表的 SQL 查询将产生不正确的结果。不允许DELETE 或INSERT 加入此表,仅允许UPDATE。
如何给这个表添加单行约束?
也许DELETE 和INSERT 触发器可以引发异常还是有更简单的方法?
【问题讨论】:
标签: sql postgresql database-design
初始创建参数表并在Postgres中添加一行。
此表应始终只有一行,否则使用此表的 SQL 查询将产生不正确的结果。不允许DELETE 或INSERT 加入此表,仅允许UPDATE。
如何给这个表添加单行约束?
也许DELETE 和INSERT 触发器可以引发异常还是有更简单的方法?
【问题讨论】:
标签: sql postgresql database-design
以下将创建一个表,您只能在其中插入一行。 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 什么也不做。如果没有该规则,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();
请注意,您必须在创建触发器之前插入单行,否则您无法插入该行。
这仅对超级用户或表的所有者部分有效。两者都有权删除或禁用触发器。但这就是超级用户的本性——他可以做任何事情。
【讨论】:
要使任何表成为单例,只需添加此列:
just_me bool NOT NULL DEFAULT TRUE UNIQUE CHECK (just_me)
这仅允许一行。另外添加触发器@a_horse provided。
但出于此目的,我会宁愿使用函数而不是表格。更简单,更便宜。
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;
将所有者设置为应允许更改的用户。
没有其他人改变它 - 当然除了超级用户。超级用户可以做任何事情。
您可以像使用表格一样使用此功能:
SELECT * FROM one_row();
如果你需要一个“表”,创建一个视图(内部实际上是一个特殊的表):
CREATE VIEW one_row AS SELECT * FROM one_row();
【讨论】:
select 42, 'foo',但这与“应允许更新”的要求相矛盾
CREATE OR REPLACE VIEW 或CREATE OR REPLACE FUNCTION。也许 OP 只是不知道替代方案。
我猜你不会在你的应用程序中使用 PostgreSQL root 用户,所以你可以简单地限制你的应用程序用户在UPDATE 上对该表的权限。
INSERT 或 DELETE 将导致 Insufficient privilege 异常。
【讨论】: