In this article, I’ll be discussing how to fix the “KUP-01005: syntax error: found "hash"” error when selecting from an external table. Here’s the error in its entirety:
ORA-29913: error in executing ODCIEXTTABLEOPEN callout
ORA-29400: data cartridge error
KUP-00554: error encountered while parsing access parameters
KUP-01005: syntax error: found "hash": expecting one of: "binary_double, binary_float, comma, char, date, defaultif, decimal, double, float, integer, (, lls, lls_compat, no, nullif, oracle_date, oracle_number, position, raw, recnum, ), unsigned, varrawc, varchar, varraw, varcharc, zoned"

Replicating the Problem

First, let’s start with creating a basic external table:

create table drop_me_ext
(
     account# number(*,0)
   , account_name varchar2(35)
   , account_start_date date
)
organization external
(
  type oracle_loader
  default directory my_oracle_directory
  access parameters
  (
    records delimited by newline
    skip 1
    fields terminated by ',' rtrim
    missing field values are null
    (
        account#
      , account_name
      , account_start_date date 'MM/DD/YYY'
    )
  )
  location ('DropMe.csv')
)
;

If we attempt to create the external table, we don’t get any issues from Oracle.

Table DROP_ME_EXT created.

However, if we try to select from the table, we see that Oracle complains.

SQL> select *
  2  from drop_me_ext;

Error starting at line : 1 in command -
select *
from drop_me_ext
Error report -
ORA-29913: error in executing ODCIEXTTABLEOPEN callout
ORA-29400: data cartridge error
KUP-00554: error encountered while parsing access parameters
KUP-01005: syntax error: found "hash": expecting one of: "binary_double, binary_float, comma, char, date, defaultif, decimal, double, float, integer, (, lls, lls_compat, no, nullif, oracle_date, oracle_number, position, raw, recnum, ), unsigned, varrawc, varchar, varraw, varcharc, zoned"
KUP-01007: at line 6 column 16

How to Fix KUP-01005: syntax error: found “hash”

The error is, frankly, one that pisses me off. Seems like Oracle got overzealous when trying to cover themselves syntactically. The problem is that we have a “#” sign in our columns. However, Oracle doesn’t have any issue with the # in the actual table definition above. But when we’re redefining the columns below, Oracle seems to now dislike it.

We can remedy the issue in the same way we can so many others (e.g. with reserved words, etc) by double quoting the identifier.

create table drop_me_ext
(
     account# number(*,0)
   , account_name varchar2(35)
   , account_start_date date
)
organization external
(
  type oracle_loader
  default directory my_oracle_directory
  access parameters
  (
    records delimited by newline
    skip 1
    fields terminated by ',' rtrim
    missing field values are null
    (
        "ACCOUNT#"
      , account_name
      , account_start_date date 'MM/DD/YYY'
    )
  )
  location ('DropMe.csv')
)
;

Of course, when when double quote the identifier, it becomes case sensitive. So, we want to capitalize it to preserve Oracle’s standard of “uppercasing all identifiers.”

Firstly, we drop the existing table…

SQL> drop table drop_me_ext purge;

Table DROP_ME_EXT dropped.

…and then, we re-create it again. (Note the change in line 18)

SQL> create table drop_me_ext
  2  (
  3       account# number(*,0)
  4     , account_name varchar2(35)
  5     , account_start_date date
  6  )
  7  organization external
  8  (
  9    type oracle_loader
 10    default directory my_oracle_directory
 11    access parameters
 12    (
 13      records delimited by newline
 14      skip 1
 15      fields terminated by ',' rtrim
 16      missing field values are null
 17      (
 18          "ACCOUNT#"
 19        , account_name
 20        , account_start_date date 'MM/DD/YYY'
 21      )
 22    )
 23    location ('DropMe.csv')
 24  )
 25  ;

Table DROP_ME_EXT created.

Finally, everything goes smoothly when we select from it. No more KUP-01005 error.

Note that we could have also fixed this by omitting the “#” from your column names altogether (for example, we could spell out ACCOUNT_NUMBER). But sometimes it’s nice to use shortcuts like this in column names. This is especially true if we are limited to 30 characters, and we have longer column names (e.g. ORDER#_LINE# instead of spelling out ORDER_NUMBER_LINE_NUMBER).

Free Oracle SQL Tuning Guide

Checkout my FREE guide, 7 SQL Tuning Secrets You Can Use Immediately, Even If You’ve Never Tuned a Query In Your Life!

Get it here: tuningsql.com/secrets

7 SQL Tuning Secrets You can Use Immediately

Leave a Reply

Your email address will not be published. Required fields are marked *