1

下面描述了我尝试将数据从文件加载到 Linux RedHat 7.2 主机上运行的 PostgreSQL 8.0 数据库的过程。

现在,我的问题是FOR EVERY ROW触发器被调用并且程序正在执行。

但是,我希望它做的是,一旦我输入文件名并根据记录的内容决定是执行一次DUMP BULK DATA还是DUMP WHOLE CSV FILE仅执行一次(在触发器上) ,它会检查我表的相应行.

请帮我解决这个问题...

logfile.tmp的如下:

27/Apr/2013:17:03:42 +0530#192.168.1.3#16#0@#$http://localhost/images/
   banner-left.jpg@#$10.1ff.ff.ff#-#Y#-
27/Apr/2013:17:03:42 +0530#192.168.1.3#16#0@#$http://localhost/images/
   banner-left.jpg@#$10.ff.ff.2ff05#-#Y#-

我正在使用的 COPY 命令:

/usr/local/pgsql/bin/psql localhost -d d1 -U u1 -tc "COPY tblaccesslog ( accesstime, clientip, username, request,bytes, urlpath, url, contenttype, issite, webcatname)  FROM 'logfile.tmp' WITH DELIMITER AS '#';" >> /tmp/parselog.log 2>&1

有问题的触发器 ( insert_accesslog_trigger):

insert_accesslog_trigger BEFORE INSERT ON tblaccesslog FOR EACH ROW EXECUTE PROCEDURE accesslog_insert_trigger()

最后是accesslog_insert_trigger()正在使用的触发函数 ( ):

accesslog_insert_trigger()
DECLARE
        tablemaxtuples NUMERIC(10);
        tableno NUMERIC(10);
        newtable TEXT;
        query TEXT;
        tablecount NUMERIC(10);
        min_limit NUMERIC(10);
        max_limit NUMERIC(10);
BEGIN

        tablemaxtuples := 100000;
    tableno := ( NEW.id - ( NEW.id % tablemaxtuples ) ) / tablemaxtuples +1;
    newtable := 'tblaccesslog'||to_char(CURRENT_DATE,'YYYYMMDD')||'_child_'||tableno;

        SELECT trim(count(tablename)) INTO tablecount FROM pg_tables WHERE tablename=newtable ;
    IF tablecount = 0
    THEN
                min_limit := (tableno-1)*tablemaxtuples;
                max_limit := min_limit + tablemaxtuples;
                                query := 'CREATE TABLE '||newtable||'( PRIMARY KEY (id),CHECK ( id >= '||min_limit||' AND id <'||max_limit||'  ) ) INHERITS (tblaccesslog)';
        EXECUTE query;
     END IF;

    query := 'INSERT INTO '|| newtable ||' ( id, username, clientip, url, accesstime, requestbytes, contenttype, issite, urlpath, webcatname ) VALUES ('||NEW.id||','''||NEW.username||''','''||NEW.clientip||''','''||NEW.url||''','''||NEW.accesstime||''','''||NEW.requestbytes||''','''||NEW.contenttype||''','''||NEW.issite||''','''|| replace(NEW.urlpath,'\'','') ||''','''||NEW.webcatname||''')';
    EXECUTE query;
    RETURN NULL;

END;
4

1 回答 1

2

触发器的PostgreSQL 文档概述清楚地表明,没有适合您要求的触发器类型:FOR EACH ROW触发器,顾名思义,每行执行一次,并且如手册页所述“语句级触发器当前不有任何方法来检查语句修改的各个行。”

但是,您可以做的是将实际COPY命令放入函数中。该函数可以COPY TO是一个临时表,然后执行适当的步骤来确定它应该从那里去哪里。

然后您的复制命令(我猜是在cron工作或类似的工作中)将运行,SELECT bulk_insert_access_log();而不是当前列出的长行。

于 2013-04-27T17:37:07.890 回答