You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL中替代SQL Server Instead of Trigger的Inserted表实现咨询

在PostgreSQL中实现链式哈希的批量插入拦截(简易区块链数据验证)

嘿,我刚好折腾过类似的需求,给你捋清楚PostgreSQL里怎么实现这个链式哈希的批量插入逻辑——毕竟要搞简易区块链,核心就是每条记录的哈希得跟前面的记录串起来对吧?

首先得明确:PostgreSQL里没有像SQL Server那样的INSTEAD OF INSERT触发器(这个只能用在视图上),但我们可以用BEFORE INSERT触发器来达到同样的效果:拦截插入请求,计算链式哈希后再把修改后的记录插入表中。而且批量插入的场景也完全能覆盖,下面是具体步骤:

1. 先准备哈希计算的依赖

PostgreSQL本身没有内置的SHA256哈希函数,得先启用pgcrypto扩展:

CREATE EXTENSION IF NOT EXISTS pgcrypto;

2. 创建区块链数据表格

我们需要一个表来存储数据、前一条记录的哈希,以及当前记录的哈希:

CREATE TABLE blockchain_data (
    id SERIAL PRIMARY KEY,
    payload TEXT NOT NULL, -- 这里放你要存储的实际业务数据
    prev_hash VARCHAR(64) NOT NULL, -- 前一条记录的哈希值
    current_hash VARCHAR(64) NOT NULL, -- 当前记录的哈希(包含prev_hash)
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

3. 编写触发器函数处理哈希计算

这个函数是核心,它会在每条记录插入前自动计算链式哈希:

CREATE OR REPLACE FUNCTION generate_chain_hash()
RETURNS TRIGGER AS $$
DECLARE
    last_record_hash VARCHAR(64);
BEGIN
    -- 获取表中最后一条记录的哈希,如果表是空的就用初始种子(空字符串的SHA256)
    SELECT current_hash INTO last_record_hash
    FROM blockchain_data
    ORDER BY id DESC
    LIMIT 1
    FOR UPDATE; -- 加锁防止并发插入时出现哈希分叉

    -- 处理第一条记录的情况
    IF last_record_hash IS NULL THEN
        last_record_hash = encode(digest('', 'sha256'), 'hex');
    END IF;

    -- 给当前要插入的记录设置前哈希
    NEW.prev_hash = last_record_hash;
    -- 计算当前记录的哈希:把业务数据和前哈希拼接后做SHA256哈希
    NEW.current_hash = encode(digest(NEW.payload || last_record_hash, 'sha256'), 'hex');

    RETURN NEW; -- 返回修改后的记录,触发器会把这条记录插入表中
END;
$$ LANGUAGE plpgsql;

这里要注意FOR UPDATE的作用:如果有多个并发插入请求,加锁能保证同一时间只有一个事务能获取最后一条记录的哈希,避免出现两条记录共用同一个prev_hash导致区块链分叉的问题。

4. 创建触发器绑定函数

把上面的函数绑定到blockchain_data表的插入事件上:

CREATE TRIGGER trigger_before_insert_blockchain
BEFORE INSERT ON blockchain_data
FOR EACH ROW
EXECUTE FUNCTION generate_chain_hash();

FOR EACH ROW意味着批量插入时每一条记录都会触发这个函数,而且同一事务里前面插入的记录的哈希会立即被后面的记录获取到,完美支持批量插入的链式计算。

5. 测试验证

现在可以试试批量插入,看看哈希链是否正常:

-- 先插入第一条记录
INSERT INTO blockchain_data (payload) VALUES ('初始测试数据');

-- 批量插入多条记录
INSERT INTO blockchain_data (payload) VALUES 
    ('第二条业务数据'),
    ('第三条业务数据'),
    ('第四条业务数据');

查询验证哈希链:

SELECT id, payload, prev_hash, current_hash FROM blockchain_data;

你会看到每条记录的prev_hash都严格等于上一条记录的current_hash,完全符合区块链的链式哈希要求。

额外说明

如果你的业务数据不是文本类型,比如是JSON或者其他格式,只需要修改digest()函数里的拼接逻辑就行——把业务数据转换成字符串再和prev_hash拼接即可。

内容的提问来源于stack exchange,提问作者Ryan Fisch

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:58:01