【问题标题】:Read data from a text file and pass that data in a stored procedure input parameter using pl/sql scripts only仅使用 pl/sql 脚本从文本文件中读取数据并在存储过程输入参数中传递该数据
【发布时间】:2021-10-21 17:28:57
【问题描述】:

我有一个包含以下数据的文本文件“C:\file\Datafile.txt”。

1,Dixon,200
2,Sam,400
3,Peter,200

现在我在 oracle 中有一个 SP,它接受三个输入参数(employeeid、employeename、salary)。

我想将该文本文件中的值作为输入参数一一传递给此存储过程。

如果可能,请分享任何 pl/sql 脚本以进行此活动。

【问题讨论】:

  • 文件是否在数据库服务器的文件系统中?还是客户?
  • 最简单的方法是生成一个 PL/SQL 块,调用该过程作为每行的 Excel 公式,然后复制整个列并传递给 SQL Developer、SQL*Plus 或任何其他 SQL 客户端零开发工作。或者对 python/cmd/powershell 或任何其他脚本语言执行相同的操作。它不需要对数据库文件系统的任何访问
  • 我猜 txt 文件在您的笔记本电脑中,而不是在数据库服务器中。请澄清这一点。如果您可以选择将此文件放在数据库服务器中,那么它会很容易做到。如果没有,我建议使用 python 读取文件并使用 cx_Oracle 调用该过程。
  • 文件在数据库服务器中
  • 由于有问题的文件在数据库服务器上,请检查定义/使用External Table

标签: oracle plsql plsqldeveloper plsql-package


【解决方案1】:

正如您所说,该文件位于数据库服务器上,您想使用UTL_FILE,然后以特权用户身份连接(例如SYS,如果您没有其他用户)并

  • 创建目录(指向文件系统目录的 Oracle 对象)
  • 将其读取(和/或写入)权限授予将使用它的用户

为什么?因为UTL_FILE(以及例如外部表功能,如果您选择使用它)需要 目录。而 SQL*Loader 则不会 - 有了它,文件可以驻留在本地 PC 上,而不是数据库服务器上。

SQL> show user
USER is "SYS"
SQL> create directory ext_dir as 'c:\temp';

Directory created.

SQL> grant read, write on directory ext_dir to scott;

Grant succeeded.

SQL> grant execute on utl_file to scott;

Grant succeeded.

现在,以用户身份连接(在我的情况下为scott)并使用您指定的输入文件(c:\temp\datafile.txt),其内容为

1,Dixon,200
2,Sam,400
3,Peter,200

执行以下操作:

SQL> create table test (id number, name varchar2(10), salary number);

Table created.

SQL> declare
  2    l_file  utl_file.file_type;
  3    l_line  varchar2(50);
  4  begin
  5    l_file := utl_file.fopen('EXT_DIR', 'datafile.txt', 'R');
  6
  7    loop
  8      begin
  9        utl_file.get_line(l_file, l_line);
 10
 11        insert into test (id, name, salary) values
 12          (substr(l_line, 1, instr(l_line, ',', 1, 1) - 1),
 13           substr(l_line, instr(l_line, ',', 1, 1) + 1,
 14                          instr(l_line, ',', 1, 2) - instr(l_line, ',', 1, 1) - 1),
 15           substr(l_line, instr(l_line, ',', 1, 2) + 1)
 16          );
 17      exception
 18        when no_data_found then exit;
 19      end;
 20    end loop;
 21
 22    utl_file.fclose(l_file);
 23  end;
 24  /

PL/SQL procedure successfully completed.

结果:

SQL> select * from test;

        ID NAME           SALARY
---------- ---------- ----------
         1 Dixon             200
         2 Sam               400
         3 Peter             200

SQL>

我觉得不错。

【讨论】:

    【解决方案2】:

    如何在 oracle 开发者中启用 UTL_FILE 包,请告诉我?

    我正在考虑实施以下解决方案。

    CREATE OR REPLACE PROCEDURE LoadFromFileData(p_FileDir IN VARCHAR2,p_FileName IN VARCHAR2)
    AS
        v_FileHandle UTL_FILE.FILE_TYPE;
        v NewLine VARCHAR2(100); -- Input line
        v_Column1 VARCHAR2(100);
        v_Column2 VARCHAR2(100);
        v_Column3 VARCHAR2(100);
        v_FirstConna NUMBER;
        v_SecondComma NUMBER;
        p_TotalInserted NUMBER;
    
    BEGIN
        v_FileHandle := UTL_FILE.FOPEN(p_FileDir ,p_FileName, 'r');
        p_TotalInserted := 1;
        LOOP
        BEGIN
        UTL_FILE.GET_LINE(v_FileHandle, v NewLine);
        EXCEPTION   WHEN NO_DATA_FOUND THEN
        EXIT;
        END;
    
        v_FirstComma := INSTR(v NewLine, ',', 1, 1);
        v_SecondComma := INSTR(v NewLine, ',', 1, 2);
    
        v_Column1 := SUBSTR(v NewLine, 1, v_FirstComma - 1);
        v_Column2 := SUBSTR(v RewLine, v_FirstConma + 1, v_SecondComma - v_FirstComma - 1);
        v_Column3 := SUBSTR(v Ne;Line, v_SecondConna + 1);
    INSERT INTO LECTURER (ID, First_Name, Last_Nane, Major) VALUES (p_TotalInserted, TO_CHAR(v_Column1), TO_CHAR(v_Column2), TO_CHAR(v_Column3));
    p_Totallnserted := p_TotalInserted + 1;
    END LOOP;
    UTL FILE.FCLOSE(v_FileHandle); COMMIT;
    EXCEPTION
    WHEN UTL FILE. INVALID OPERATION THEN 
    UTL FIEE.FCLOSE(v FileHandle);
    COMMIT;
    EXCEPTION
    DBMS_OUTPUT.put_line('Uncessusful');
    END LoadLecturerData;
    

    【讨论】:

    • 连接为 sys(sys as sysdba);将 utl_file 上的执行权限授予 ;
    猜你喜欢
    • 1970-01-01
    • 2021-12-30
    • 2016-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多