Number becomes to BigDecimal after the hibernate reverse engeering? - oracle

I set the field as Number like below in the oracle database.
name type length scale
EMP_GENDER NUMBER 0 0
After the hibernate reverse engineering,this filed's type becomes to BigDecimal.
private BigDecimal empGender;
But when I set the length to 2 in database,it could be right and field type in the entity become to Integer.
How did this happen?

When Hibernate reverse engineers your schema, that will use Oracle's Mete-data tables to extract table and columns information.
One of the them will be user_tab_columns View.
Having
create table EMP (EMP_GENDER number);
To extract EMP table,s column information you may use:
select *
from user_tab_columns
where user_tab_columns.TABLE_NAME = 'EMP'
The query result will be characterization of every column of EMP table.
We will see DATA_TYPE , DATA_LENGTH and DATA_PRECISION columns.(using Oracle 10 g)
Having:
create table EMP (EMP_GENDER number(2));
We will see
When not defining precision for numeric type, the DATA_LENGTH (default is 22 ) will be treated as precision.
So a number with length of 22 will be translated to Big-decimal by Hibernate(that will exceed the maximum precision of decimal data type)
When numeric type precision is equals to 2, the Integer data type will be sufficient.
You must specify the exact numeric precision on table creation to prevent the problem.

Related

How does Number data type work in Oracle 21c?

I created a table like this:
CREATE TABLE table(
id INTEGER GENERATED ALWAYS AS IDENTITY,
nome VARCHAR2(100 CHAR)
)
ALTER TABLE table ADD CONSTRAINT table_pk PRIMARY KEY (ID);
CREATE UNIQUE INDEX TABLE_UNIQ_IDX ON TABLE(NOME ASC);
ALTER TABLE table ADD (PERC NUMBER(1, 2) NOT NULL);
Then I tried to write 2 records on it:
INSERT INTO TABLE(NOME,PERC)VALUES('a',0.8);
INSERT INTO TABLE(NOME,PERC)VALUES('b',0.2);
Then I received this error:
ORA-01438: valor maior que a precisão especificada usado para esta coluna
Translated:
ORA-01438: value larger than specified precision allows for this column
I tried select cast (0.8 as number(1,1)) from dual; and it worked but when I tried select cast (0.8 as number(1,2)) from dual; I received the same error.
I then tried select cast (0.81 as number(1,2)) from dual; and received the same ORA-01438.
I changed my field to number(1,1), no big deal, but how does this "Number" data type work?
Shouldn't select cast (0.81 as number(1,2)) from dual; have worked?
Why does select cast (0.81 as number(2,2)) from dual; work and
select cast (0.81 as number(2,3)) from dual; does not?
Thanks for any help
If you have NUMBER(precision, scale) then precision is the number of digits and scale is the number of decimal places.
So, NUMBER(1, 2) has a single digit and 2 decimal places. The minimum value it can store is -0.09 and the maximum it can store is +0.09.
NUMBER(2,2) works as it stores 2 digits in 2 decimal places (from -0.99 to +0.99).
NUMBER(2,3) does not work as it stores 2 digits in 3 decimal places (from -0.099 to +0.099).
What you said, is that perc column should accept numeric values whose length is 1, and out of that 1, you want to keep 2 decimal places. That won't work.
SQL> create table test (perc number(1, 2));
Table created.
SQL> insert into test values (0.8);
insert into test values (0.8)
*
ERROR at line 1:
ORA-01438: value larger than specified precision allowed for this column
Perhaps you meant to put it vice versa?
SQL> alter table test modify perc number(2, 1);
Table altered.
SQL> insert into test values (0.8);
1 row created.
SQL>

when we declared number datatype in oracle what it will take default data type?

I was declared one column in oracle datatype is number ex:cust_acc_no NUMBER (9) DEFAULT (0),.
After creating table that column take double datatype why?
but that column is account number so when i select that particular field it shows account numbers with decimal.
If you didn't put any decimal numbers into it, then they aren't decimal numbers. If you think they are, please, post an example - copy/paste your SQL*Plus session which shows what you're saying. I suspect that it is matter of formatting, not data storage.
By the way, you could have used the INT datatype, e.g.
SQL> create table test (cust_acc_no int default 0);
Table created.
SQL> insert into test
2 select 100 from dual union
3 select 0.5 from dual union
4 select 20.6 from dual;
3 rows created.
SQL> select * from test;
CUST_ACC_NO
-----------
1
21
100
SQL>

Resulting precision of operations on Oracle NUMBER

What is the precision of the value resulting in an operator on 2 Oracle default/as-given NUMBER columns (where NUMBER has no (p,s) set))? Like if I:
create table foo(field1 NUMBER, field2 NUMBER);
insert into foo (field1, field2) values (1.1, 3);
select field1/field2 as f1df2 from foo;
Will f1df2 be 0.3666666666666...7?
Will f1df2 be 0.3666666666666...7?
Yes.
Numbers inserted into NUMBER columns that were created without setting p,s are stored 'as given'. The resulting precision of an operation on these columns appear to be the precision and scale of highest precision and scale column:
create table test_number(f1 number, f2 number, f3 integer);
-- remember integer in Oracle is NUMBER(38)
insert into test_number (f1, f2, f3) values (1.1, 3, 4);
select f1/f2 as f1df2, f2/f3 as f2df3 from test_number
Results in:
F1DF2 |F2DF3
------------------------------------------|-----
0.3666666666666666666666666666666666666667|0.75
Note that this is true even if f1 was re-defined to be NUMBER(p, 1)! It appears that defining (p,s) for a NUMBER field only restricts precision of the data being entered into the field.
Now, what happens if we mixed the arbitrary precision type with a float? Well, according to Oracle Numeric Precedence rules:
If any of the operands is BINARY_DOUBLE, then Oracle attempts to convert all the operands implicitly to BINARY_DOUBLE before performing the operation.
If none of the operands is BINARY_DOUBLE but any of the operands is BINARY_FLOAT, then Oracle attempts to convert all the operands implicitly to BINARY_FLOAT before performing the operation.
Otherwise, Oracle attempts to convert all the operands to NUMBER before performing the operation

Oracle Number data type and its strictness

I'm very new to oracle but I've been learning about it in class and I've recently come across the number data type. I've read the documentation regarding scale and precision (s,p) but I still am not positive regarding the type's proper usage.
Let's say I want to store percent values as a decimal. The decimal can be anywhere from 0 to 1 and may have up to 3 numbers following the decimal place.
Some possible decimals to be stored may include:
.66
.553
1.00
If I were to make the column NUMBER(4,3) would that work EVEN IF there were only two numbers? See below
.22
.10
.35
etc...
In short, does the number type require that the EXACT sizes are met? Eg. Would NUMBER(4,3) ABSOLUTELY REQUIRE that the data inserted is 4 numbers, 3 of them falling after the decimal place?
Thanks for the help!
Data types for columns limit the range of values that can be stored. But they don't do anything to force a particular length or precision.
Just like you can store a single character or a NULL in a VARCHAR2(100) column, you can store numbers with less than 3 digits of precision and less than 4 digits of scale. For example, the values 0 and 6.1 are both perfectly valid for a NUMBER(4,3) column. If you insert a value that has too many digits of precision, the value will be silently rounded to the precision specified in the column definition.
SQL> create table foo (
2 col1 number(4,3)
3 );
Table created.
SQL> insert into foo values( 9.999 );
1 row created.
SQL> insert into foo values (0);
1 row created.
SQL> insert into foo values( 6.1 );
1 row created.
SQL> insert into foo values( 1.2345 );
1 row created.
SQL> select * from foo;
COL1
----------
9.999
0
6.1
1.235

OCI: Determine length of text representation of query columns

My goal is to execute a query (SELECT), fetch results and output them as text. Query is given as a parameter and can be e.g. select * from t.
I use OCIStmtPrepare and OCIStmtExecute, then I can describe columns of the query by OCIParamGet and series of OCIAttrGet. Suppose I get OCI_ATTR_DATA_TYPE = 12 (DATE) for one of the columns. Then OCI_ATTR_DATA_SIZE = 7 -- this is size of internal DATE representation.
I want to get this DATE as text, with respect to currect NLS settings. For that I use OCIDefineByPos with dty = SQLT_STR. It works alright, but I also need to supply a buffer for fetching. The question is: what size of buffer do I need?
Evidently it depends on NLS_DATE_FORMAT. I believe that Oracle knows this value:
SQL> create table x as select to_char(sysdate) d from dual;
Table created.
SQL> select value from nls_session_parameters where parameter='NLS_DATE_FORMAT';
VALUE
----------------------------------------
DD.MM.RR
SQL> select data_length from dba_tab_columns where table_name='X';
DATA_LENGTH
-----------
8
This is the exact length. Only when date format is masked from Oracle (by a function, for example), it uses absolute maximum (?) value of 75:
SQL> create or replace function get_date_format return varchar2 is
2 begin
3 return 'DD.MM.RR';
4 end;
5 /
Function created.
SQL> create table x as select to_char(sysdate,get_date_format) d from dual;
Table created.
SQL> select data_length from dba_tab_columns where table_name='X';
DATA_LENGTH
-----------
75
All said above applies to NUMBER as well.
So, is it possible to get length of text representation of a column in OCI?
The maximum buffer size for any date is 75. The maximum buffer size for any number is 42.
I hope that helps.
You can determine needed buffer size by calling OCIAttrGet for OCI_ATTR_DISP_SIZE attribute. It returns 40 for NUMBER, 75 for DATE, N for VARCHAR2(N). Add 1 byte for Null-termination and you good to go.
Yes - the trick is that in C, a string is really a pointer to a character array, so you would say char* mystring = OCIStringPtr(envhp, x); where x is a pointer to an OCIString, which you can get back by connecting with OCI_OBJECT set and asking for a SQLT_VST instead of an SQLT_STR. The actual memory for the string is allocated for you in the global env by OCI behind the scenes.

Resources