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

标签 postgresql plpgsql bulkinsert database-partitioning psql

下面描述了我尝试将文件中的数据加载到运行在 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;

最佳答案

PostgreSQL documentation overview of triggers明确表示没有适合您要求的触发器类型:正如其名称所示,FOR EACH ROW 触发器将为每一行执行一次,正如手册页所述“语句级触发器目前没有任何方法来检查语句修改的单个行。”

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

然后你的复制命令(我猜是在 cron 作业或类似的)将只运行 SELECT bulk_insert_access_log(); 而不是当前列出的长行.

关于postgresql - 将 CSV 文件中的内容加载到 PostgreSQL 表中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16251980/

相关文章:

postgresql - 如何返回表的行类型加上函数的附加列?

c# - 在 Entity Framework 6 中的 BulkInsert 期间在上下文中找不到类型

sql-server - Sql Bulk insert XML格式文件,终止符中带双引号

node.js - Sequelize – 多对多关联

postgresql - PostgreSQL从声明的表中插入(存储过程或函数)

sql - 设置变量时,记录的 IS NOT NULL 测试不返回 TRUE

postgresql - 动态 SQL 中的参数串联

database - 如何自动化 postgres 函数和 View 的导入和导出

SQL UNION 问题

sql-server - 批量插入返回错误 "Access is denied"