以下是一个完整的 PostgreSQL 触发器实例,其中包含创建表、插入数据、定义触发器函数以及创建触发器的 SQL 语句。

1. 创建表:
CREATE TABLE employee (
    emp_id SERIAL PRIMARY KEY,
    emp_name VARCHAR(100),
    salary INTEGER
);

2. 插入一些数据:
INSERT INTO employee (emp_name, salary) VALUES
    ('John Doe', 50000),
    ('Jane Smith', 60000),
    ('Bob Johnson', 75000);

3. 创建触发器函数(用 C 编写):
#include "postgres.h"
#include "fmgr.h"
#include "executor/spi.h"

PG_MODULE_MAGIC;

PG_FUNCTION_INFO_V1(update_salary_trigger);

Datum
update_salary_trigger(PG_FUNCTION_ARGS)
{
    TriggerData *trigdata = (TriggerData *) PG_GETARG_POINTER(0);
    TupleDesc tupdesc;
    HeapTuple newtuple;
    Datum *values;
    bool *nulls;

    if (!CALLED_AS_TRIGGER(fcinfo))  /* internal error */
        elog(ERROR, "not fired by trigger manager");

    if (!TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))  /* must be row-level trigger */
        elog(ERROR, "trigger not fired for row events");

    if (TRIGGER_FIRED_BEFORE(trigdata->tg_event))  /* must be BEFORE trigger */
        elog(ERROR, "trigger not fired before event");

    tupdesc = trigdata->tg_relation->rd_att;

    if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
    {
        newtuple = trigdata->tg_newtuple;
    }
    else
    {
        elog(ERROR, "unsupported event type");
        PG_RETURN_NULL();
    }

    SPI_connect();

    values = (Datum *) palloc(tupdesc->natts * sizeof(Datum));
    nulls = (bool *) palloc(tupdesc->natts * sizeof(bool));

    for (int i = 0; i < tupdesc->natts; i++)
    {
        values[i] = SPI_getbinval(newtuple, tupdesc, i + 1, &nulls[i]);
    }

    // Modify the salary field
    if (!nulls[2])  // Assuming salary is the third column
    {
        int *salary = (int *) &(values[2]);
        *salary *= 2;
    }

    // Update the tuple
    SPI_modifytuple(trigdata->tg_relation, newtuple, 1, SPI_modify_update, values, nulls);

    SPI_finish();

    PG_RETURN_NULL();
}

4. 编写 Makefile 文件:
MODULES = update_salary_trigger
PG_CONFIG = pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS)

5. 编译 C 代码并生成共享库:

在命令行中运行 make,它将编译并生成共享库文件 update_salary_trigger.so。

6. 创建触发器:
-- 创建触发器函数
CREATE OR REPLACE FUNCTION update_salary_trigger()
RETURNS TRIGGER AS '$libdir/update_salary_trigger.so'
LANGUAGE C;

-- 创建触发器
CREATE TRIGGER before_update_salary
BEFORE UPDATE ON employee
FOR EACH ROW
EXECUTE FUNCTION update_salary_trigger();

在上述示例中,我们创建了一个表 employee,并向其中插入了一些数据。然后,我们定义了一个触发器函数 update_salary_trigger,该函数会在每次更新 employee 表的数据时将 salary 字段的值加倍。最后,我们创建了一个 BEFORE UPDATE 的触发器 before_update_salary,将其关联到 employee 表上,以在每次更新之前触发。


转载请注明出处:http://www.zyzy.cn/article/detail/8486/PostgreSQL