【发布时间】:2015-11-03 15:25:21
【问题描述】:
我编写了下面的存储过程,用于读取移动到服务器上的逗号分隔文件(“DIR”文件夹),并且在执行脚本时,它基本上解析文件(.csv),并将数据分配给它相应的变量(xJOB_ID、xCTRL_ID、xACCT_SEC、xCREATEDON_DATE),以便我可以将数据插入表中。
我在 Windows 7 环境中使用 Oracle SQL Developer 版本 4.0.0.13。幸运的是,在将我的头撞在桌子上几次之后,代码可以正常工作,并且我在运行脚本时没有遇到任何问题。
文件格式示例:
1111, 2, T, 10/10/2000
2222、12345、U、2001 年 10 月 10 日
5555, 123, S, 10/10/1999
我的问题:
我发现使用 SUBSTRING 和 INSTRING 函数来解析数据有点困难,我想知道如何改进脚本,以便在需要进行一些调试时,对于没有编写存储过程的人来说可以轻松解决。
请让我知道这是否有意义。我给了你整个脚本,这样你就可以理解我想要完成的工作,以便我可以改进代码以进行调试。
create or replace PROCEDURE SP_INSERT_INTO_TABLE(xFILE_NAME IN VARCHAR2)
IS
--UTL_FILE is an oracle package that allows you to read and write operating system files.
TEXT_DATA UTL_FILE.FILE_TYPE;
v_ROW_LENGTH NUMBER := 1024;
v_TEXTSTRING VARCHAR2(4000);
cLINE VARCHAR2(100);
xJOB_ID NUMBER;
xCTRL_ID NUMBER;
xACCT_SEC VARCHAR2(1);
xCREATEDON_DATE DATE;
xCOUNT NUMBER := 0;
BEGIN
BEGIN
--Streams in the file data and assigns it to TEXT_DATA variable.
TEXT_DATA := UTL_FILE.FOPEN('DIR', xFILE_NAME, 'R', v_ROW_LENGTH);
END;
--Begin LOOP to get each line and assign to cLINE to extract, assign to each variable, and insert into the table
LOOP
BEGIN
--Gets each string/line up to the line terminator
UTL_FILE.GET_LINE(TEXT_DATA, v_TEXTSTRING);
EXCEPTION
WHEN NO_DATA_FOUND THEN
EXIT;
END;
--Each line is assigned to the variable cLINE.
cLINE := v_TEXTSTRING;
--Begin to parse data using SUBSTRING and INSTRING functions
BEGIN
--Extracts string from cLINE position 1 up to the first occurrence, converts it to a number, and assigns it to the variable.
xJOB_ID := TO_NUMBER(SUBSTR(cLINE, 1,INSTR(cLINE, ',', 1, 1)-1));
--Extracts string from cLINE between the 1st and 2nd occurrence, converts it to a number, and assigns it to the variable.
xCTRL_ID := TO_NUMBER(SUBSTR(cLINE, INSTR(cLINE, ',', 1, 1)+1, INSTR(cLINE, ',', 1,2)-INSTR(cLINE, ',', 1,1)-1));
--Extracts string from cLINE between the 2nd and 3rd occurrence and assigns it to the variable.
xACCT_SEC := SUBSTR(cLINE, INSTR(cLINE, ',', 1, 2) +1, INSTR(cLINE, ',', 1,3)-INSTR(cLINE, ',', 1,2) -1);
--Extracts string from cLINE after the last occurrence, converts it to a date, and assigns it the variable.
xCREATEDON_DATE := TO_DATE(SUBSTR(cLINE, INSTR(cLINE, ',', 1, 3)+1), 'MM/DD/YYYY');
INSERT INTO TABLE(JOB_ID, CTRL_ID, ACCT_SEC, CREATEDON_DATE)
VALUES(xJOB_ID, xCTRL_ID, xACCT_SEC, xCREATEDON_DATE);
COMMIT;
--Counter to count the amount of inserts
xCOUNT := xCOUNT + 1;
EXCEPTION
--Exception to handle the conversion of a string to a NUMBER or value is longer than the declared length of the variable.
WHEN VALUE_ERROR THEN
NULL;
END;
END LOOP;
DBMS_OUTPUT.PUT_LINE('RECORDS INSERTED: ' || xCOUNT);
UTL_FILE.FCLOSE(TEXT_DATA);
END;
【问题讨论】:
-
您是否有理由创建自己的解决方案,而不是使用SQL*Loader 或external table 将文件加载到表中?该文件已经在服务器上并且在一个可识别的目录中,因此外部表似乎是最简单的方法。
-
@AlexPoole - 老实说,不知道 SQL*Loader 并且不确定我将如何使用它,我确实想到了一个外部表,但是当我运行 ' 时似乎总是遇到问题SELECT * FROM EXTERNAL_TABLE' 针对 .CSV 文件(也许我会很快再次解决这个问题,并进一步敲击我的头)。做SP让我的生活变得困难了吗?谢谢!
-
好点,@AlexPoole!外部表 FTW! \o/ (并且插入变为
insert into table_name (...) select ... from external_table_name;的额外好处非常容易调试......) -
外部表通常不需要任何头疼...尽管基于外部表的答案不适合您的要求。我建议您尝试这种方法,如果您遇到困难,请单独提出一个问题?
-
@NewComer - 如果您需要有关外部表的帮助,我认为您应该提出一个新问题; boneist 已经为您最初提出的问题提供了答案,您可能还会得到其他人的答案;它们可能对未来的访问者有所帮助。
标签: plsql oracle11g plsqldeveloper