需要在PL / SQL

时间:2017-07-06 09:12:08

标签: csv plsql

我需要阅读包含转义字符的CSV文件内容。 csv文件规范如下:

1.  File Encoding UTF-8
2.  First line will contain the header information
3.  MS-DOS-style lines that end with (CR/LF) characters (optional for the last line)
4.  The delimiter character will be the semi-colon “;”
5.  Each record must contain the same number of separated fields.
6.  Any field may be quoted (with double quotes).
7.  Fields containing a line-break, double-quote, and/or delimiter character should be quoted. (If they are not, the file will likely
be impossible to process correctly).
8.  A (double) quote character in a field must be represented by two (double) quote characters.

在PL / SQL中实现此功能的最佳方法是什么。 以下是我目前使用的程序:

   PROCEDURE parse_csv(
    i_csvline IN VARCHAR2,
    p_delim   IN            VARCHAR2 DEFAULT ',',
    p_optionally_enclosed IN VARCHAR2 DEFAULT '"',
    o_namelist OUT dimension.NAMELIST )
IS
  --
  CARRIAGE_RETURN CONSTANT CHAR(1) := chr(13);
  LINE_FEED       CONSTANT CHAR(1) := chr(10);
  --
  l_char           CHAR(1);
  l_lookahead      CHAR(1);
  l_pos            NUMBER          := 0;
  l_token          VARCHAR2(32767) := NULL;
  l_token_complete BOOLEAN         := false;
  l_line_complete  BOOLEAN         := false;
  l_new_token      BOOLEAN         := true;
  l_enclosed       BOOLEAN         := false;
  --
  l_lineno   NUMBER             := 1;
  l_columnno NUMBER             := 1;
  v_namelist dimension.NAMELIST :=dimension.NAMELIST();
BEGIN
  LOOP
    l_pos := l_pos + 1;
    l_char := dbms_lob.substr( i_csvline, 1, l_pos);
    EXIT
  WHEN l_char IS NULL OR l_pos > dbms_lob.getLength( i_csvline );
    IF l_new_token AND l_char = p_optionally_enclosed THEN
      l_enclosed             := true;
      l_pos                  := l_pos + 1;
      l_char                 := dbms_lob.substr( i_csvline, 1, l_pos);
    END IF;
    l_new_token := false;
    l_lookahead := dbms_lob.substr( i_csvline, 1, l_pos+1 );
    IF l_char             = p_optionally_enclosed AND l_enclosed THEN
      IF l_lookahead      = p_optionally_enclosed THEN
        l_pos            := l_pos + 1;
        l_token          := l_token || l_lookahead;
      elsif l_lookahead   = p_delim THEN
        l_pos            := l_pos + 1;
        l_token_complete := true;
      ELSE
        l_enclosed := false;
      END IF;
    elsif l_char IN ( CARRIAGE_RETURN, LINE_FEED ) AND NOT l_enclosed THEN
      l_token_complete := true;
      l_line_complete  := true;
      IF l_lookahead  IN ( CARRIAGE_RETURN, LINE_FEED ) THEN
        l_pos := l_pos + 1;
      END IF;
    elsif l_char        = p_delim AND NOT l_enclosed THEN
      l_token_complete := true;
    elsif l_pos         = dbms_lob.getLength( i_csvline ) THEN
      l_token          := l_token || l_char;
      l_token_complete := true;
      l_line_complete  := true;
    ELSE
      l_token := l_token || l_char;
    END IF;
    -- process a new token
    IF l_token_complete THEN
      v_namelist.EXTEND;
      v_namelist(v_namelist.LAST):=l_token;
      l_columnno                 := l_columnno + 1;
      l_token                    := NULL;
      l_enclosed                 := false;
      l_new_token                := true;
      l_token_complete           := false;
    END IF;
    IF l_line_complete THEN
      l_lineno        := l_lineno + 1;
      l_columnno      := 1;
      l_line_complete := false;
    END IF;
  END LOOP;
  o_namelist:=v_namelist;
END parse_csv;

0 个答案:

没有答案