【问题标题】:Trigger before insert in PostgreSQL and except some columns在 PostgreSQL 中插入之前触发,但某些列除外
【发布时间】:2021-03-29 04:37:31
【问题描述】:

我正在尝试为我的表编写触发器。该表有 50 列,其中 3 列是 timestamp 类型。将来我将插入新行,它们可以与现有行重复,因此我需要计算每一行的哈希值。我的想法是在每次插入中计算行的哈希并检查它是否存在,这就是我编写触发器的原因。我想计算哈希并将其写入我的主表的最后一列(我在创建表时创建了它)。 我有一个问题 - 我需要计算散列而不是整行,我不应该使用时间戳类型的 3 列(对于行的散列,我应该排除 3 列)。

我刚刚开始这样做并遇到了一个问题 - 我不知道如何排除这些列以进行散列。

CREATE OR REPLACE FUNCTION check_row_hash() RETURNS TRIGGER AS $mergetrigger$
BEGIN
    -- As I understand I can get row's data using NEW.column_name
    -- But how to exclude 3 columns and get others dynamically ??
    -- I can use these script for getting needed columns 
 
       select column_name
            from user_tab_columns
       where table_name = 'main_table' 
            data_type not in ('date', 'timestamp')
    
    -- But what should i do next?

END;


CREATE TRIGGER check_inserted_row
    BEFORE INSERT ON main_table
    for each row
    EXECUTE PROCEDURE check_row_hash();

【问题讨论】:

  • 与编写或生成特定于可以直接在所需列上工作的表的触发器相比,该级别的间接/通用代码会很慢。或者使用生成的列。
  • @Brian,你是什么意思?我是数据库新手,所以我无法理解您的想法..

标签: sql database postgresql triggers postgresql-13


【解决方案1】:

如果列名始终相同,则通过 JSON 值进行重定向会使这有点动态:

CREATE OR REPLACE FUNCTION check_row_hash() 
RETURNS TRIGGER AS $mergetrigger$
declare
  l_row_data jsonb;
  l_row_text text;
BEGIN
  l_row_data := to_jsonb(new) - 'updated_at' - 'created_at'; 
  select string_agg(t.v, ',')
    into l_row_text
  from jsonb_each_text(l_row_data) as t(k,v);
  
  new.hash_value := md5(l_row_text::text);
  return new;  
END;

has_value 是目标表中应该存储生成的哈希的列(我使用了 MD5 哈希)。

您可以通过以下方式查询pg_attribute 使其完全动态化:

select attname
from pg_attribute
where attnum > 0
and not attisdropped
and atttypid in ('date'::regtype, 'timestamp'::regtype)
and attrelid = TG_RELID;

然后使用该查询中的列列表从 JSONB 值中删除键。

【讨论】:

    猜你喜欢
    • 2022-01-19
    • 2016-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-30
    • 1970-01-01
    • 2015-02-14
    相关资源
    最近更新 更多