【问题标题】:Fire SQL Trigger only when a particular user update the row仅当特定用户更新行时触发 SQL 触发器
【发布时间】:2014-01-07 11:17:41
【问题描述】:

postgres 中有一个触发器,每当更新特定表时都会调用该触发器。 它用于向另一个 API 发送更新。

有没有一种方法可以控制此触发器的触发? 有时当我更新表时,我不希望触发触发器。我该怎么做呢? 有没有静默触发sql语法?

如果没有

我可以在 PG 用户 X 更新行并且当 PG 用户 Y 更新表时不应该触发触发器时触发触发器吗?

【问题讨论】:

  • 困惑。你不是在几秒钟前删除了与此相同的帖子吗?
  • @CraigRinger 是的,StackOverflow 给了我质量警告,因此我请我的朋友为我发布它。最终我们俩同时发布了它。
  • 这样做是有原因的。与其忽略此类警告,不如阅读您收到的警告消息中的建议并遵循它。否则最终你们都将被该网站禁止。 (顺便说一句,你也会因为创建然后删除很多问题而受到惩罚)。如果版主注意到或有人指出,使用朋友的帐户来避免禁止或禁止警告只会使 两个 帐户被禁止。

标签: sql postgresql triggers


【解决方案1】:

在最近的 Postgres 版本中,有一个 when 子句可用于有条件地触发触发器。你可以像这样使用它:

... when (old.* is distinct from new.*) ...

我不是 100% 这个可以工作(无法测试 atm):

... when (current_user = 'foo') ...

(如果没有,请尝试将其放在 plpgsql 中的 if 块中。)

http://www.postgresql.org/docs/current/static/sql-createtrigger.html

(还有[before|after] update of [col_name] 语法,但我倾向于发现它不太有用,因为即使列的值保持不变,它也会触发。)


添加这个额外的注释,看到@CraigRinger 的回答突出了你在做什么......

我认为,尝试使用条件触发器在 Salesforce 和 Postgres 之间设置主-主复制是一个白日梦。算了吧……还有更多的事情要做:您需要在两端适当地锁定数据(这不一定以合理的方式可行),管理由此产生的死锁(这可能不会自动被检测到),并处理冲突的数据。

您在一个小团队中成功完成此任务的几率大约为零 - 特别是如果您的 Postgres 技能处于投入时间阅读手册可以回答您自己的问题的水平。您可以放心地打赌,在 Salesforce 或某些主要 SQL 商店(例如,像 Craig 工作的那家)更有能力的人也认为相同,并且要么惨遭失败,要么被排除在外。

此外,我要强调的是,实现高效、同步、多主机复制不是一个已解决的问题。你没看错:没有解决了。就在几年前,这样做根本还没有得到很好的解决,无法在 Postgres 核心中实现。因此,您没有可以很好地作为您的工作基础和迭代的现有技术。

【讨论】:

  • current_user 是告诉我更新行的用户,还是正在监听触发器的用户?
  • 连接到数据库的用户。如果您想要应用程序用户,您需要一个额外的字段来存储最后更新它的人,事情变得简单:when (new.updated_by = 'foo')(或者更有可能是他的 id)。
  • @codeAnand 它标识运行导致触发器触发的命令的用户的用户名。这通常是连接到数据库的用户的登录名,但如果您正在运行(例如)SECURITY DEFINER 过程,它可以更改。如果您的应用为所有用户使用单个 SQL 级别登录,current_user 对您毫无用处。
【解决方案2】:

这似乎和this post a few minutes ago 是同一个问题,从不同的方向接近它。

如果是这样,虽然您确实可以按照 Denis 的建议进行操作,但不要试图重新发明这个轮子。如果您尝试双向(多主机)复制,请使用已建立的工具,如 Slony-I 或 Bucardo。在处理冲突更新时,您还需要了解多主控所涉及的主要限制。

一般来说,有几种方法可以控制触发器触发:

  • 让触发器触发,然后将逻辑放入 PL/PgSQL 触发器主体中,使其在满足特定条件时不采取任何行动。当规则很复杂时,这通常是唯一的选择。

  • 正如 Denis 指出的,使用触发器 WHEN 子句有条件地触发触发器

  • 使用session_replication_role 控制所有触发器的触发

  • Directly enable/disable triggers.

特别是,如果您的应用程序为所有数据库访问共享一个 SQL 级别的用户 ID,并在 SQL 级别之上进行自己的用户管理,并且您希望在每个用户的基础上控制触发器触发,那么唯一的方法是这样做将使用触发逻辑。您可能会发现这个关于在触发器中获取用户 ID 的先前答案很有用:

Passing user id to PostgreSQL triggers

【讨论】:

  • Slony 我让我用两个数据库进行主-主复制;我想做的是使用 Postgresql 和 Salesforce(通过 REST API)进行主主复制
  • @codeAnd 那么,您不能将触发器放在 REST API 上,可以吗?那么,当您只能从一端触发事件时,您怎么可能期望它起作用呢?您要轮询 API 调用以查找更改吗?
  • 我在 Salesforce 上有触发器。那部分已经解决了。
  • 是的。听起来它正在做异步,使用 http 回调之类的东西可能不是特别一致的推送。技术细节很薄弱,网站因收购而消失。如果该工具产生及时、一致的结果,我会感到非常惊讶——但您可能不需要它,在这种情况下,类似的基于 http 回调的方法对您来说是合理的。它不是“触发销售人员”,但它可能会满足您的需求。我会非常担心不一致、分歧和重新同步自己。
  • @codeAnand:没有冒犯,但老实说我对此表示怀疑。更接近现实的是,您会遇到一些病态的情况,即冲突的行抬起他们丑陋的头脑,以及与网络延迟相关的问题阻碍了有效同步的方式。它不仅仅是运送有效载荷。
猜你喜欢
  • 1970-01-01
  • 2021-10-04
  • 1970-01-01
  • 2018-05-24
  • 1970-01-01
  • 2012-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多