当前位置:早雪网网络学院编程文档数据库技术Postgresql → PostgreSQL7.0手册-程序员手册 -47. 触发器

PostgreSQL7.0手册-程序员手册 -47. 触发器

减小字体 增大字体 作者:不详  来源:supcode.com收集整理  发布时间:2005-7-23 12:21:57
东西--如果你不想用另一条记录覆盖此记录(INSERT)或忽略操作. 
tg_newtuple 
如果是 UPDATE,这是一个指向新版本的记录的指针,如果是 INSERT 或 DELETE,就是 NULL这就是你将返回给执行器的东西-- 如果你是 UPDATE 并且你不想用另一条记录替换这条记录或忽略操作. 
tg_trigger 
是一个指向结构 Trigger 的指针,该结构在 src/include/utils/rel.h 里定义: 
typedef struct Trigger
{
    Oid         tgoid;
    char       *tgname;
    Oid         tgfoid;
    FmgrInfo    tgfunc;
    int16       tgtype;
    bool        tgenabled;
    bool        tgisconstraint;
    bool        tgdeferrable;
    bool        tginitdeferred;
    int16       tgnargs;
    int16       tgattr[FUNC_MAX_ARGS];
    char      **tgargs;
} Trigger;
tgname 是触发器的名称,tgnargs 是在 tgargs 里参数的数量,tgargs 是一个指针数组,数组里每个指针指向在 CREATE TRIGGER 语句里声明的参数.其他成员只在内部使用.

--------------------------------------------------------------------------------
--------------------------------------------------------------------------------

数据改变的可视性
Postgres 数据修改的可视性规则:在查询执行过程中,由查询本身造成的数据修改(通过 SQL-函数,SPI-函数,触发器)对查询扫描而言是不可见的.例如,在查询 
   INSERT INTO a SELECT * FROM a
里,插入的记录对 SELECT 的扫描是不可见的.实际上,这么做在数据库内部形成非递归的数据库表的复制(当然是要受到唯一索引规则的制约的) 
但是请记住在 SPI 文挡里关于可视性的注释: 

由查询 Q 造成的改变可以为查询 Q 以后运行的查询可见,不管这些查询 
是在查询 Q 内部开始运行(在 Q 运行期间)的还是Q运行完毕后开始运行的
这些对触发器而言也是正确的,尽管被插入的记录 (tg_trigtuple)对 BEFORE 触发器是不可见的,这个刚被插入的记录却可以被一个 AFTER 触发器看到,并且对所有这个(触发器)以后的所有 BEFORE/AFTER 触发器均可见!

--------------------------------------------------------------------------------
--------------------------------------------------------------------------------

例子
在 src/test/regress/regress.c 和 contrib/spi 里有更复杂的例子. 
这里是一个非常简单的触发器使用的例子.函数 trigf 报告在被触发的关系 ttest 中记录数量,并且如果查询试图把 NULL 插入到 x 里(例如 -它做为一个 NOT NULL 约束但不退出事务的约束)时略过操作. 

#include "executor/spi.h"       /* this is what you need to work with SPI */
#include "commands/trigger.h"   /* -"- and triggers */

HeapTuple               trigf(void);

HeapTuple
trigf()
{
        TupleDesc       tupdesc;
        HeapTuple       rettuple;
        char            *when;
        bool            checknull = false;
        bool            isnull;
        int             ret, i;

        if (!CurrentTriggerData)
                elog(WARN, "trigf: triggers are not initialized");
        
        /* tuple to return to Executor */
        if (TRIGGER_FIRED_BY_UPDATE(CurrentTriggerData->tg_event))
                rettuple = CurrentTriggerData->tg_newtuple;
        else
                rettuple = CurrentTriggerData->tg_trigtuple;
        
        /* check for NULLs ? */
        if (!TRIGGER_FIRED_BY_DELETE(CurrentTriggerData->tg_event) &&
                TRIGGER_FIRED_BEFORE(CurrentTriggerData->tg_event))
                checknull = true;
        
        if (TRIGGER_FIRED_BEFORE(CurrentTriggerData->tg_event))
                when = "before";
        else
                when = "after ";
        
        tupdesc = CurrentTriggerData->tg_relation->rd_att;
        CurrentTriggerData = NULL;
        
        /* Connect to SPI manager */
        if ((ret = SPI_connect()) < 0)
                elog(WARN, "trigf (fired %s): SPI_connect returned %d", when, ret);
        
        /* Get number of tuples in relation */
        ret = SPI_exec("select count(*) from ttest", 0);
        
        if (ret < 0)
                elog(WARN, "trigf (fired %s): SPI_exec returned %d", when, ret);
        
        i = SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1, &isnull);
        
        elog (NOTICE, "trigf (fired %s): there are %d tuples in ttest", when, i);
        
        SPI_finish();
        
        if (checknull)
        {
                i = SPI_getbinval(rettuple, tupdesc, 1, &isnull);
                if (isnull)
   

上一页  [1] [2] [3]  下一页

[数据载入中...] [返回上一页] [打 印]