将CSV文件中的内容加载到PostgreSQL表中
下面是我尝试将文件中的数据加载到运行在Linux RedHat 7.2主机上的PostgreSQL 8.0数据库中的过程的描述。将CSV文件中的内容加载到PostgreSQL表中
现在,我的问题是FOR EVERY ROW
触发器正在调用并且该过程正在执行。
然而,我希望它做的事情是让它检查我的表的相应行,一旦我给出了文件名,并根据记录的内容决定是否仅执行DUMP BULK DATA
或DUMP WHOLE CSV FILE
一次(在触发器上)。
请帮我解决这个问题...
我logfile.tmp
如下:
27/Apr/2013:17:03:42 +0530#192.168.1.3#16#[email protected]#$http://localhost/images/
[email protected]#$10.1ff.ff.ff#-#Y#-
27/Apr/2013:17:03:42 +0530#192.168.1.3#16#[email protected]#$http://localhost/images/
[email protected]#$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();
而不是当前列出的长行。
这里我的问题是在这个设置中,每次调用触发器都会消耗太多的CPU资源。所以我只想减少它。只有在CRON调用新文件进行转储时才会触发调用。所以临时数据库不能解决我的问题。 – 2013-04-29 05:11:33
可以将触发器定义为在执行任何INSERT,UPDATE或DELETE操作之前或之后执行,可以是每个修改的行执行一次,也可以执行一次“每个SQL语句”。在这个声明中它显示了我可以用SQL调用触发器...所以如何实现它?我想做什么改变? – 2013-04-29 05:15:59
如果您使用为整个语句运行的触发器,则无法访问所插入的数据,正如我已经引用的那样。但是这个*没有任何理由成为触发器 - 只需编写一个自定义函数并从cron运行即可。 – IMSoP 2013-04-29 14:43:51
8.0很老了,可能还没有打补丁的安全问题。请尽快升级。 – 2013-04-28 06:42:37
Red Hat 7.2甚至更老(2001年),可能会有更多的安全问题。您应该尽快将此数据迁移到现代服务器。 – 2013-04-28 21:44:09
我无法升级其中的任何一个人。由于某些原因,只有您可以帮助我完成此配置吗? – 2013-04-29 05:08:02