2017-09-13 74 views
0

我有一个简单的oracle数据库和一个日志文件。日志文件中的每一行都是唯一的。有很多线路(~1百万)。 我需要使用文件中的最后一行作为插入语句的一部分。PL/SQL获取文件中的最后一行,避免循环

获取文件正常工作:

F1 := UTL_FILE.FOPEN('USER_DIR','log.txt','R'); 

把里面的循环工作方式在文件中的每一行都是唯一的,所以我知道,如果我已经添加了行了或不:

loop 
BEGIN 
UTL_FILE.GET_LINE(F1,VX); 
-- do action 
EXCEPTION WHEN No_Data_Found THEN EXIT; END 
end loop; 

但是,这似乎可怕的效率低下,因为我要阅读文件中的每一行,即使我知道我只关心最后一行。这避免了环路,只是

出了点:

UTL_FILE.GET_LAST_LINE(F1,VX) 
-- do action 

将是巨大的。我确定有这样的构造或东西,但我找不到它。如果这很重要的话,那就是Oracle11g。

回答

3

对此文章有帮助吗?

UTL_FILE - Random Access of Files

的FGETATTR程序允许我们检查文件是否存在,并 返回文件长度。然后,我们使用正常的GET_LINE 过程读取第一行。为了得到最后一行,我们需要使用FSEEK过程跳到文件末尾 并向后工作,直到我们点击 行终止符。 GET_LINE过程不会返回行 终止符,因此我们通过检查 空行的返回来检测它的存在。然后我们可以显示最后一行。

SET SERVEROUTPUT ON SIZE 1000000 
DECLARE 
    l_file   UTL_FILE.file_type; 
    l_location  VARCHAR2(100) := 'MY_DOCS'; 
    l_filename  VARCHAR2(100) := 'temp'; 
    l_exists  BOOLEAN; 
    l_file_length NUMBER; 
    l_blocksize NUMBER; 
    l_text   VARCHAR2(32767); 
BEGIN 
    UTL_FILE.fgetattr(l_location, l_filename, l_exists, l_file_length, l_blocksize); 

    IF l_exists THEN 
    -- Open file. 
    l_file := UTL_FILE.fopen(l_location, l_filename, 'r', 32767); 

    -- Read and output first line. 
    UTL_FILE.get_line(l_file, l_text, 32767); 
    DBMS_OUTPUT.put_line('First Line: |' || l_text || '|'); 
    UTL_FILE.FSEEK (l_file, l_file_length-1); 

    -- Step backwards through the file until we reach the start of the last line. 
    FOR i IN REVERSE 0 .. l_file_length-2 LOOP 
     UTL_FILE.FSEEK (l_file, NULL, -2); 
     UTL_FILE.get_line(l_file, l_text, 1); 
     EXIT WHEN l_text IS NULL; 
    END LOOP; 

    -- Read and output the last line. 
    UTL_FILE.get_line(l_file, l_text, 32767); 
    DBMS_OUTPUT.put_line('Last Line : |' || l_text || '|'); 

    -- Close the file. 
    UTL_FILE.fclose(l_file); 
    END IF; 
END; 
/
+0

不像我希望那么简单,但它确实有效。谢谢 – Scheme