更新后如何正确更新行的值

How can I properly update value of my row after it has been updated

我正在尝试跟踪我的数据是如何更改的,

我正在使用自定义解决方案,因为我只会在 运行 脚本时跟踪这些更改。

对我来说最重要的是拥有previous_valuevalue_after_update

INSERT INTO audit_details 
    (updated_table, updated_column, query, value_before_update, value_after_update)

SELECT 'some_table', 'some_column', query, enabled, (Here I've tried to put same query as it's contained on update because that value will be there after update),
FROM some_table WHERE product_id = _new_product_id;


UPDATE some_table
SET enabled = CASE WHEN (SELECT 1 FROM some_table WHERE enabled = true AND product_type = T1.product_type AND product_id = ANY(_previous_product_ids)) IS NOT NULL
    THEN true
    ELSE enabled END,
    THEN true
    ELSE accepted END
WHERE product_id = _new_product_id;

你们可以注意到伙计们,问题是我不知道如何正确插入 values_after_update,我应该以某种方式重复 阻止更新到我上面的插入(我已经尝试过了,即使我不能 运行 它又大又丑 XD)?

任何形式的帮助都会很棒!

谢谢

干杯

您可以通过一个链接多个 CTEs 的语句来实现这一点,该语句捕获 UPDATE 前后的旧值和新值。

然后您可以 "iterate" 通过将行转换为 JSONB 并提取更改后的值来处理列。

with old_data as (
  -- collect the old values
  select id, to_jsonb(t) as old_value
  from some_table t
  where product_id = 100
), new_data as (

  -- this is where the actual UPDATE is done
  -- change the SET part as you need it
  update some_table
     set enabled = false,
         some_value = 4
  where product_id = 100
  -- this returns the modified values from the CTE
  returning id, to_jsonb(some_table) as new_value

), changed_column_values as (
  -- this converts the JSON values into one row per column
  -- and selects those column values that have changed
  -- it is assumed that the column some_table.id is the primary key 
  select nd.id, x.*
  from new_data nd
    join old_data od using (id)
    join lateral (
      select nd.id, n.col as column_name, o.value as old_column_value, n.value as new_column_value
      from jsonb_each_text(nd.new_value) as n(col, value)
        join jsonb_each_text(od.old_value) as o(col, value) on o.col = n.col and n.value is distinct from o.value 
    ) x on x.id = nd.id
)
-- now insert the result of the previous comparison into the audit table
insert into audit_details (updated_table, updated_column, query, value_before_update, value_after_update)
select 'some_table', column_name, old_column_value, new_column_value
from changed_column_values

Online example


虽然上面的代码有效,但它非常丑陋并且容易出错,只是为了捕获单个 UPDATE 语句的更改。

我会使用可以找到的许多现成的通用审计解决方案之一 here or here or here 并将通用触发器仅附加到那些 table 您需要它的地方。

或扩展触发器功能以检查例如一个 configuration setting and only store the changes if the property is set to e.g. true. Then if you want to "debug" your statements turn on the audit logging (set session ....) and turn it off afterwards. You can also create a function for that, similar