i want to import csv file to oracle Database.
my csv look like this :
Table A : sometimes containing 2 lines or 3 lines or empty. i want to import start Table B. so my control.ctl is :
echo OPTIONS (SKIP=5, errors=12000)
LOAD DATA
APPEND INTO TABLE xyz
when id <> '' and sales = ''
FIELDS TERMINATED BY X'09'
optionally enclosed by '"'
TRAILING NULLCOLS
(id "TRIM (:id)",
customer "TRIM (:customer)",
qty "TRIM (:qty)",
sales filler)
xyz table is :
create xyz (
id varchar2(3),
customer varchar2(255),
qty varchar2(5)
)
why no data is stored?
In Oracle, the empty string is considered null. And null is never equal to nor unequal to any other value including null. You need to use is null or is not null to look for null values.
The predicate
when id <> '' and sales = ''
can never possibly be true. No id value is ever unequal to null and no sales value is ever equal to null. Perhaps you want
when id is not null and sales is null
If you are just trying to avoid loading blank rows, however, I'd expect that your when clause would just be on id not on sales.
Related
I need your help to frame a SQL query in Oracle . I am creating a XML type Table in Oracle Database and making one column of it a Multi Value Field. The data given to the Multi Value column for the records are of different cases with Multi Value and Sub Value. (Ex : ( “ ” : #VM: “ 10 ”) , (“ 12” : #VM: “ ”) , (“ ” : #SM: “ 8 ”) , (“ 6” : #SM: “ ”)) . When a SQL query is executed to select the records for which the Multi value column is equated to Null, the record where the first value of #SM is NULL is not getting selected ie. (“ ” : #SM: “ 8 ”).
Table Creation :
CREATE TABLE "F_TESTMV" (RECID VARCHAR2(255) NOT NULL PRIMARY KEY, XMLRECORD XMLTYPE) XMLTYPE COLUMN XMLRECORD STORE AS CLOB
CREATE TABLE D_F_TESTMV (RECID VARCHAR2(255) NOT NULL PRIMARY KEY, XMLRECORD CLOB)
Insert Statement :
INSERT INTO TAFJ24.F_TESTMV (RECID,XMLRECORD) VALUES
('11000',TO_CLOB(' <row id='11000'><c1></c1><c1 m='2'>US</c1></row>')),
('12000',TO_CLOB(' <row id='12000'><c1>US</c1><c1 m='2'></c1></row>')),
('13000',TO_CLOB(' <row id='13000'><c1>GB</c1><c1 m='2'>US</c1></row>')),
('14000',TO_CLOB(' <row id='14000'><c1>US</c1><c1 m='2'>GB</c1></row>'));
('15000',TO_CLOB('<row id='15000'><c1>OF</c1><c1 m='2'></c1></row>')),
('16000',TO_CLOB('<row id='16000'><c2>gb</c2></row>')),
('17000',TO_CLOB(<row id='17000'><c1>US</c1><c1 m='1' s='2'></c1></row>'));
('18000',TO_CLOB('<row id='18000'><c1 m='1' s='2'>GB</c1></row>'));
View Definition:
SELECT a.RECID, a.XMLRECORD "THE_RECORD",extractValue(a.XMLRECORD,'/row/c1[position()=1]') "COUNTRY" ,extract(a.XMLRECORD,'/row/c1') "COUNTRY_1" FROM "F_TESTMV"
Select Query :
SELECT RECID FROM "V_F_TESTMV" WHERE ( XMLEXISTS('$t[/row/c1[not(text())][not(*)] or /row/c1/text()= "" or fn:not(/row/c1/text()) ] ' PASSING "THE_RECORD" as "t") )
Current Result :
From the eight records in the table, The above SQL query selects 5 records, with RECID 11000,12000,15000,16000,17000. It does not select RECID 18000 even when the first part of Sub Value is NULL in the record.
EXPECTED RESULT
The Query should select 6 Records . The records with RECID 11000,12000,15000,16000,17000 and 18000 should be selected, as RECID 18000 also has first part of Sub Value as NULL.
Kindly provide your Suggestion on the SQL Query required that will fetch the above records when the name of the Column with Multi Value field is Equated to NULL.
Thanks
Oracle Table Structure.
create table EmployeeTemp
(
Name VARCHAR2(80) NOT NULL,
Age NUMBER(3),
Gender VARCHAR2(10)
);
SQL Loader Control File
LOAD DATA
REPLACE
INTO TABLE EmployeeTemp
FIELDS TERMINATED BY "|" OPTIONALLY ENCLOSED BY '"' TRAILING NULLCOLS
(
Name CHAR(80),
Age INTEGER EXTERNAL,
Gender CHAR(10)
)
Data File:
John Williams|23|Male
Caser|78|
Brit
Sam|34||extrafield
How to reject a record which has has more fields or fewer fields in data file compared to the number of fields in Database table?
In the data file example:
Record 'Sam' need to be rejected as it has 4th field (Extra field ).
Record 'Brit' need to be rejected as it has not passed null or empty value for Gender field. ( Having fewer field information)
'John Williams' & 'Caser' record has either data or null/empty values for all 3 fields is provided. So they should not be rejected.
Please suggest how to achieve my requirement and what changes needed in the Oracle SQL loader Control file (As I don't have option to change table structure to make Age and Gender field as not null)?
I was loading data using SQL*Loader and when making the control file I used the table definition and accidentally left the INTEGER data type on the "version" line.
And in the "version" field (data type integer) it inserted the value 808594481.
I'm having a hard time understanding how it processed this value -- I'm assuming it took it as a literal ... but is that the sum of the ASCII representations of each letter?
NOPE!
SELECT ASCII('I')+ascii('N')+ASCII('T')+ASCII('E')+ASCII('G')+ASCII('E')+ASCII('G')+ASCII('E')+ASCII('R')
FROM SYS.DUAL
returns 666 (which, btw is hilarious).
concatenate ascii values?
SELECT ASCII('I')||ascii('N')||ASCII('T')||ASCII('E')||ASCII('G')||ASCII('E')||ASCII('G')||ASCII('E')||ASCII('R')
FROM SYS.DUAL
returns 737884697169716982
I'm hoping someone out there knows the answer.
This is the actual control file:
OPTIONS (SKIP=1)
LOAD DATA
APPEND into table THETABLE
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
(id ,
parent_id ,
record_id ,
version INTEGER,
created_at ,
updated_at ,
created_by ,
updated_by ,
species_and_cohort ,
species_and_cohort_count)
Table DDL:
create table THETABLE
(
id VARCHAR2(36),
parent_id VARCHAR2(36),
record_id VARCHAR2(36),
version INTEGER,
created_at VARCHAR2(25),
updated_at VARCHAR2(25),
created_by VARCHAR2(50),
updated_by VARCHAR2(50),
species_and_cohort VARCHAR2(150),
species_and_cohort_other VARCHAR2(150),
species_and_cohort_count NUMBER
)
Data:
id,parent_id,record_id,version,created_at,updated_at,created_by,updated_by,species_and_cohort,species_and_cohort_other,species_and_cohort_count
60D90F54-C5F2-47AF-951B-27A424EAE8E3,f9fe8a3b-3470-4caf-b0ba-3682a1c79731,f9fe8a3b-3470-4caf-b0ba-3682a1c79731,1,2014-09-23 21:02:54 UTC,2014-09-23 21:02:54 UTC,x#gmail.com,x#gmail.com,"PRCA Cherrylaurel,Sapling","",5
FC6A2120-AA0B-4238-A2F6-A6AEDD9B8202,f9fe8a3b-3470-4caf-b0ba-3682a1c79731,f9fe8a3b-3470-4caf-b0ba-3682a1c79731,1,2014-09-23 21:03:02 UTC,2014-09-23 21:03:02 UTC,x7#gmail.com,x7#gmail.com,"JUVI Eastern Redcedar,Sapling","",45
If you split 808594481 into bytes as it would be encoded in a 32 bit twos complement encoding, and treat each byte as an ascii-encoded character, you get "02,1" or "1,20" depending on byte order. You probably inserted a string that starts or ends with one of those, and some layer between your code and the database silently converted it to an integer.
I'm struggling with an Oracle external table, although I researched the Oracle forums. Still, no success.
Let's suppose I have a simple table
DESCRIBE PRODUCTS
Name Null Type
------------------------------ -------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ID NOT NULL NUMBER
NAME VARCHAR2(30)
VALUE NUMBER(5,2)
DEP VARCHAR2(30)
COUNT NUMBER(3)
Then, I created an oracle folder:
CREATE OR REPLACE DIRECTORY ext_prod_dir AS 'c:\';
I save the content of that table in a .lst file
spool c:\products.lst
select p.id || ';' || p.name || ';' || p.value || ';' || p.dep || ';' || p.count FROM products p;
spool off;
P.ID||';'||P.NAME||';'||P.VALUE||';'||P.DEP||';'||P.COUNT
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1;Settlers of Catan;29,95;Toys;3
2;DVD Player;82,97;Electronics;2
3;Red Shirt;12,49;Clothes;3
4;Black Leather Couch;399,99;Furniture;5
5;Oak Cofee Table;223,99;Furniture;5
6;Technodrome;27,99;Toys;4
7;Oh Cereal;3,95;Foods;1
8;Game Console;299,95;Toys;2
9;Video Game;29,95;Toys;3
10;Lawn Chair;34,99;Furniture;11
11;Dog Toy Bone;34,99;Toys;9
12;Heated Blanket;27,95;Toys;8
13;Flux Capacitor;27,95;Toys;7
14;Chocolate Pie;3,14;Foods;7
Then I tried to create the external table:
CREATE TABLE products_ext
(ID NUMBER,
NAME VARCHAR2(30),
VALUE NUMBER(5,2),
DEP VARCHAR2(30),
COUNT NUMBER(3))
ORGANIZATION EXTERNAL
(TYPE oracle_loader DEFAULT DIRECTORY ext_prod_dir
ACCESS PARAMETERS
(RECORDS DELIMITED BY NEWLINE
FIELDS TERMINATED BY ';'
MISSING FIELD VALUES ARE NULL
BADFILE ext_prod_dir:'products.bad_xt'
LOGFILE ext_prod_dir:'products.log_xt'
(ID CHAR(6),
NAME CHAR(30),
VALUE CHAR(8),
DEP CHAR(30),
COUNT CHAR(3)))
location ('products.lst')
) REJECT LIMIT UNLIMITED
So far so good. Then when I select data from the external table, I got:
ORA-29913: error in executing ODCIEXTTABLEOPEN callout
ORA-29400: data cartridge error
KUP-00554: error encontered while parsing access parameters
KUP-01005: syntax error: found "badfile": expecting one of: "column (,reject"
KUP-01007: at line 4 column 7
I tried a huge amount of things, but I got variations on this error. Best thing I accomplished was that I got rid of error, but the table was empty. I would be very much indebted If someone with more experience can point me in the right direction.
BADFILE and LOGFILE are not part of the FIELDS clause. So, move them above the FIELDS TERMINATED.
CREATE TABLE products_ext
(ID NUMBER,
NAME VARCHAR2(30),
VALUE NUMBER(5,2),
DEP VARCHAR2(30),
COUNT NUMBER(3))
ORGANIZATION EXTERNAL
(TYPE oracle_loader DEFAULT DIRECTORY ext_prod_dir
ACCESS PARAMETERS
(RECORDS DELIMITED BY NEWLINE
BADFILE ext_prod_dir:'products.bad_xt'
LOGFILE ext_prod_dir:'products.log_xt'
FIELDS TERMINATED BY ';'
MISSING FIELD VALUES ARE NULL
(ID CHAR(6),
NAME CHAR(30),
VALUE CHAR(8),
DEP CHAR(30),
COUNT CHAR(3)))
LOCATION ('products.lst')
) REJECT LIMIT UNLIMITED
Also, you said when you got rid of the error, the table was empty. Did you check the logfile? If the error is with the VALUE column, then check NLS_NUMERIC_CHARACTERS parameter
in view v$nls_parameters.
select * from v$nls_parameters;
Check if the decimal marker is indeed a comma. If not either update this parameter or change it in the data file.
I am trying to use the "Create Table As Select" feature from Oracle to do a fast update. The problem I am seeing is that the "Null" field is not being preserved.
I defined the following table:
create table mytable(
accountname varchar2(40) not null,
username varchar2(40)
);
When I do a raw CTAS, the NOT NULL on account is preserved:
create table ctamytable as select * from mytable;
describe ctamytable;
Name Null Type
----------- -------- ------------
ACCOUNTNAME NOT NULL VARCHAR2(40)
USERNAME VARCHAR2(40)
However, when I do a replace on accountname, the NOT NULL is not preserved.
create table ctamytable as
select replace(accountname, 'foo', 'foo2') accountname,
username
from mytable;
describe ctamytable;
Name Null Type
----------- ---- -------------
ACCOUNTNAME VARCHAR2(160)
USERNAME VARCHAR2(40)
Notice that the accountname field no longer has a null, and the varchar2 field went from 40 to 160 characters. Has anyone seen this before?
This is because you are no longer selecting ACCOUNTNAME, which has a column definition and meta-data. Rather you are selecting a STRING, the result of the replace function, which doesn't have any meta-data. This is a different data type entirely.
A (potentially) better way that might work is to create the table using a query with the original columns, but with a WHERE clause that guarantees 0 rows.
Then you can insert in to the table normally with your actual SELECT.
By having query of 0 rows, you'll still get the column meta-data, so the table should be created, but no rows will be inserted. Make sure you make your WHERE clause something fast, like WHERE primary_key = -999999, some number you know would never exist.
Another option here is to define the columns when you call the CREATE TABLE AS SELECT. It is possible to list the column names and include constraints while excluding the data types.
An example is shown below:
create table ctamytable (
accountname not null,
username
)
as
select
replace(accountname, 'foo', 'foo2') accountname,
username
from mytable;
Be aware that although this syntax is valid, you cannot include the data type. Also, explicitly declaring all the columns somewhat defeats the purpose of using CREATE TABLE AS SELECT.