Changing precision of numeric column in Oracle
Assuming that you didn't set a precision initially, it's assumed to be the maximum (38). You're reducing the precision because you're changing it from 38 to 14.
The easiest way to handle this is to rename the column, copy the data over, then drop the original column:
alter table EVAPP_FEES rename column AMOUNT to AMOUNT_OLD;
alter table EVAPP_FEES add AMOUNT NUMBER(14,2);
update EVAPP_FEES set AMOUNT = AMOUNT_OLD;
alter table EVAPP_FEES drop column AMOUNT_OLD;
If you really want to retain the column ordering, you can move the data twice instead:
alter table EVAPP_FEES add AMOUNT_TEMP NUMBER(14,2);
update EVAPP_FEES set AMOUNT_TEMP = AMOUNT;
update EVAPP_FEES set AMOUNT = null;
alter table EVAPP_FEES modify AMOUNT NUMBER(14,2);
update EVAPP_FEES set AMOUNT = AMOUNT_TEMP;
alter table EVAPP_FEES drop column AMOUNT_TEMP;
PL/SQL instruction to get numeric column precision
You can find this information in user_tab_cols
and all_tab_cols
views:
create table tbl1_1(column_1 number(8,3));
select column_name, data_precision, data_scale
from user_tab_cols
where table_name = 'TBL1_1' and column_name = 'COLUMN_1';
COLUMN_NAME DATA_PRECISION DATA_SCALE
------------------------------ -------------- ----------
COLUMN_1 8 3
numeric precision in Oracle
The docs also state:
The FLOAT data type is a subtype of NUMBER
So it's a number
under the covers and
To convert from binary to decimal precision, multiply n by 0.30103
Plugging the numbers in:
49 * 0.30103 = 14.75047
50 * 0.30103 = 15.05150
51 * 0.30103 = 15.65356
So float(50)
and float(51)
correspond to number(16)
, whereas float(49)
is number(15)
You can verify this by taking a dump
of the values:
create table numeric_types2 (
f1 float(60), n1 number
);
insert into numeric_types2
with rws as (
select BIN_TO_NUM(
1,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,1) n from dual
)
select n, n from rws;
select dump ( f1 ), dump ( n1 ),
dump ( cast ( n1 as float(50) ) ) df50,
dump ( cast ( n1 as float(49) ) ) df49
from numeric_types2;
DUMP(F1) DUMP(N1) DF50 DF49
Typ=2 Len=9: 200,46,4,60,97,28,38,5,98 Typ=2 Len=9: 200,46,4,60,97,28,38,5,98 Typ=2 Len=9: 200,46,4,60,97,28,38,5,98 Typ=2 Len=8: 200,46,4,60,97,28,38,6
Note that
dump ( f1 ) = dump ( n1 ) = dump ( cast ( n1 as float(50) ) )
Only casting the number as float(49)
gives a different value.
Finally note that the docs also contain this recommendation:
Oracle FLOAT is available for you to use, but Oracle recommends that
you use the BINARY_FLOAT and BINARY_DOUBLE data types instead, as they
are more robust
Modifying an Oracle number column
ALTER TRIGGER trfoobar DISABLE;
ALTER TABLE foobar ADD (newcol number);
UPDATE foobar SET newcol=oldcol, oldcol=null;
ALTER TABLE foobar MODIFY(oldcol number(22,2));
UPDATE foobar SET oldcol=newcol;
ALTER TABLE foobar DROP(newcol);
ALTER TRIGGER trfoobar ENABLE;
Oracle Save decimal in a column with number datatype
In Oracle, you may (but are not required to) give both a precision and a scale to columns of NUMBER
data type. NUMBER(20)
is valid shorthand for NUMBER(20,0)
, meaning 20 digits, none after the decimal point.
How to fix it depends on your needs. Normally a NUMBER
column should be declared simply as NUMBER
. Specify precision and scale only if you have a good reason to.
For example: if your numbers must be limited to no more than 20 digits before the decimal point and no more than six decimal places (after the decimal point), the total PRECISION is 20 + 6 = 26. You would then declare NUMBER(26, 6)
.
You can change a column declared as NUMBER(20)
to NUMBER
(if that meets your needs otherwise), since there is no loss of information in this change. However, note that numbers that are ALREADY saved in the column have ALREADY LOST information, which cannot be recovered from the table; you will need to go to the original source of those numbers, if you need to fix it.
Brief demo (notice in the last output that the row inserted BEFORE the change has its value forever changed to 10, with no recovery possible):
create table test_tbl
(
amt number(20)
);
insert into test_tbl values (9.999);
select * from test_tbl;
AMT
---
10
alter table test_tbl modify (amt number);
insert into test_tbl values (9.999);
select * from test_tbl;
AMT
-----
10
9.999
Related Topics
Sql-Server: Error - Exclusive Access Could Not Be Obtained Because the Database Is in Use
Multiple Full Outer Join on Multiple Tables
Tricks for Generating SQL Statements in Excel
Accessing JSON Array in SQL Server 2016 Using JSON_Value
How to Count Rows That Have the Same Values in Two Columns (Sql)
How to Insert a Unique Id into Each SQLite Row
How to Add Results of Two Select Commands in Same Query
Parse JSON into Oracle Table Using Pl/Sql
How to Bulk Insert a File into a *Temporary* Table Where the Filename Is a Variable
Identity_Insert Is Set to Off - How to Turn It On
Declare Variable for a Query String
Prevent Recursive Cte Visiting Nodes Multiple Times
Postgresql Changing Data Directory in Ubuntu
SQL Server Management Studio 2012 - Export All Tables of Database as CSV
Postgresql Prefix Wildcard for Full Text