Why can't I trim a column of type CHAR? - oracle

Like the title says, if a create a table in my DB :
CREATE TABLE TEST
(
FIELD CHAR(20 CHAR) NULL
)
NOLOGGING
NOCOMPRESS
NOCACHE;
Insert this :
Insert into TEST
(FIELD)
Values
('TEST -here are blank spaces- ');
COMMIT;
Then i run the following statement :
UPDATE TEST SET FIELD = TRIM(FIELD);
COMMIT;
but the field still has blank spaces, notice that if I change the data type to varchar2, it works ... does anyone know why?
Thanks!

char is a fixed width data type. A char(20) will always and forever have a length of 20. If you try to insert a shorter string, it will be padded with spaces to the fixed width length of the field. So
UPDATE TEST SET FIELD = TRIM(FIELD);
removes the spaces due to the trim function, then adds them back because the string that gets written has to be exactly 20 bytes long.
Practically, there is almost never a case to use char. You're almost always better off with a varchar2. varchar2 is a variable length data type so there is no need for the database to append the spaces to the end.

Related

Unable to insert Arabic alphabets in DB

I am trying to run sql file with below insert query, where this query has to insert arabic alphabets
INSERT INTO language
(locale_id, language_id,
VALUE
)
VALUES (4011951073333968003, 9161117031233296391,
'ابةتثجحخدذرزسشصضطظعغفقكلمنهوي'
);
But the result of this query is,
INSERT INTO language
(locale_id, language_id,
VALUE
)
VALUES (4011951073333968003, 9161117031233296391,
'يوهنملكقÙغعظطضصشسزرذدخحجثتبأ'
);
I am facing this issue, even though, I have set charset to UTF-8.
Second problem :
If I try to specify a number following Arabic alphabets, it is misplaced and get inserted before the declaration of Arabic alphabets, like,
INSERT INTO language
(locale_id, language_id,
VALUE, priority
)
VALUES (4011951073333968003, 9161117031233296391,
1,'ابةتثجحخدذرزسشصضطظعغفقكلمنهوي'
);
Here, Corresponding priority value is 1 but I am unable to declare it after Arabic script, every time, it moves at the beginning, if I declare it after the script.
Can anyone suggest me the solution to resolve this problem?

Determining input datatype Oracle/PLSQL

I am writing a PLSQL 'INSTEAD OF INSERT' Trigger whereby the ID field (GID) can be inserted as either a string or a number. If the GID value is a string I would like to attempt to convert that into the correct GID (number) otherwise if a number is input the script will continue.
The part I am struggling with here is determining the datatype of ':New.CHART_GID' - is this possible in PLSQL? I can't check for chars in the string as the string may only contain numbers in some instances.
Thanks.
You can use TRANSLATE to check if there is something other as numbers:
CREATE OR REPLACE TRIGGER trigger_name
INSTEAD OF INSERT
ON table_name
FOR EACH ROW
DECLARE
vGID INTEGER;
...... other things
BEGIN
IF :New.CHART_GID is not null AND TRANSLATE(:New.CHART_GID,'0123456789',' ') is null THEN
vGID := TO_NUMBER(:New.CHART_GID);
.... do what you want with number
ELSE
... do what you want with not number
END IF;
.... other things
END;
CHART_GID have to be varchar2 in the view
I realise what I was trying to achieve was actually not possible. The solution for me was actually to join the Chart_no into the view and insert into either that field of the GID. If I input a Chart_no the GID field would be automatically populated and the same for if I input a GID.

Cannot update a row with a bind variable in UPDATE statement

I am using Oracle SQL Developer 4.0.0.13.
Query :
UPDATE employes
SET emptime = systimestamp
WHERE emp_id = 123
AND emp_device = :abc;
Field Definition : emp_device char(20 byte)
Value is : 99998000000008880999 (This value is present in the table)
When I run the above query in SQL developer it asks me to give the value for the bind variable, which I paste in the text box and it returns 0 rows updated.
But when I remove the bind variable in the update query and specify the actual value, it updates the column value. Below is the query.
Query:
UPDATE employes
SET emptime = systimestamp
WHERE emp_id = 123
AND emp_device = 99998000000008880999 ;
---(works)
Also, when I add some trailing spaces in the bind variable text box and trim the emp_device column, it updates the column. Below is the query.
Query :
UPDATE employes
SET emptime = systimestamp
WHERE emp_id = 123
AND emp_device = trim(:abc);
-- (works --- :abc value is '99998000000008880999 ')
I do not know what is wrong with it. Can someone please take a look and suggest a solution.
You are using CHAR type for your emp_device datatype. Note that CHAR type always blank pads the resulting string out to a fixed width.read this.
You should use VARCHAR2 as datatype if you are expecting a string or just NUMBER as your example consists purely of numeric values.
in dialog box enter your parameter as '99998000000008880999' use apostrophe chars.

SQL loader position

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

How to make a varchar2 field shorter in Oracle?

I have a field in a table that is varchar2, 4000 bytes. There are over 50000 rows. Not all rows have data in this field. Few data fields are over 255 bytes, but some are 4000. To place the table in a new application, I need to shorten the field to 255 bytes.
Is there a SQL statement that will reduce the length to 255? I realize data will be lost, that is part of the cost of the new application. The cut should be arbitrary, just stopping the data at 255 no matter the circumstance.
update b set text2 = substr(text2,1,255);
then alter table to set length of column to 255 :
alter table b MODIFY "TEXT2" varchar2(255 byte);

Resources