在 PostgreSQL 中插入之前触发,但某些列除外
Trigger before insert in PostgreSQL and except some columns
我正在尝试为我的 table 编写触发器。这个 table 有 50 列,其中 3 列是 timestamp
类型。将来我会插入新行,它们可以与现有行重复,所以我需要计算每一行的哈希值。我的想法是在每次插入时计算行的散列并检查它是否存在,这就是我编写触发器的原因。我想计算散列并将其写入我的主 table 到最后一列(我在创建 table 时创建了它)。
我有一个问题 - 我需要计算散列而不是整行,我不应该使用时间戳类型的 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();
如果列名始终相同,则通过 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
是目标 table 中应该存储生成的哈希值的列(我使用了 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 值中删除键。
我正在尝试为我的 table 编写触发器。这个 table 有 50 列,其中 3 列是 timestamp
类型。将来我会插入新行,它们可以与现有行重复,所以我需要计算每一行的哈希值。我的想法是在每次插入时计算行的散列并检查它是否存在,这就是我编写触发器的原因。我想计算散列并将其写入我的主 table 到最后一列(我在创建 table 时创建了它)。
我有一个问题 - 我需要计算散列而不是整行,我不应该使用时间戳类型的 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();
如果列名始终相同,则通过 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
是目标 table 中应该存储生成的哈希值的列(我使用了 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 值中删除键。