im trying to replace a phc table with information from a txtfile but im not getting the information on the screen.
re is the table i want to replace the values
txtcabecalho is the imported file that people have to choose
reciboc is the cursor that i've created to store the values from the txt file so i can replace them on re and show them to the screen
sre is the screen of the table re.
Local txtcabecalho
Use re
Delete all
txtcabecalho=getfile("txt")
Create cursor reciboc(rno n(10), rdata d(10), moeda c(3), no n(10), nome c(2), ccusto c(20), intid c(10), clbanco c(20), total float(19), totalmoeda float(19), ndoc n(3))
append from (txtcabecalho) delimited with tab
select reciboc
goto top
scan for !empty(reciboc.rno)
select re
append blank
replace re.rno with reciboc.rno
replace re.rdata with reciboc.rdata
replace re.moeda with reciboc.moeda
replace re.no with reciboc.no
replace re.nome with reciboc.nome
replace re.ccusto with reciboc.ccusto
replace re.intid with reciboc.intid
replace re.clbanco with reciboc.clbanco
replace re.total with reciboc.total
replace re.totalmoeda with reciboc.totalmoeda
replace re.ndoc with reciboc.ndoc
select re
endscan
sre.refresh()
Thanks!
Updated
So this actually works if i crate a file of my own with the delimitianion i choose for example with tabs. Thi thing is the files that i need to import are like using spaces as spaceholders and got no delimitations from each other. Let me explain better. for example first 3 fields rno and rdata and moeda.
The txt files come like 22014-12-23EUR
Where 2 is the rno but has 9 spaces behind working like place holders for bigger numbers making the rno(10)
Next is 2014-12-23 wich is right next to the rno with no delimitation wich does the rdata(10)
Next is the moeda wich is EUR , again with no delimitation , being the moeda(3)
Many fields will be blank , and those the txt files come with spaces ocupying full length of the fields. Basically, field length is used as delimitation, and when empty , its filled with spaces.
Did u understood right? sorry im not an english native.
update
heres is some of the txt file 22014-11-27EUR 208 799,00 799,00 00
just keep in mind that before the first number 2 , there are 9 spaces.
Thanks!
the rdata field wich is going to be filled with 2014-11-27 is rdata d(10)
edited
currently code:
Local txtcabecalho, fileconvert
Use re
zap
txtcabecalho=getfile("txt")
Create cursor reciboc(rno n(10), rdata d(10), moeda c(3), no n(10), nome c(2), ccusto c(20), intid c(10), gg c(20), chq c(20), clbanco c(20), total float(19), totalmoeda float(19), ndoc n(3))
fileconvert = filetostr(txtcabecalho)
chrtran(fileconvert,'-','')
strtofile(fileconvert, txtcabecalho)
append from (txtcabecalho) type sdf
scan
select re
append blank
replace rno with reciboc.rno
replace rdata with reciboc.rdata
replace moeda with reciboc.moeda
replace no with reciboc.no
replace nome with reciboc.nome
replace ccusto with reciboc.ccusto
replace intid with reciboc.intid
replace clbanco with reciboc.clbanco
replace total with reciboc.total
replace totalmoeda with reciboc.totalmoeda
replace ndoc with reciboc.ndoc
select re
endscan
select reciboc
browse title "resultado"
reindex
sre.refresh()
what i get is this is what i get
stil ltrying to figure out i really don't know aff
for example : firt row should be:
RNO 2
RDATA 2014-11-27
NO 208
EDITED
actually this made it ahah
fileconvert = filetostr(txtcabecalho)
fileconvert2 = strtran(fileconvert,'-','')
strtofile(fileconvert2, txtcabecalho)
if i need further help i'll update my question! Thank you so much guys!
EDITED
Doyou guys know if there is any problem converting from txt file float numbers to cursors?
I got for example 799,20 but i just show up as 799. Data type is set to totalmoeda f(19) . This must be pretty simple but i can't find it!
You are doing a SCAN loop which implies many rows from the reciboc table. However, in your "re" table, you just keep overwriting the same row with the same values, and if no record on file, you will have nothing anyhow. If you want to add them, you need to append to the "RE" table.
Now, another consideration is the "rno" column. Is that supposed to be an "ID" column such as your external text file may have updated values for each given "RNO" and you want to update if it does not exist yet, or add if it does NOT exist in the "re" table?
UPDATE for your question with tags and extra clarified elements...
If you have an index on you "RE" table on the "RNO" column, great. If not, and that is the key column that you want to update based on, I suggest creating an index on it...
From the VFP command window, build the index so it is always available
use RE exclusive
index on RNO tag RNO
use
Now, in your code, AFTER Your Append from delimited, and your cursor is prepared... I would set a relationship between the live table and your temp cursor and do the update like...
select reciboc
index on RNO tag RNO && so the cursor has an index too.
selece RE
set relation to RNO into RECIBOC
Now, the two tables are pointing to each other for whatever records match in each table. Now, replace FOR [scope]. Due to the relationship, as the records are cycled in the "RE" table, it will point to the same RNO record in the "RECIBOC" table if one exists. So the FOR condition is testing for NOT EOF() (end of file = no match found in RECIBOC. So NOT EOF() means there IS a record found.
replace rdata with reciboc.rdata,;
moeda with reciboc.moeda,;
no with reciboc.no,;
nome with reciboc.nome,;
ccusto with reciboc.ccusto,;
intid with reciboc.intid,;
clbanco with reciboc.clbanco,;
total with reciboc.total,;
totalmoeda with reciboc.totalmoeda,;
ndoc with reciboc.ndoc ;
FOR NOT EOF( "RECIBOC" )
finally, get any NEW "RNO" records into your "RE" table. Get all records NOT in your existing RE table based on matching "RNO" column.
select * ;
from RECIBOC ;
WHERE RNO NOT IN ( select RNO from RE );
into cursor NewRecordsToAdd readwrite
Now, add them to the "RE" table. Since the columns are the same name, they will come over directly without explicit column name from/to reference.
select RE
append from dbf( "NewRecordsToAd" )
use in select( "NewRecordsToAdd" )
Create Cursor reciboc(rno N(10), rdata d(10), moeda c(3), no N(10), ;
Nome c(2), ccusto c(20), intid c(10), clbanco c(20), ;
Total Float(19), totalmoeda Float(19), ndoc N(3))
Append From (m.txtcabecalho) Type Delimited With Blank
Select re
Append from (Dbf('reciboc'))
Above is the shorter version for what you are trying to do.
In your update what you are describing is a Fixed Width Data format or what is known as System Data Format (SDF). Then do not use delimited but SDF as the type:
Create Cursor reciboc(rno C(10), rdata C(10), moeda c(3), no C(10), ;
Nome c(2), ccusto c(20), intid c(10), clbanco c(20), ;
Total C(19), totalmoeda C(19), ndoc C(3))
Append From (m.txtcabecalho) Type SDF
alter table reciboc alter column rdata d && convert rdata column to date
* do other needed column type conversions
Select re
Append from (Dbf('reciboc'))
The sizes you use when creating your cursor should match with the sizes of data columns in your text file. After getting the whole data as text, alter columns to match the data types (I assumed your sizes were right) - d(10) was meaningless, and float is never a suggested type.
PS: If you can find FoxyClasses then it does have an importer class in it which handles much of the work for you (unfortunately I lost the server where I was serving the download). You can read the details in its chm file if you can find.
With exactly 9 spaces before 2 it works for me:
Create Cursor reciboc(rno C(10), rdata C(10), moeda c(3), no C(10), ;
Nome c(2), ccusto c(20), intid c(10), clbanco c(20), ;
Total C(19), totalmoeda C(19), ndoc C(3))
Append From (m.txtcabecalho) Type SDF
browse title "Before data type change"
Set Date YMD
Set Century ON
alter table reciboc alter column rdata d && convert rdata column to date
browse title "After date type change"
In case of SDF, keep in mind positions in text file specify field widths.
Related
I want to create a procedure to remove all special characters from a column of my spesific table and then remove duplicate records.
I tried the following query so far to show the desired logic :
SELECT ft_nm_val,count(*)
FROM ( SELECT REGEXP_REPLACE(ft_nm_val, '[^A-Za-z0-9, ]') AS ft_nm_val
FROM fraud_token_name )
GROUP BY ft_nm_val
HAVING COUNT(*) > 1
Since you want to remove duplicate records and if there are other columns exist in the table, then concept duplicate would change row-wisely. So, I assume you have that table with only one column mentioned. Then you can create such a procedure :
SQL> create or replace procedure make_unique is
begin
--# Leave only alpha-numeric characters through applying [^ ] to [:alnum:] posix
update fraud_token_name
set ft_nm_val = regexp_replace(ft_nm_val,'[^[:alnum:]]');
--# Then delete duplicate records
delete fraud_token_name f1
where rowid <
(
select max(rowid)
from fraud_token_name f2
where f2.ft_nm_val = f1.ft_nm_val
);
commit;
end;
/
SQL> exec make_unique;
Demo
My Source (Oracle) data is having below values. We need to delete _00 or .00 or _ if exists at the end. Can you please provide some SQL query to get the below target values.
SOURCE VALUES:
123450_00
12356_00
123455678
34569_
67589
123400.00
TARGET MUST BE
123450
12356
123455678
34569
67589
123400
I tried using rtrim(columnname,'_00') but if i use this, '0' before _ is also getting deleted which is not correct.
You can use regular expressions for this, namely regexp_replace():
select value,
regexp_replace(value, '[_.][0-9]*$', '')
from demo;
This will replace a
literal _ or .
followed by 0 or more digits [0-9]*
at the end of the string $
with the empty string.
Schema
create table demo(value varchar2(30 char));
insert into demo values('123450_00');
insert into demo values('12356_00');
insert into demo values('123455678');
insert into demo values('34569_');
insert into demo values('67589');
insert into demo values('123400.00');
SQL Fiddle
Till today we use to enter numeric value in the Varchar column so Oracle converted that varchar field to Numeric field.
And now when we are trying to insert Character value it is throwing ORA-01722 (invalid number).
Could anyone help me out in order to convert it back to varchar field?
The commenters are correct: the database does not change column types on its own. In general, you must create a new column, copy the old data over to the new column, drop the original column, and rename the new column.
drop table deleteme_table;
-- zippy s/b varchar2(30), not integer
CREATE TABLE deleteme_table
(
adate DATE
, zippy INTEGER
);
-- Add the correct type to the table as a new column
ALTER TABLE deleteme_table
ADD (tempcol VARCHAR2 (30));
-- Copy the old values to the new column
UPDATE deleteme_table
SET tempcol = zippy;
-- Get rid of the original column
ALTER TABLE deleteme_table
DROP COLUMN zippy;
-- Rename to original column name
alter table deleteme_table rename column tempcol to zippy;
I have the below Nested table created :
create or replace TYPE access_t AS OBJECT (
AccessID VARCHAR2(50),
Eligibility char(1)
);
/
create or replace TYPE Access_tab IS TABLE OF access_t;
/
create or replace TYPE add_t AS OBJECT (
city VARCHAR2(100),
state VARCHAR2(100),
zip VARCHAR2(10),
APOINTSARRAY Access_tab )
;
/
create or replace TYPE add_tab IS TABLE OF add_t;
/
CREATE TABLE RQST_STATUS
( RQST_ID NUMBER,
ADDRESS add_tab
)
NESTED TABLE ADDRESS STORE AS RQST_STATUS_ADDRESS
( NESTED TABLE APOINTSARRAY STORE AS RQST_STATUS_AP)
;
If i need to change ADDRESS type to new_add_tab with some additional columns instead of add_tab , Can i just use ALTER TABLE .. MODIFY .. command ?
I am getting ORA-00922 or ORA-22913 errors . I cannot change the type directly because it is used somewhere else too. Also, the table is already loaded with data.
Please suggest.
You can do that but you have to alter the TYPE not the TABLE.
Check the documentation ALTER TYPE Statement: alter_method_spec
Most important is the CASCADE key word.
Examples:
ALTER TYPE access_t ADD ATTRIBUTE NEW_Eligibility INTEGER CASCADE;
ALTER TYPE access_t DROP ATTRIBUTE Eligibility CASCADE;
ALTER TYPE access_t MODIFY ATTRIBUTE AccessID VARCHAR2(100) CASCADE;
Here is a step-by-step description of my suggestion. It might not be the most elegant, but I think that it would be best for you to have something you can fully understand (as opposed to an obscure trick).
Also, and since I don't really know what kind of changes you need to do for the internal table, I'm leaving the maximal flexibility for you to do any change you may wish to do.
Let's call your table T1 that contains a columns C_T which is your internal table.
The internal table contains columns C_1, C-2 and C_3, and you want the new structure for the record to be D_1, D_2, D_3, D_4 and D_5, where the mapping is:
C_1 -> D_5,
C_2 -> D_1,
C_3 -> D_2,
{new} -> D_3,
{new} -> D_4.
Create a tempo table TEMPO_T with a column SOURCE_ROWID (varchar2(64)) and the new columns D_1,..., D5.
Write a small anonymous block having a cursor that selects the ROWID of each row of table T1 and all the records within the internal table in column C_T (order by ROWID). The result would look like (this is just an example of course):
ROWID C_1 C_2 C_2
wwereeedffff 1 a ww
wwereeedffff 2 b xx
wwereeedffff 7 l yy
ertrtrrrtrrr 5 d PP
ertrtrrrtrrr 99 h mm
...
[Note: The use of ROWID is under the assumption that you don't have a column that can serve as a unique identifier for each row in table T1; if there is such column - one defined as UNIQUE INDEX - you can use that field instead]
Having this query ready, convert it into an INSERT into the temporary table TEMPO_T along with whatever values you need to store for columns D_3 and D_4.
Now, you have a backup of the original contents of column C_T and hence can delete the column.
Now, you can update the type that defines the structure of column C_T to its new form (i.e. D_1,...,D_5) and alter table T1 by adding a column whose type is the updated one.
Finally, you can insert the contents of column C_T with that stored in the temporary table (since you already have this, I assume that you know how to implement it - inserting a table within a cell column of the outer table).
That's it.
Needless to say, I would make a backup of your data before engaging into this.
Hope this description is detailed enough to enable you to complete the task at hand.
New to SQL loader and am a bit confused about the POSITION.
Let's use the following sample data as reference:
Munising 49862 MI
Shingleton49884 MI
Seney 49883 MI
And here is the load statement:
LOAD DATA
INFILE 'zipcodes.dat'
REPLACE INTO TABLE zipcodes (
city_name POSITION(1) CHAR(10),
zip_code POSITION(*) CHAR(5),
state_abbr POSITION(*+1) CHAR(2)
)
In the load statement, the city_name POSITION is 1. How does SQLLDR know where it ends? Is CHAR(10) the trick here? Counting the two spaces behind 'Munising', it has 10 characters.
Also why is zip_code assigned with CHAR even though it contains nothing but numbers?
Thank You
Yes, when end position is not specified, it is derived from the datatype. This documentation explains the POSITION clause.
city_name POSITION(1) CHAR(10)
Here the starting position of data field is 1. Ending position is not specified, but is derived from the datatype, that is 10.
zip_code POSITION(*) CHAR(5)
Here * specifies that, data field immediately follows the previous field and should be 5 bytes long.
state_abbr POSITION(*+1) CHAR(2)
Here +1 specifies the offset from the previous field. Sqlloader skips 1 byte and reads next 2 bytes, as derived from char(2) datatype.
As to why zipcode is CHAR, zip code is considered simply a fixed length string. You are not going to do any arithmetic operations on it. So, CHAR is appropriate for it.
Also, have a look at SQL Loader datatypes. In control file you are telling SQL*Loader how to interpret the data. It can be different from that of table structure. In this example you could also specify INTEGER EXTERNAL for zip code.
we need three text file & 1 batch file for Load Data:
Suppose your file location 'D:\loaddata'
input file 'D:\loaddata\abc.CSV'
1. D:\loaddata\abc.bad -- empty
2. D:\loaddata\abc.log -- empty
3. D:\loaddata\abc.ctl "Write Code Below"
OPTIONS ( SKIP=1, DIRECT=TRUE, ERRORS=10000000, ROWS=5000000)
load data
infile 'D:\loaddata\abc.CSV'
TRUNCATE
into table Your_table
(
a_column POSITION (1:7) char,
b_column POSITION (8:10) char,
c_column POSITION (11:12) char,
d_column POSITION (13:13) char,
f_column POSITION (14:20) char
)
D:\loaddata\abc.bat --- For execution
sqlldr db_user/db_passward#your_tns control=D:\loaddata\abc.ctl log=D:\loaddata\abc.log
After double click "D:\loaddata\abc.bat" file you data will be load desire oracle table. if anything wrong check you "D:\loaddata\abc.bad" and "D:\loaddata\abc.log" file