如何在没有看似多余的更新语句的情况下启动触发器?
How to kick off triggers without a seemly redundant update statement?
我有一个带有主键、时间戳和计数的简单 table。
我有触发器自动更新时间戳并在更新事件之前按标准计数。
要执行触发器,我必须执行一个事件(例如更新)。尽管它可以执行标准更新,但我并不完全满意table,因为它似乎是多余的。
update users set username = 'johndoe' where username = 'johndoe';
从 SQL 的角度来看,明确更新字段会感觉更好,但我宁愿将自动更新留给触发器,以便代码库与模式实现很好地分离(以便以后升级)。
有没有办法在不使用更新的情况下启动 table 行上的所有关联触发器?或者这是一个好的解决方案?由于没有任何变化,未来的数据库更新是否会拒绝该交易?
谢谢!
/* update_timestamp function to call from trigger */
create function update_timestamp() returns trigger as $$
begin
NEW.timestamp := current_timestamp;
return NEW;
end;
$$ language plpgsql;
/* update_count function to call from trigger */
create function update_count() returns trigger as $$
begin
NEW.count := OLD.count + 1;
return NEW;
end;
$$ language plpgsql;
/* users table */
create table users(
username character varying(50) not null,
timestamp timestamp not null default current_timestamp,
count bigint not null default 1);
/* timestamp & count triggers */
create trigger users_timestamp_upd before update on users for each row execute procedure update_timestamp();
create trigger users_count_upd before update on users for each row execute procedure update_count();
最后一个问题在先:
Will a future database update refuse the transaction since nothing is changing?
没有。这是完全有效的 SQL 语法。拒绝它会在 SQL 标准支持方面倒退,这对于任何生产就绪的 RDBMS 来说都是非常不规则的。此外,该标准要求 BEFORE UPDATE
在所有受影响的行上触发 运行,即使这些行实际上并未更改。
Is there a way to kick-off all associated triggers on a table row without using update? Or is this an ok solution?
就目前而言,这是一个合理的解决方案,但我将其称为代码异味。一般来说,触发器不是相关的。纯关系数据库更容易推理。在纯关系数据库中,您不会做这样的事情。所以你应该问问自己,触发器是否是一个好主意。当然,答案很可能是"yes, because there's no other reasonable way of doing this."但你应该实际考虑一下,而不是假设是这样。
谢谢。决定使用函数而不是触发器。直接从 PHP.
调用它
create or replace function add_update_user(varchar) returns void as $$
begin
if exists (select 1 from users where username = ) then
update users set timestamp = current_timestamp where username = ;
update users set count = count + 1 where username = ;
else
insert into users (username) values ();
end if;
end;
$$ language plpgsql;
create table users(
username character varying(50) not null,
timestamp timestamp not null default current_timestamp,
count bigint not null default 1);
select add_update_user('testusername');
我有一个带有主键、时间戳和计数的简单 table。
我有触发器自动更新时间戳并在更新事件之前按标准计数。
要执行触发器,我必须执行一个事件(例如更新)。尽管它可以执行标准更新,但我并不完全满意table,因为它似乎是多余的。
update users set username = 'johndoe' where username = 'johndoe';
从 SQL 的角度来看,明确更新字段会感觉更好,但我宁愿将自动更新留给触发器,以便代码库与模式实现很好地分离(以便以后升级)。
有没有办法在不使用更新的情况下启动 table 行上的所有关联触发器?或者这是一个好的解决方案?由于没有任何变化,未来的数据库更新是否会拒绝该交易?
谢谢!
/* update_timestamp function to call from trigger */
create function update_timestamp() returns trigger as $$
begin
NEW.timestamp := current_timestamp;
return NEW;
end;
$$ language plpgsql;
/* update_count function to call from trigger */
create function update_count() returns trigger as $$
begin
NEW.count := OLD.count + 1;
return NEW;
end;
$$ language plpgsql;
/* users table */
create table users(
username character varying(50) not null,
timestamp timestamp not null default current_timestamp,
count bigint not null default 1);
/* timestamp & count triggers */
create trigger users_timestamp_upd before update on users for each row execute procedure update_timestamp();
create trigger users_count_upd before update on users for each row execute procedure update_count();
最后一个问题在先:
Will a future database update refuse the transaction since nothing is changing?
没有。这是完全有效的 SQL 语法。拒绝它会在 SQL 标准支持方面倒退,这对于任何生产就绪的 RDBMS 来说都是非常不规则的。此外,该标准要求 BEFORE UPDATE
在所有受影响的行上触发 运行,即使这些行实际上并未更改。
Is there a way to kick-off all associated triggers on a table row without using update? Or is this an ok solution?
就目前而言,这是一个合理的解决方案,但我将其称为代码异味。一般来说,触发器不是相关的。纯关系数据库更容易推理。在纯关系数据库中,您不会做这样的事情。所以你应该问问自己,触发器是否是一个好主意。当然,答案很可能是"yes, because there's no other reasonable way of doing this."但你应该实际考虑一下,而不是假设是这样。
谢谢。决定使用函数而不是触发器。直接从 PHP.
调用它create or replace function add_update_user(varchar) returns void as $$
begin
if exists (select 1 from users where username = ) then
update users set timestamp = current_timestamp where username = ;
update users set count = count + 1 where username = ;
else
insert into users (username) values ();
end if;
end;
$$ language plpgsql;
create table users(
username character varying(50) not null,
timestamp timestamp not null default current_timestamp,
count bigint not null default 1);
select add_update_user('testusername');