Oracle changes encoding - oracle

select rawtohex(UNISTR('\0436')) from dual
returns 0436
update my_table set my_column = UNISTR('\0436') where id = 248149;
SELECT rawtohex(my_column) from my_table where id = 248149;
returns E6
so I put symbol in UTF8 and get it back in CP1251. Why so?

You are saving the unicode string into varchar2 column. Consider saving them in the nvarchar2 type columns.
create table my_table
(
id number(10),
my_column varchar2(100),
my_column_uni nvarchar2(100)
);
insert into my_table values(1, UNISTR('\0436'), UNISTR('\0436'));
commit;
select rawtohex(my_column), rawtohex(my_column_uni)
from my_table
where id = 1;
The output will be E6 for varchar2 column and 0436 for nvarchar2 column. Oracle changes the encoding based on your nls parameters, where you have NLS_CHARACTERSET and NLS_NCHAR_CHARACTERSET NLS parameters. You can query your specific parameters by.
select *
from nls_database_parameters

Related

Comparing Nvarchar2 field with Varchar2 field in ORACLE database

so I have the table A with last_name column in varchar2 type, and a table B with last_name column in nvarchar2 type, I want to compare them to find differences
select *
from a
join b
on a.user_id = b.user_id
where CAST(lower(a.last_name) AS varchar2(100)) <> CAST(lower(a.last_name) AS varchar2(100))
but this brings me every row even when their last_name is the same

Oracle INSERTING into RAW with UTL_RAW.cast_to_raw

I ran into some code that was never implemented (see below).
CREATE TABLE encryption_values
(
NAME VARCHAR2(6),
VALUE NVARCHAR2(100)
);
/
insert into encryption_values
select 'key' name,
rawtohex (
rpad ('52AB32;^$!ER94988OPS3W21##=WTQ32',32,'X')
) value
from dual
union
select 'iv' name,
rawtohex (
rpad ('TY54ABCX12#÷×+==643QREVDG43AAYMN',32,'X')
) value
from dual;
I want to change the table definition from NVARCHAR2(100) to RAW(256). I tried using
UTL_RAW.cast_to_raw()
but I'm running into some syntax errors. Can someone please provide me with the correct syntax. Note I want to keep the RPAD to ensure I'm converting 32 character bytes.
I'm looking to INSERT the data into this table definition.
CREATE TABLE encryption_values
(
NAME VARCHAR2(6),
VALUE RAW(256)
);
/
You are using the wrong function, rawtohex. You must use in your case cast_to_raw from the package utl_raw
This function converts a VARCHAR2 value represented using some number
of data bytes into a RAW value with that number of data bytes. The
data itself is not modified in any way, but its datatype is recast to
a RAW datatype.
Demo
SQL> desc encryption_values
Name Null? Type
----------------------------------------- -------- ----------------------------
NAME VARCHAR2(6)
VALUE RAW(256)
SQL> insert into encryption_values
2 select 'key' name,
3 utl_raw.cast_to_raw (rpad('52AB32;^$!ER94988OPS3W21##=WTQ32',32,'X')) value
4 from dual
5 union
6 select 'iv' name,
7 utl_raw.cast_to_raw (rpad('TY54ABCX12#÷×+==643QREVDG43AAYMN',32,'X')) value
8* from dual
SQL> /
2 rows created.
SQL> select * from encryption_values ;
NAME
------
VALUE
--------------------------------------------------------------------------------
iv
5459353441424358313240EFBFBDEFBFBDEFBFBDEFBFBD2B3D3D3634335152455644473433414159
key
3532414233323B5E2421455239343938384F50533357323140403D5754513332

Number data type column is not behaving as number

I have a table in oracle which has column recid which is of number Datar type. The table is partition table and it has partition index on it.
When I query the partition like
select * from table partition (abc)
I am able to see value for rec id =50. But when I query
select * from table partition(abc) where rec id =50,
It doesn’t give any record .
If I do type casting as
select * from table partition(abc) where cast (recid as number ) =50
I am getting records.
Please let me know what might be the issue .?
The issue exist only for one partition and rest of the partition working normal.
If it's not behaving as a number, then it's not stored as a number.
Run a DESCRIBE (DESC) on your table in either SQL Developer, SQLcl, or SQL*Plus. It will show how the REC_ID column is defined.
If it's stored as a VARCHAR2, you wil get an error on your WHERE CLAUSE predicate for REC_ID, if not every REC_ID could be treated as also a number:
ORA-01722: invalid number
Like so:
SQL> DESC employees
Name Null? Type
EMPLOYEE_ID NOT NULL NUMBER(6)
FIRST_NAME VARCHAR2(20)
LAST_NAME NOT NULL VARCHAR2(25)
EMAIL NOT NULL VARCHAR2(25)
PHONE_NUMBER VARCHAR2(20)
HIRE_DATE NOT NULL DATE
JOB_ID NOT NULL VARCHAR2(10)
SALARY NUMBER(8,2)
COMMISSION_PCT NUMBER(2,2)
MANAGER_ID NUMBER(6)
DEPARTMENT_ID NUMBER(4)
SQL>
SQL> SELECT * FROM employees WHERE first_name = 50;
Error starting at line : 4 in command -
SELECT * FROM employees WHERE first_name = 50
Error report -
ORA-01722: invalid number
SQL> select * from emps_copy_num where first_name = 50;
EMPLOYEE_ID FIRST_NAME LAST_NAME EMAIL PHONE_NUMBER HIRE_DATE JOB_ID SALARY COMMISSION_PCT MANAGER_ID DEPARTMENT_ID
100 50 King SKING 515.123.4567 17-JUN-87 AD_PRES 24000 90
The first query fails - because not every value in that column can be simplicity cast as a number by the database.
The second query works, because I created a copy of the table where all of the first_name strings were values that COULD be cast as a number.
You probably have spaces in there somewhere, eg
SQL> create table t ( should_have_been_numeric varchar2(30));
Table created.
SQL>
SQL> insert into t values ('50 ');
1 row created.
SQL> insert into t values (' 50 ');
1 row created.
SQL> insert into t values (' 50');
1 row created.
SQL>
SQL> select * from t where should_have_been_numeric = '50';
no rows selected
SQL> select * from t where cast(should_have_been_numeric as number) = 50;
SHOULD_HAVE_BEEN_NUMERIC
------------------------------
50
50
50
3 rows selected.
but as already mentioned, if you are treating strings as numbers, then there is problems ahead in terms of spurious errors, not to mention potential performance issues because the optimizer also doesn't know that these are really numbers.

Oracle: Select Milliseconds from Timestamp Type that Defaults with SYSTIMESTAMP

I have a column with TIMESTAMP type in my Oracle Database. The default column value is SYSTIMESTAMP.
I want to SELECT milliseconds FROM the TIMESTAMP column. I use the query below without success:
SELECT TO_CHAR (MY_TIMESTAMP, 'dd-mm-yyyy hh24:mi:ss.FF') AS MY_TIMESTAMP
FROM MY_TABLE
-- Result: 20-12-2015 15:23:28.
As you see the result does not have any milliseconds and it is empty. If I change the query with .FF4 then it results .0000.
How can I SELECT the column with milliseconds?
The precision for timestamp columns can be set up by
TIMESTAMP [(fractional_seconds_precision)].
In your case for 4 it's:
create table my_table
(id number,
my_TIMESTAMP timestamp(4) default SYSTIMESTAMP);
You can check your current precision by:
select column_name, data_scale from user_tab_columns
where table_name = 'MY_TABLE' and column_name = 'MY_TIMESTAMP';
Here is sample in SQL Fiddle
The display can be change by:
alter session set NLS_TIMESTAMP_FORMAT = 'DD-MON-RRRR HH:MI:SS.FF9';

What is the difference between column_name and qualified_col_name?

The following query on the standard view user_tab_col:
select * from user_tab_cols;
returns on Oracle the columns column_name and qualified_col_name.
What is the difference?
qualified_col_name indicates full column path for XML tables. Basically it stores the expression for this column. For regular columns it will be equal to column_name.
If you run:
select owner, table_name, column_name, data_type, qualified_col_name
from all_tab_cols
where column_name <> qualified_col_name;
you will see returned columns from XML tables in XDB schema.
For example:
OWNER TABLE_NAME COLUMN_NAME DATA_TYPE QUALIFIED_COL_NAME
XDB XDB$SIMPLE_TYPE SYS_NC00074$ XDB$APPINFO_LIST_T "XMLDATA"."RESTRICTION"."MIN_INCLUSIVE"."ANNOTATION"."APPINFO"
Update:
For object tables qualified_col_name stores expression of type casting and accessing to attribute. For example:
create or replace type test1_obj as object(
n1 number,
n2 number,
s1 varchar2(10),
s2 varchar2(20)
)
not final;
create or replace type test2_obj under test1_obj(
d1 date,
d2 date
)
not final;
create table object_table of test1_obj;
select column_name, data_type, qualified_col_name
from user_tab_cols
where table_name = 'OBJECT_TABLE'
order by internal_column_id;
For last 2 hidden system columns reserved for instances of type test2_obj we can see:
COLUMN_NAME DATA_TYPE QUALIFIED_COL_NAME
SYS_NC00010$ DATE TREAT(SYS_NC_ROWINFO$ AS "TEST"."TEST2_OBJ")."D1"
SYS_NC00011$ DATE TREAT(SYS_NC_ROWINFO$ AS "TEST"."TEST2_OBJ")."D2"

Resources