将CSV文件中的内容加载到PostgreSQL表中

将CSV文件中的内容加载到PostgreSQL表中,postgresql,plpgsql,bulkinsert,database-partitioning,psql,Postgresql,Plpgsql,Bulkinsert,Database Partitioning,Psql,下面是我尝试将数据从文件加载到运行在Linux RedHat 7.2主机上的PostgreSQL 8.0数据库的过程的描述 现在,我的问题是调用了每行的触发器,并且过程正在执行 但是,我希望它在输入文件名后检查表中的相应行,并根据记录内容决定是转储批量数据,还是仅转储整个CSV文件一次(在触发器上) 请帮我解决这个问题 我的logfile.tmp如下所示: 27/Apr/2013:17:03:42 +0530#192.168.1.3#16#0@#$http://localhost/images/

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

现在,我的问题是调用了每行的
触发器,并且过程正在执行

但是,我希望它在输入文件名后检查表中的相应行,并根据记录内容决定是
转储批量数据
,还是
仅转储整个CSV文件一次(在触发器上)

请帮我解决这个问题

我的
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#-
我正在使用的复制命令:

/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\u accesslog\u trigger
):

insert_accesslog_trigger BEFORE INSERT ON tblaccesslog FOR EACH ROW EXECUTE PROCEDURE accesslog_insert_trigger()
最后是正在使用的触发器函数(
accesslog\u insert\u 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;
accesslog\u insert\u触发器()
声明
tablemaxtuples数字(10);
表号(10);
新文本;
查询文本;
tablecount数字(10);
最小极限数值(10);
最大极限数值(10);
开始
tablemaxtuples:=100000;
tableno:=(NEW.id-(NEW.id%tablemaxtuples))/tablemaxtuples+1;
新表:='tblaccesslog'| | to| char(当前|u日期,'YYYYMMDD')| | | | | |表号;
从tablename=newtable的pg_tables中选择trim(count(tablename))进入tablencount;
如果tablecount=0
然后
最小限制:=(tableno-1)*tablemaxtuples;
最大限制:=最小限制+tablemaxtuples;
query:='CREATE TABLE'| | newtable | |'(主键(id),CHECK(id>='| | | min| | | u limit | | | | | | |和id明确说明没有适合您需求的触发器类型:如其名称所示,每行将执行一次
,如手册页面所述“语句级触发器当前无法检查由语句修改的各行。”

但是,您可以将实际的
COPY
命令放在函数中。函数可以
复制到一个临时表中,然后执行适当的步骤来确定它应该从那里开始


然后,您的复制命令(我猜是在
cron
作业或类似作业中)将只运行
SELECT bulk\u insert\u access\u log();
,而不是当前列出的长行。

8.0非常旧,可能存在未修补的安全问题。请尽快升级。Red Hat 7.2更旧(2001)可能会有更多的安全问题。你应该尽快将此数据迁移到现代服务器。我无法升级其中任何一个。由于某些原因。你能帮我完成此配置吗?我的问题是此设置每次调用触发器都会占用太多CPU。因此我只想减少它。仅使用调用触发器w当CRON调用要转储的新文件时。因此临时数据库无法解决我的问题。可以定义触发器在任何插入、更新或删除操作之前或之后执行,每个修改的行执行一次,或每个SQL语句执行一次".在这个语句中,它显示了我可以用SQL调用调用触发器…那么如何实现它呢?我想做些什么更改?如果你使用一个为整个语句运行的触发器,你就不能访问插入的数据,正如我已经引用的那样。但是没有理由这必须是一个触发器-只需编写一个自定义函数并运行它我认为这是更好的方法..在PSQL中有没有什么方法可以让我知道最后更新的表是哪一个?我想在哪一个表中添加下一个即将到来的数据?你可以跟踪另一个表中使用的最后一个表-类似于
从分区表信息中选择max(分区号)+1
。。。