Unable to insert Arabic alphabets in DB - oracle

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?

Related

find a best way to traverse oracle table

I have an oracle table. Table's DDL is (not have the primary key)
create table CLIENT_ACCOUNT
(
CLIENT_ID VARCHAR2(18) default ' ' not null,
ACCOUNT_ID VARCHAR2(18) default ' ' not null,
......
)
create unique index UK_ACCOUNT
on CLIENT_ACCOUNT (CLIENT_ID, ACCOUNT_ID)
Then, the data's scale is very huge, maybe 100M records. I want to traverse this whole table's data with batch.
Now, I use the table's index to batch traverse. But I have some oracle grammar problems.
# I want to use this SQL, but grammar error.
# try to use b-tree's index to locate start position, but not work
select * from CLIENT_ACCOUNT
WHERE (CLIENT_ID, ACCOUNT_ID) > (1,2)
AND ROWNUM < 1000
ORDER BY CLIENT_ID, ACCOUNT_ID
Has the fastest way to batch touch table data?
Wild guess:
select * from CLIENT_ACCOUNT
WHERE CLIENT_ID > '1'
and ACCOUNT_ID > '2'
AND ROWNUM < 1000;
It would at least compile, although whether it correctly implements your business logic is a different matter. Note that I have cast your filter criteria to strings. This is because your columns have a string datatype and you are defaulting them to spaces, so there's a high probability those columns contain non-numeric values.
If this doesn't solve your problem, please edit your question with more details; sample input data and expected output is always helpful in these situations.
Your data model seems odd.
Your columns are defined as varchar2. So why is your criteria numeric?
Also, why do you default the key columns to space? It would be better to leave unpopulated values as null. (To be clear, NULL is not a good thing in an indexed column, it's just better than a space.)

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

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.

How to make a good procedure in PL/SQL?

so I have just started to create procedure in pl/sql but my skills is very limited. I have this table:
bank_account (
NUM_CC NUMBER(10) CONSTRAINT PK_NUMCC PRIMARY KEY,
NUM_CLIENT NUMBER(10),
SOLD NUMBER(10)
)
I want to create a procedure to transfer an amount 'm' on my account, so i have write this procedure :
Create or replace procedure virement-cc(num-client number, num-cc number , m number)AS
Begin
UPDATE bank_account
SET SOLD = SOLD+m
WHERE NUM_CLIENT = num-client
AND NUM_CC = num-cc ;
End ;
This is procedure is not good but i would like to know how to improve it to resolve my problem. Thank you all.
don't use hyphen but underline
don't name parameters as columns; prefix them with e.g. p_. Otherwise, Oracle will simply do nothing (but set column's name to its current value) and you'd have impression that nothing happened
So:
Create or replace procedure virement_cc
(p_num_client number, p_num_cc number, p_m number)
AS
Begin
UPDATE bank_account
SET SOLD = SOLD + p_m
WHERE NUM_CLIENT = p_num_client
AND NUM_CC = p_num_cc;
End ;
You need to distinguish between 'num_cc' the input parameter and 'num_cc' the column name. Rename 'num_cc' the input parameter as 'p_num_cc'.
Your WHERE clause has an issue:
WHERE NUM_CLIENT = p_num_client
AND NUM_CC = p_num_cc ;
(I've gone ahead and renamed your input parameter)
If NUM_CC is the primary key (it is) then it uniquely identifies a particular role, so there is no need to include a comparison on num_client. And with that you don't even need an input parameter for it.
Give more thought to your naming conventions
I name all of my table columns in the format 'adjective_noun'. And don't be afraid to be descriptive. Instead of NUM_CC, how about CARD_NUMBER. Instead of NUM_CLIENT, try CLIENT_NUMBER. This 'adjective_noun' format also has the advantage of absolutely eliminating the possibility of accidentally trying to use a reserved or key word.
I name all of my parameters P_'adjective_noun'
I name all of my internal variables V_'adjective_noun'.
You may well decide on different naming standards. They key is to actually have naming standards, and that those standards be well thought out an reasoned.

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.

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

Resources