下面是我写触发器可能要用到的表:--创建统计信息表(触发器要更改的表)
create table td_static (
daysusers integer default 0,     //今日用户数
daysposts integer default 0,     //今日帖子数(所有的回帖和发帖数)
daystopics integer default 0,    //今日主题数(发帖数)
totalusers integer default 0,    //总用户数(从论坛4月13号到现在)
totalposts integer default 0,    //总帖子数(上同)
totaltopics integer default 0,   //总主题数(上同)
datecreated date default sysdate //生成时间(从4月13日,一直显示到今天,一天一条记录)
);
--创建主题信息表(该表用于发帖人发布的帖子信息)
create table td_threads (
threadid integer not null constraint td_threads_pk primary key,      //主题ID
forumid integer not null,    //所属版块
emotionurl varchar2(200),      // 表情url
topic varchar2(200) not null,   //标题
description clob not null,       // 主题描述:即发帖人的帖子标题
author varchar2(50) not null,    //用户名
lastname varchar2(50) not null,  //最后回复的用户
posttime date default sysdate,    //主题发表时间
lasttime date not null,           //最后回复时间
lastvieweddate date not null,     //最后查看日期
isgood integer default 0,         //是否精华帖
threadtop integer default 0,      //是否置顶帖
islocked integer default 0,       //是否锁帖
isdelete integer default 1,       //是否删除
deletedcount integer not null,    //已删除帖子数)
totalviews integer not null,     // 该主题总浏览数
totalreplies integer not null,   //(总回复数
threadstatus integer not null,   //主题状态
ipaddress varchar2(100)          //ip地址列
);
--创建帖子信息表(该表记录回复帖子的帖子信息)
create table td_posts (
postid integer not null constraint td_posts_pk primary key,    //(帖子ID)
threadid  integer not null,        //主题ID:发帖人发布的帖子主题,即帖子标题
postauthor varchar2(50) not null,  //作者
subject varchar2(200) not null,    //标题
body clob not null,               // 正文内容
ipaddress varchar2(50) not null,  //IP地址
isdelete integer default 1,      // 删除标记
postdate date default sysdate    //创建时间
);--创建用户在线信息表
create table td_useronline (
forumid integer not null,                //论坛ID
sessionid varchar2(200) not null,       //SessionID
username varchar2(50) not null,         //用户名称
ipaddress varchar2(50) not null,        //IP地址
forumname varchar2(50) not null,        //所在论坛
threadid integer not null,              //当前所在主题ID
topic varchar2(200) not null,           //当前所在主题
cometime date default sysdate,          //来访时间
lasttime date not null                  //最后更新时间
);--创建用户信息表(该表只列部分中文说明,其他与该触发器没关系,故不列)
create table td_users (
userid integer not null constraint td_users_pk primary key,         // 用户ID
uname  varchar2(50) not null,        //用户名
upassword varchar2(50) not null,     //用户密码
usex integer default 0,              //性别
uroleid integer not null,
webaddress varchar2(200),
gallery varchar2(200),
urank varchar2(50) not null,
newmessage integer default 0,
totalposts integer default 0,      //发表帖数
umoney integer default 0,
experience integer default 0,
ufaceurl varchar2(200) not null,
regip varchar2(50) not null,
actip varchar2(50) not null,
regtime date default sysdate,   //注册日期
posttime date,                  //发帖日期
lastacttime date not null,      //最后活动日期
utitle varchar2(200),
actday integer not null,       //用户活跃天数
usign varchar2(200),
uinfo varchar2(200),
isonline integer default 0     //是否在线
);   我现在想写个触发器,想随时更新统计信息表td_static中所有的字段,比如用户登录一次,今日用户数+1,,用户发布帖子一次,今日主题数目+1且今日帖子数+1,回复贴子一次,今日帖子数+1,都会而且应该激活触发器,更新统计信息表td_static中所有的字段。但是,我不会写,结果我的统计信息表在页面显示出了时间以外,其他字段信息全部是0。
高手帮忙,这个触发器该如何写啊?

解决方案 »

  1.   

    --自己调试一下
    CREATE OR REPLACE TRIGGER tr_td_useronline
      AFTER INSERT ON td_useronline
      FOR EACH ROW
    DECLARE
      v_cnt        NUMBER;
      v_totalusers NUMBER;
    BEGIN
      --查询今天的统计记录
      SELECT COUNT(*)
        INTO v_cnt
        FROM td_static t
       WHERE t.datecreated >= trunc(SYSDATE)
         AND t.datecreated < trunc(SYSDATE) + 1;
      --判断是否有统计记录
      IF v_cnt = 0 THEN
        --没有统计记录,先插入一条统计计录,
        --总计字段的初始值为上一最大创建日期的总计值
        BEGIN
          SELECT a.totalusers
            INTO v_totalusers
            FROM td_static a
           WHERE a.datecreated = (SELECT MAX(t.datecreated) FROM td_static t);
        EXCEPTION
          WHEN OTHERS THEN
            v_totalusers := 0;
        END;
        INSERT INTO td_static
          (datecreated, daysusers, totalusers)
        VALUES
          (trunc(SYSDATE), 1, v_totalusers + 1);
      ELSE
        --有统计记录,直接更新
        UPDATE td_static t
           SET t.daysusers = t.daysusers + 1, t.totalusers = t.totalusers + 1
         WHERE t.datecreated >= trunc(SYSDATE)
           AND t.datecreated < trunc(SYSDATE) + 1;
      END IF;
    END;
    /CREATE OR REPLACE TRIGGER tr_td_threads
      AFTER INSERT ON td_threads
      FOR EACH ROW
    DECLARE
      v_cnt         NUMBER;
      v_totalposts  NUMBER;
      v_totaltopics NUMBER;
    BEGIN
      SELECT COUNT(*)
        INTO v_cnt
        FROM td_static t
       WHERE t.datecreated >= trunc(SYSDATE)
         AND t.datecreated < trunc(SYSDATE) + 1;
      IF v_cnt = 0 THEN
        BEGIN
          SELECT a.totalposts, a.totaltopics
            INTO v_totalposts, v_totaltopics
            FROM td_static a
           WHERE a.datecreated = (SELECT MAX(t.datecreated) FROM td_static t);
        EXCEPTION
          WHEN OTHERS THEN
            v_totalposts  := 0;
            v_totaltopics := 0;
        END;
        INSERT INTO td_static
          (datecreated, daysposts, daystopics, totalposts, totaltopics)
        VALUES
          (trunc(SYSDATE), 1, 1, v_totalposts + 1, v_totaltopics + 1);
      ELSE
        UPDATE td_static t
           SET t.daysposts   = t.daysposts + 1,
               t.daystopics  = t.daystopics + 1,
               t.totalposts  = t.totalposts + 1,
               t.totaltopics = t.totaltopics + 1
         WHERE t.datecreated >= trunc(SYSDATE)
           AND t.datecreated < trunc(SYSDATE) + 1;
      END IF;
    END;
    /CREATE OR REPLACE TRIGGER tr_td_posts
      AFTER INSERT ON td_posts
      FOR EACH ROW
    DECLARE
      v_cnt        NUMBER;
      v_totalposts NUMBER;
    BEGIN
      SELECT COUNT(*)
        INTO v_cnt
        FROM td_static t
       WHERE t.datecreated >= trunc(SYSDATE)
         AND t.datecreated < trunc(SYSDATE) + 1;
      IF v_cnt = 0 THEN
        BEGIN
          SELECT a.totalposts
            INTO v_totalposts
            FROM td_static a
           WHERE a.datecreated = (SELECT MAX(t.datecreated) FROM td_static t);
        EXCEPTION
          WHEN OTHERS THEN
            v_totalposts := 0;
        END;
        INSERT INTO td_static
          (datecreated, daysposts, totalposts)
        VALUES
          (trunc(SYSDATE), 1, v_totalposts + 1);
      ELSE
        UPDATE td_static t
           SET t.daysposts = t.daysposts + 1, t.totalposts = t.totalposts + 1
         WHERE t.datecreated >= trunc(SYSDATE)
           AND t.datecreated < trunc(SYSDATE) + 1;
      END IF;
    END;
    /
      

  2.   

    不要急时抱佛脚啊,磨刀不误砍柴功,多看看书,
    推荐一本书《精通Oracle 10g PL/SQL编程》
      

  3.   

    tangren,谢谢你!你的触发器基本没什么问题,就是totalusers integer default 0, //总用户数  这个没有改变,还是为0!我在自己改改看啊!
      

  4.   


    统计信息表(触发器要更改的表)
    create table td_static (
    daysusers integer default 0, //今日用户数
    daysposts integer default 0, //今日帖子数(所有的回帖和发帖数)
    daystopics integer default 0, //今日主题数(发帖数)
    totalusers integer default 0, //总用户数(从论坛4月13号到现在)
    totalposts integer default 0, //总帖子数(上同)
    totaltopics integer default 0, //总主题数(上同)
    datecreated date default sysdate //生成时间(从4月13日,一直显示到今天,一天一条记录)
    );
    唐大哥,比如今天是5月28日,今天的总用户数目=表td_static 5月27号记录中的totalusers +今天的daysusers,                    现在的totalusers=229;
    或者
    今天的总用户数=5月28号以前所有的今日用户daysusers之和+5月28日今日用户daysusers;

    唐大哥,小弟还是没写出来,望你帮忙啊!
      

  5.   

    不好意思,更正一下:
    昨天的(5月27日)totalusers=229
      

  6.   

    --用这个脚本执行一次,初始化一下totalusers字段数据,然后看看。
    DELETE FROM td_static t WHERE t.datecreated >= trunc(SYSDATE) + 1;
    UPDATE td_static a
       SET a.totalusers =
           (SELECT totalusers
              FROM (SELECT t.datecreated,
                           SUM(t.daysusers) over(ORDER BY t.datecreated) totalusers
                      FROM td_static t) b
             WHERE b.datecreated = a.datecreated);
    COMMIT;
      

  7.   


    初始化totalusers字段数据
    ,到目前为止,一共有240个用户,我采用如下方法更新,怎么没有选中了
    {0}SQL> update td_static
      2  set totalusers=240
      3  where datecreated=to_date('2011-5-29','yyyy-mm-dd');已更新0行。 我以为跟今天有关,今天不能更新,要等到明天,所以我更新昨天的,结果昨天也不能更新,这是为什么了?
    {0}
    SQL> update td_static
      2  set totalusers=238
      3  where datecreated=to_date('2011-5-28','yyyy-mm-dd');已更新0行。 
    唐大哥,这是怎么回事了?                 *
      

  8.   

    唐大哥,这是你脚本的执行结果:
    {0}
    SQL> DELETE FROM td_static t WHERE t.datecreated >= trunc(SYSDATE) + 1;已删除0行。SQL> UPDATE td_static a
      2     SET a.totalusers =
      3         (SELECT totalusers
      4            FROM (SELECT t.datecreated,
      5                         SUM(t.daysusers) over(ORDER BY t.datecreated) totalu
    sers
      6                    FROM td_static t) b
      7           WHERE b.datecreated = a.datecreated);已更新23行。SQL> COMMIT;提交完成。
     有个疑问:
    为什么是删除0行?
    我原来从4月到5月的总用户数一下子从0恢复到了正常了,可是我明明在
    SQL> update td_static
      2  set totalusers=238
      3  where datecreated=to_date('2011-5-28','yyyy-mm-dd');已更新0行。只更新了0行了,怎么就全都正确了?
      

  9.   

    1、本来一开始,如果td_static中记录全部由触发器来生成,而不是手动生成,
       就没有问题的。但是你手动生成了一部分记录,但又没有手动汇总。
    2、删除当天以后的记录,避免初始化手动生成了过多的数据,避免触发器出错。
       delete只是一个保证,删除0条表明你没有手工初始多余的数据。
    3、更新0行,你自己写的这条update语句条件不成立。检查一下。
      

  10.   


    唐大哥,我现在的问题是:
    5月30号以后的totalusers又变成0了,而5月30号以前的数据正常了,我现在不敢随便该了,明天就要验收了,大哥,该怎么办了?
      

  11.   

    “5月30号以后的totalusers又变成0了,而5月30号以前的数据正常了”
    认真检查一下,你确定这个真的又问题????????????????
      

  12.   


    下面是页面显示的部分数据,最后一列是:totalusers

    2011-05-27  0  0  12  0  0  229  
    2011-05-28  2  3  9  2  3  238  
    2011-05-29  1  1  4  1  1  240  
    2011-05-30  2  3  4  2  3  0  
    2011-06-02  3  7  31  3  7  0  我不知道tangren 什么时候能来啊,我明天一大清早就要验收了,等不起啊!
    陈大哥,那你帮忙我看看这个更新语句:
     update td_static
      2 set totalusers=244  
    3 where datecreated=to_date('2011-5-30','yyyy-mm-dd');到底是哪里出错了,为什么只更新了0行???
      

  13.   

    更新0行,表名并没有符合条件的数据可以更新,
    你的datecreated字段存储格式是什么?日期格式:yyyy-mm-dd
      

  14.   


    这是我的表:
    create table td_static (
    daysusers integer default 0, //今日用户数
    daysposts integer default 0, //今日帖子数(所有的回帖和发帖数)
    daystopics integer default 0, //今日主题数(发帖数)
    totalusers integer default 0, //总用户数(从论坛4月13号到现在)
    totalposts integer default 0, //总帖子数(上同)
    totaltopics integer default 0, //总主题数(上同)
    datecreated date default sysdate //生成时间);我就是这个时间的赋值不会啊!
      

  15.   

    datecreated date default sysdate
    这里默认为当前系统时间,所以你更新0行呢!
    这个等式用永远不成立:datecreated=to_date('2011-5-30','yyyy-mm-dd');
      

  16.   


    我按照你的思路,现在对了。
    但是,明天验收不会又出现问题吧?
    如果出现问题了,是不是又用这个脚本初始化一下就行了,tangren?