Home>Question Details



John -- Thanks for the question regarding "External table intermittent errors", version 10.2.0

Submitted on 29-Apr-2008 15:10 Central time zone
Last updated 30-Apr-2008 13:03

You Asked

I'm having a problem with External tables. Most of the time I can read the data in the table without any issue. But when I issue the query below I get an error.


Contents of test.csv file
Tool type,ID
Common,1
Type1,2
Type2,3



  CREATE TABLE "TEST_IMPORT" 
     (    "MACHINE" VARCHAR2(20 BYTE), 
      "ID" NUMBER
     ) 
     ORGANIZATION EXTERNAL 
      ( TYPE ORACLE_LOADER
        DEFAULT DIRECTORY "IMPORT_DIR"
        ACCESS PARAMETERS
        ( records delimited by newline  skip 1
          fields terminated by ','
          optionally enclosed by '"'                                             )
        LOCATION
         ( "IMPORT_DIR":'test.csv'
         )
      )
    ;
 
 
 
 
SQL> select count(*) from test_import;
 
 COUNT(*)               
 ---------------------- 
 3                      
 
 1 rows selected

SQL> create table perm_tbl as select * from test_import where upper(machine) in
('COMMON','TYPE1');

Table created.
 
SQL> desc perm_tbl;
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------

 MACHINE                                            VARCHAR2(20)
 ID                                                 NUMBER



select * from (
select id from perm_tbl where upper(machine) in ('COMMON','TYPE1')
);

ID           
---------------------- 
1                      
2                      

2 rows selected


SQL> select * from perm_tbl where id not in
  2  (select id from test_import where upper(machine) in ('COMMON','TYPE2'));
select * from perm_tbl where id not in
*
ERROR at line 1:
ORA-29913: error in executing ODCIEXTTABLEFETCH callout
ORA-30653: reject limit reached
ORA-06512: at "SYS.ORACLE_LOADER", line 52


Log file:
  LOG file opened at 04/29/08 13:08:03

Field Definitions for table TEST_IMPORT
  Record format DELIMITED BY NEWLINE
  Data in file has same endianness as the platform
  Rows with all null fields are accepted

  Fields in Data Source: 

    MACHINE                         CHAR (255)
      Terminated by ","
      Enclosed by """ and """
      Trim whitespace same as SQL Loader
    ID                    CHAR (255)
      Terminated by ","
      Enclosed by """ and """
      Trim whitespace same as SQL Loader
error processing column ID in row 1 for datafile C:\test.csv
ORA-01722: invalid number

BAD file:
Tool type,ID


and we said...

you are assuming an order of operation in SQL processing and you cannot, we can evaluate anything in any order we want.


SQL> create table perm_tbl as select * from test_import where upper(machine) in
('COMMON','TYPE1');


we apparently evaluated "where uppper() in (...)" before selecting machine and id - and hence converting the string into a number for ID - and therefore did NOT fail.


for:

SQL> select * from perm_tbl where id not in
2 (select id from test_import where upper(machine) in ('COMMON','TYPE2'));


well, one way to process that query is:

select p.*
from perm_tbl p, test_import t
where p.id = t.id(+)
and t.machine in ('COMMON','TYPE2')
and t.id is null;


(an anti-join), there are other ways as well - but as you can see, the SQL you "get" is not necessary the sql you wrote - they are equivalent, but different.

It is all about the plan... And the accidental order of operation.

Here is a potential plan for your query:

ops$tkyte%ORA10GR2> select * from perm_tbl where id not in
  2  (select id from test_import where upper(machine) in ('COMMON','TYPE2'));

------------------------------------------------------------------------------------------
-
| Id  | Operation                   | Name        | Rows  | Bytes | Cost (%CPU)| Time     
|
------------------------------------------------------------------------------------------
-
|   0 | SELECT STATEMENT            |             |     1 |    25 |     4   (0)| 00:00:01 
|
|*  1 |  FILTER                     |             |       |       |            |          
|
|   2 |   TABLE ACCESS FULL         | PERM_TBL    |     1 |    25 |     2   (0)| 00:00:01 
|
|*  3 |   EXTERNAL TABLE ACCESS FULL| TEST_IMPORT |     2 |    50 |     2   (0)| 00:00:01 
|
------------------------------------------------------------------------------------------
-

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter( NOT EXISTS (SELECT /*+ */ 0 FROM "TEST_IMPORT" "TEST_IMPORT" WHERE
              (UPPER("MACHINE")='COMMON' OR UPPER("MACHINE")='TYPE2') AND 
LNNVL("ID"<>:B1)))
   3 - filter((UPPER("MACHINE")='COMMON' OR UPPER("MACHINE")='TYPE2') AND
              LNNVL("ID"<>:B1))


Note
-----
   - dynamic sampling used for this statement



see the filter on step 3? that is why...

if you know that when machine in (values) means ID is a number, you would:

case when upper(machine) in ('A','B') then to_number(id) end

and map ID as a STRING - which is apparently is...




Reviews    
2 stars   April 30, 2008 - 12pm Central time zone
Reviewer: John Lavoie 
No. Looking at the BAD FILE, the line in the CSV file that Oracle is choking on is the HEADER line.

If we remove that from the CSV file and remove the SKIP 1 from the ACCESS PARAMETERS, then the query works correctly.


Contents of test.csv
Common,1
Type1,2
Type2,3

External table definition
  CREATE TABLE "TEST_IMPORT" 
   (    "MACHINE" VARCHAR2(20 BYTE), 
    "ID" NUMBER
   ) 
   ORGANIZATION EXTERNAL 
    ( TYPE ORACLE_LOADER
      DEFAULT DIRECTORY "IMPORT_DIR"
      ACCESS PARAMETERS
      ( records delimited by newline
          fields terminated by ','
          optionally enclosed by '"' 
    )
      LOCATION
       ( "IMPORT_DIR":'test.csv'
       )
    )
  ;

Same query as before
SQL> select * from perm_tbl where id not in
  (select id from test_import where upper(machine) in ('COMMON','TYPE2'))


MACHINE              ID                     
-------------------- ---------------------- 
Type1                2                      

1 rows selected


Followup   April 30, 2008 - 1pm Central time zone:

ahh, I see - sorry about that.

That will be a 'bug' apparently - it does not reproduce in 11gR1 but does in 9i and 10g.

please contact support and reference bug 4380703
4 stars clarification on the query   April 30, 2008 - 7pm Central time zone
Reviewer: Amit Poddar from New Haven, CT
Hi,

In the case of above query, I have updated perm_table id to be null for both the rows then I run the same query

SQL> update perm_tbl set id=null;

2 rows updated.

SQL> commit;

Commit complete.

SQL> alter session set statistics_level=all;

Session altered.

SQL> select * from perm_tbl where id not in
   (select id from test_import where upper(machine) in ('COMMON','TYPE2'))
  2    3  
SQL> /

no rows selected

SQL> set linesize 150;
SQL> set pagesize 4000;
SQL> select * from table(dbms_xplan.display_cursor(null,null,'ALLSTATS'));

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
--------------------------------------------------
SQL_ID  58fff37ugs9t7, child number 2
-------------------------------------
select * from perm_tbl where id not in    (select id from test_import where upper(machine)
in ('COMMON','TYPE2'))

Plan hash value: 3425822930

----------------------------------------------------------------------------------------------------
-
| Id  | Operation                   | Name        | Starts | E-Rows | A-Rows |   A-Time   | Buffers 
|
----------------------------------------------------------------------------------------------------
-
|*  1 |  FILTER                     |             |      1 |        |      0 |00:00:00.06 |     118 
|
|   2 |   TABLE ACCESS FULL         | PERM_TBL    |      1 |      2 |      2 |00:00:00.01 |       3 
|
|*  3 |   EXTERNAL TABLE ACCESS FULL| TEST_IMPORT |      1 |      2 |      1 |00:00:00.06 |     115 
|
----------------------------------------------------------------------------------------------------
-

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter( IS NULL)
   3 - filter(((UPPER("MACHINE")='COMMON' OR UPPER("MACHINE")='TYPE2') AND LNNVL("ID"<>:B1)))



1. Can you please explain the filter 1 i.e. filter (IS NULL)
2. Why is the external table in step 3 starts only once instead of twice since the number of rows returned in step 2is 2.
3. Since at lease one id is null in perm_table, the result of not in will be no rows selected, so oracle can get away without accessing the external table at all (it looks like that this optimization is not implemented, is that correct)




All information and materials provided here are provided "as-is"; Oracle disclaims all express and implied warranties, including, the implied warranties of merchantability or fitness for a particular use. Oracle shall not be liable for any damages, including, direct, indirect, incidental, special or consequential damages for loss of profits, revenue, data or data use, incurred by you or any third party in connection with the use of this information or these materials.

About Oracle | Legal Notices and Terms of Use | Privacy Statement