Avoid inserting exponential value in DB Float column - sql

I have a table like
CONTACT
Name Null Type
------------------------------ -------- -----------
CONTACT_ID NOT NULL NUMBER
NAME NOT NULL VARCHAR2(45)
EMAIL NOT NULL VARCHAR2(45)
ADDRESS NOT NULL VARCHAR2(45)
TELEPHONE NOT NULL VARCHAR2(45)
AMOUNT NOT NULL FLOAT(126)
and the insert statement is:
Insert into contact("CONTACT_ID","NAME","EMAIL","ADDRESS","TELEPHONE","AMOUNT")
values ('36','babusailesh1117777','hainatu1#gmail.com','Vietnam1',
'0904277091','0.0000000555559080767');
When I see the final value inserted in the database, I see an exponential value.
How can I avoid this at database level for all tables?

It isn't stored as an exponential, it's stored in Oracle's internal number representation. When you query it, it's displayed with your sessions's current number format:
select 0.0000000555559080767 from dual;
0.0000000555559080767
---------------------------------------
5.6E-08
Which you can override in SQL*Plus or SQL Developer:
set numformat 999.9999999999999999999
select 0.0000000555559080767 from dual;
0.0000000555559080767
------------------------
.0000000555559080767
Or explicitly format the value as a string, for display only:
set numf ""
select to_char(0.0000000555559080767, '9990.9999999999999999999') from dual;
TO_CHAR(0.000000055555908
-------------------------
0.0000000555559080767
If you have a client application retrieving and using the value then it should query it as a float, into a suitable data type for the client's language, and then it's up to the client how it's displayed.
You also shouldn't be inserting a string into the float column, that just does an implicit conversion; the last argument in your insert should be 0.0000000555559080767 rather than the quoted '0.0000000555559080767'.

This is a function of the way the value is displayed, not what is being stored in the database. The database just stores a numeric float value, and whatever retrieves and displays the data decides how to display that. The exponential value you mention is common for displaying such floating point numbers.
You can have Oracle return a string formatted in a way for display using a function such as to_char, that allows you to set formatting. However, it may make more sense to handle this in whatever program or code is using the database.
Also note that floating point numbers have limited precision, so if you need to get that exact number string back, a float is not the way to go.

Related

How to convert VARCHAR2 to FLOAT in select statement in Oracle SQL

select mudel
from mudel
where 50 > TO_NUMBER(voimsus)
ERROR: ORA-01722: invalid number
Voimsus is a float number ex. 50.21 but datatype is VARCHAR2. Any idea how to convert it. Also I cant change datatype because there is data and there are child records.
Data
Datatypes
SOLUTION: I changed every comma to decimal with
UPDATE mudel
SET voimsus = REPLACE(voimsus, ',', '.')
WHERE voimsus LIKE '%,%'
and it worked
Assuming that your session's nls_numeric_characters setting specifies that a period is your decimal separator and a comma is your grouping separator (i.e. it has a value of ".,")
select *
from nls_session_parameters
where parameter = 'NLS_NUMERIC_CHARACTERS'
while the data in your table uses a comma as the decimal separator, that would be the problem. You could specify the NLS parameters you want to use in your to_number call
create table my_table( incorrect_data_type varchar2(10) );
insert into my_table( incorrect_data_type ) values( '123,45');
select to_number( incorrect_data_type,
'9999D99',
q'{nls_numeric_characters=',.'}')
from my_table;
Or you could change your session's settings
alter session set nls_numeric_characters = ',.'
select to_number( incorrect_data_type) from my_table;
Of course, if you solve the problem by changing your session's settings, that means that when you (or someone else) starts a new session, they'll need to change their session's settings as well (assuming they use the same NLS settings to establish the connection that you are).
The right answer, of course, is to use the correct data type for the column in the first place. Storing numeric data in a character column is going to cause plenty of grief-- this is just one of the ways that tends to go wrong. Fixing the data type now will save you lots of grief down the line.
Here's a fiddle showing the options working (and failing).
When converting strings to numbers, then don't rely on session settings by merely using
to_number(voimsus)
but specify the format stored in the string. For this you must tell the DBMS what the decimal separator is with NLS_NUMERIC_CHARACTERS. E.g.:
TO_NUMBER(voimsus, '9999999999D.99', 'NLS_NUMERIC_CHARACTERS='',.''')
But well, it is of course much better not to store numbers in string columns in the first place. Use a proper number type such as NUMBER(12,2) instead. (And I recommend not to use any float data type, such as (BINARY_FLOAT), because then your stored numbers are not exact, but approximate, e.g. 1.3 may be stored as something like 1.3000001).

I can't understand SQLite

So I've been learning a lot of SQL in school using MySQL , Oracle and SQL Server. So now i need to work with SQLite on a raspberry pi project. The thing I don't understand is datatypes. When you put your field to be int it can only save whole numbers right? And in SQLite it can save integers inside of a int datatype. So i have been reading about it and how SQLite saves data in these groups:
NULL. The value is a NULL value.
INTEGER. The value is a signed integer, stored in 1, 2, 3, 4, 6, or 8 bytes depending on the magnitude of the value.
REAL. The value is a floating point value, stored as an 8-byte IEEE floating point number.
TEXT. The value is a text string, stored using the database encoding (UTF-8, UTF-16BE or UTF-16LE).
BLOB. The value is a blob of data, stored exactly as it was input.
So it only makes a difference when saving data and not on input? I can't understand it.. How can I make my INT columns not accept integers? Or it isn't possible?
The SQLite dialect of SQL is a dynamically-typed language. Just like Python will let you create an array of mixed types like [None, 42, 3.14, 'Hello, world!', b'\x01\x23'], SQLite will let you store values of multiple types in the same column.
Storage classes
Conceptually, SQLite has five scalar data types, called “storage classes”:
The NULL type is used for the singleton value NULL, which is a sentinel value indicating an unknown or not-applicable value.
The INTEGER type is a 64-bit signed integer. The part about “stored in 1, 2, 3, 4, 6, or 8 bytes depending on the magnitude of the value” is an implementation detail of the file format, and not something you as a programmer need to be concerned with. From the point of view of the C API and the SQL language, it's always 8 bytes.
The REAL type is a 64-bit floating-point number.
The TEXT type is a character string.
The BLOB type is a sequence of octets. SQL literals are X-prefixed strings of hex digits (e.g., X'0123456789ABCDEF').
If you're a Python 3.x programmer, you can think of:
NULL = None (of type NoneType)
INTEGER = int (but limited to 64 bits)
REAL = float
TEXT = str
BLOB = bytes
(This is actually the type mapping used by Python's standard sqlite3 module.)
If you're a C# programmer, you can think of:
NULL = null (but without the arbitrary distinction between value types and reference types)
INTEGER = long
REAL = double
TEXT = string
BLOB = byte[]
SQLite lets you store a value of any data type in any column. (Exception: If a column is declared as INTEGER PRIMARY KEY, and its table is not declared WITHOUT ROWID, then it actually is constrained to contain only integers, because it is an alias for the row ID.)
Column type affinity
Independent of the above list of “storage classes”, SQLite has the concept of type affinity which determines the preferred data type to store in a column. The affinitity of a column is determine by its declared datatype.
Only numeric (INTEGER and REAL) and TEXT values are affected by these automatic type conversions; there is never any implicit conversion to or from the NULL or BLOB storage classes.
So, if you declare a column with integer affinity (e.g., INT or INTEGER), but you insert a text string into it, then SQLite will automatically convert the value to an integer for you. But if it can't, it leaves it as a string. So, the string '42' becomes the integer 42, but the string 'xyz' stays as-is.
Real-affinity columns (REAL, FLOAT, DOUBLE) are similar, except that they attempt to convert strings into REAL values instead of INTEGER values. Numeric-affinity columns (NUMERIC, DECIMAL) convert strings to numbers, but will happily allow INTEGER and REAL values in the same column.
Text-affinity columns (CHAR, VARCHAR, TEXT, CLOB) will make the opposite conversion: All numbers (integer or real) are converted to strings.
Blob-affinity columns (BLOB or no declared data type) leave all values as-is.
No, it is wrong to say that in SQLite if you declare an INT column it will only accept integer values. In SQLite, you can store any datatype in any column. Therefore, you can declare the column AGE INTEGER and store the value 'I am pretty old', of type TEXT in that column.
This is quite different from virtually every other relational database, which requires the type of the value to match the type of the column it is stored in.
The actual value determines the type.
Similar to Excel.
You don't even have to define types for columns, e.g. -
create table t (c1,c2,c3);
https://www.sqlite.org/datatype3.html
Datatypes In SQLite
Most SQL database engines (every SQL database engine other than
SQLite, as far as we know) uses static, rigid typing. With static
typing, the datatype of a value is determined by its container - the
particular column in which the value is stored.
SQLite uses a more general dynamic type system. In SQLite, the
datatype of a value is associated with the value itself, not with its
container. The dynamic type system of SQLite is backwards compatible
with the more common static type systems of other database engines in
the sense that SQL statements that work on statically typed databases
should work the same way in SQLite. However, the dynamic typing in
SQLite allows it to do things which are not possible in traditional
rigidly typed databases.
drop table if exists t;
create table t (studentId int);
insert into t (studentId) values (1),(2),('Say what?'),(3),('Yep!');
select studentId from t;
sqlite> drop table if exists t;
sqlite> create table t (studentId int);
sqlite> insert into t (studentId) values (1),(2),('Say what?'),(3),('Yep!');
sqlite> select studentId from t;
studentId
----------
1
2
Say what?
3
Yep!
sqlite> .header on
sqlite> drop table t;
sqlite> create table t (studentId text);
sqlite> insert into t (studentId) values (1),(2),('Say what?'),(3),('Yep!');
sqlite> select studentId,studentId * 10 from t;
studentId studentId * 10
---------- --------------
1 10
2 20
Say what? 0
3 30
Yep! 0

ORA-12899 value too large for column despite of same length

I am running the following query. But getting ORA-12899. Altough the length of string am trying to insert is 30.
INSERT INTO TABLE1 SELECT * FROM temp_Table1 where LENGTH(column1)=30;
SQL Error: ORA-12899:value too large for column "TABLE1"."column1" (actual: 31, maximum: 30)
select column1 from temp_Table1 where LENGTH(column1)=30;
Testing  - HLC/TC Design Corre
Desc temp_Table1
column1 VARCHAR2(30)
Desc Table1
column1 VARCHAR2(30)
You're seeing the difference between character and byte length semantics:
You must specify a maximum length for a VARCHAR2 column. This maximum must be at least 1 byte, although the actual string stored is permitted to be a zero-length string (''). You can use the CHAR qualifier, for example VARCHAR2(10 CHAR), to give the maximum length in characters instead of bytes. A character is technically a code point of the database character set. You can use the BYTE qualifier, for example VARCHAR2(10 BYTE), to explicitly give the maximum length in bytes. If no explicit qualifier is included in a column or attribute definition when a database object with this column or attribute is created, then the length semantics are determined by the value of the NLS_LENGTH_SEMANTICS parameter of the session creating the object.
If your session is using byte semantics then the column in your table will default to that:
select value from nls_session_parameters where parameter = 'NLS_LENGTH_SEMANTICS';
VALUE
----------------------------------------
BYTE
create table t42(text varchar2(5));
Table T42 created.
select char_used from user_tab_columns where table_name = 'T42' and column_name = 'TEXT';
C
-
B
That is the same as explicitly doing:
create table t42(text varchar2(5 byte));
If your source data is five characters but includes any multibyte characters then the number of bytes will exceed five:
insert into t42 (text) values ('Hello');
1 row inserted.
insert into t42 (text) values ('Señor');
SQL Error: ORA-12899: value too large for column "SCHEMA"."T42"."TEXT" (actual: 6, maximum: 5)
Which is what you're seeing. When you insert the values from your other table you are filter on the length of the values, but length() counts characters rather than bytes. There is a lengthb() function that does count bytes. If you check the byte length of the 30-character value you're selecting you'll see it is in fact 31 bytes, so one of those characters is multibyte.
with t42 (text) as (
select 'Hello' from dual
union all select 'Señor' from dual
union all select 'Testing  - HLC/TC Design Corre' from dual
)
select text, length(text) as chars, lengthb(text) as bytes, dump(text, 16) as hex
from t42;
TEXT CHARS BYTES HEX
------------------------------- ----- ----- ----------------------------------------------------------------------------------------------------------
Hello 5 5 Typ=1 Len=5: 48,65,6c,6c,6f
Señor 5 6 Typ=1 Len=6: 53,65,c3,b1,6f,72
Testing  - HLC/TC Design Corre 30 31 Typ=1 Len=31: 54,65,73,74,69,6e,67,c2,a0,20,2d,20,48,4c,43,2f,54,43,20,44,65,73,69,67,6e,20,43,6f,72,72,65
From the dump() values you can see that after Testing (54,65,73,74,69,6e,67) and before the space and dash (20,2d) you have c2,a0, which is the UTF-8 multibyte non-breaking space character. (You often see that, along with curly quotes and other non-ASCII-range characters, in text that has been copied from,. say, a Word document).
You can either change your insert to filter on LENGTHB(column1)=30 (which will exclude the row you currently find), or change your column definition to 30 characters instead of 30 bytes:
drop table t42;
Table T42 dropped.
create table t42(text varchar2(5 char));
Table T42 created.
select char_used from user_tab_columns where table_name = 'T42' and column_name = 'TEXT';
C
-
C
insert into t42 (text) values ('Hello');
1 row inserted.
insert into t42 (text) values ('Señor');
1 row inserted.
Or replace any unexpected multibyte characters with single-byte equivalents, if that's possible and makes sense for your data; in this case a normal space might work, but with any substitution you are destroying information that might actually be important.
Try to change your table like
ALTER TABLE1 MODIFY column1 VARCHAR2(30 CHAR)
The error states that your column1 can store maximum of 30 characters and you are passing more than 30 characters in it which results in the error.
You can also refer this article: Oracle Database - Bytes or Characters for VARCHAR2 and CHAR
ORA-12899
Often times, as our companies grow and evolve in response to an
expansion in the form of client-base, staff, profit or markets, the
data associated with this growth will also change. Data systems like
Oracle have the innate ability to remain fairly flexible in regards to
working with this variance in information. Still, even the most
versatile database systems require maintenance and refining in the
face of increased data traffic. This work is essential to
accommodating any constraints on memory or necessary redefinitions of
parameters. The ORA-12899 error is representative of an instance in
which either an uptick in data or a user error is forcing Oracle to
stall during its requested action.
THE PROBLEM
The ORA-12899 is an Oracle error that occurs when the value entered
into the column string is too large. What this means is that an
attempt was made by the user to update or insert a column with a value
that is too wide for the destination column. The name of a particular
column will be given and the actual width of the value, as well as the
maximum width permitted for the column, will be associated with that.
As mentioned, the value can be given in the form of characters. In the
event that the width is reported in characters, this will mean that
character length semantics are operating for the column. Otherwise the
width will be reported in bytes. Essentially, this error results from
trying to push through a value, or set of values, that exceed the
specified maximum width of the column. So, how does a user correct
this type of error?
THE SOLUTION
To begin, open up the OERR utility. The user will require the full
ORA-12899 message to receive the proper feedback on the error. This
will provide more information on the error and allow further
investigation. Typically, the error can come from one of three
sources. The first source is the SQL statements that have been
generated. Checking source and destination column data types to
discover whether they are compatible with current formats is the
second source. Lastly, the user can look at the destination column
width – where the value is being assigned – to make sure it is large
enough to accommodate the maximum value that the user anticipates
assigning. Let us now turn to an example that corrects ORA-12899.
Suppose the user has created the following table:
CREATE TABLE Clients(
ClientID varchar2(9) PRIMARY KEY,
Client_Contact varchar2(40) NOT NULL,
Address varchar(20) NOT NULL,
Zip varchar2(5) NOT NULL,
Client_Number varchar2(11) NOT NULL)
The user then attempts to issue an INSERT VALUES statement that looks
something like this:
INSERT INTO Clients VALUES(
727546345,
‘Roger Holcomb’,
‘—Benjamin Road Syracuse’,
‘-----‘, 05307623754)
The user might try to run the statement from here, but will receive
the following error message:
Error starting at line 7 in command: INSERT INTO Clients
VALUES(727546345, ‘Ricky Galorey’, ‘18 Benjamin Road Syracuse’,
‘13208’, 05307623754) Error report: SQL Error: ORA-12899: value too
large for column “ORGANIZATIONS”. “MARKET”. “ADDRESS”(actual: 25,
maximum: 20) 12899. 00000 – “value too large for column %s (actual:
%s, maximum: %s)”
This error statement indicates that the variable ‘Address’ cannot hold
more than twenty characters as that would exceed the width of the
column parameter. When we look back at the address value (’18 Benjamin
Road Syracuse’) we can see that the total number of characters (25)
exceeds the maximum number allowed for the width of the column. To
correct this, the user can change the VARCHAR2 for address to an
amount that can accommodate the typical address length that their
company would input.
The above answer original URL
Due to different NLS settings in the target table database it might require more bytes in the target.
Try altering the table as
alter Table1 modify column1 varchar2(30 char)

SQL Datatype to use when inserting money

I am using Oracle SQL database and I have to insert a monetary value(salary) as part of a row. For some strange reason the money command isnt working, is there any alternates that would work with this?
Data input format: £00,000.000
CREATE TABLE staff
(staffno CHAR(6) NOT NULL
, staffsurname VARCHAR(8) NOT NULL
, staffforename VARCHAR(7) NOT NULL
, salary MONEY NOT NULL
, PRIMARY KEY (staffno)
);
Look at this line
salary MONEY NOT NULL
There is no existing money datatype.
If you are looking for something similar to SQL-Server small money type, you want to use a Number(10,4) and then format the number.
You can format the number using to_char function
select to_char(yourColumn, '$99,999.99') from yourTable where someCondition
The "strange" reason is simple: There is no MONEY data type.
The data type most appropriate for monetary values would be NUMBER (using an appropriate scale). Since it is a decimal floating-point type, it is better suited for monetary values than the binary floating-point types BINARY_FLOAT and BINARY_DOUBLE.
Note, though, that you will still need to parse the input string £00,000.000 in your front end and send it as a numeric value to the back end.

How to restrict the length of INTEGER when creating a table in SQL Server?

When creating a table in SQL SERVER, I want to restrict that the length of an INTEGER column can only be equal 10.
eg: the PhoneNumber is an INTEGER, and it must be a 10 digit number.
How can I do this when I creating a table?
If you want to limit the range of an integer column you can use a check constraint:
create table some_table
(
phone_number integer not null check (phone_number between 0 and 9999999999)
);
But as R.T. and huMpty duMpty have pointed out: a phone number is usually better stored in a varchar column.
If I understand correctly, you want to make sure the entries are exactly 10 digits in length.
If you insist on an Integer Data Type, I would recommend Bigint because of the range limitation of Int(-2^31 (-2,147,483,648) to 2^31-1 (2,147,483,647))
CREATE TABLE dbo.Table_Name(
Phone_Number BIGINT CONSTRAINT TenDigits CHECK (Phone_Number BETWEEN 1000000000 and 9999999999)
);
Another option would be to have a Varchar Field of length 10, then you should check only numbers are being entered and the length is not less than 10.
I would recommend you to use varchar as phone number(only for phone numbers as some phone numbers may contain hyphen,phus sign) and restrict the length to 10 ie, varchar(10).
As correctly pointed by a_horse_with_no_name in comments you can put constraint on the numbers to be of specified range like this:
check (phone_number between 0 and 9999999999)
Also on a side note:-
You will receive a error message like this if you use numbers outside the range of int -2147483648 through 2147483647
Arithmetic overflow error converting expression to data type int.
So you will not be able to use all the int of length 10 in your case.
As per me Phone number should not be stored in integer as we are not going to do any numeric operation on it like adding dividing .we are going to treat it as string for e.g. finding all number with ISD say '91' or STD '022' etc secondly if you switch to make it integer you have to handle overflow
I don't think there is a way to limit if you use number fields like int, bigint, smallint, and tinyint
Make a varchar(10) field and validate before insert
Still you need to use int field to store the phone number, you will need to restrict before in your application
Make column varchar and create a check that it strictly should have 10 characters
create table some_table
(
phone_number varchar(10) check (len(phone_number)=10)
);
First consider internal and external format:
Yes, a telephone number can be stored as an integer. You would have to assure however that all numbers are stored in the same format, e.g. as the international number without the plus sign. 4940123456 would then be a German number for instance, as 49 is the German country code. To analize the number later, however, would be difficult; country codes can be 1 to 4 digits, followed by a presumably unknown number of area code digits. But just to know a number and not to know its structure may be sufficient for your purposes. With check constraints you could assure that the number is positive and not longer than, well, how long is the longest number allowed? Be aware: Everytime you show the number, you may have to format the output (in the example given: add a leading plus sign to the number).
The other way would be to store phone numbers as strings. That would make it possible to store numbers such as '+49-40-123456'. Then the internal format is the same as the external. Advantage: You wouldn't have to think of formatting the output everytime you show the number. But you could even change the format on output if you wanted (remove dashes or replace the plus sign with the actual county dial code or remove country and area code for local calls, etc.) You would have to decide whether to enforce a certain format or not. If not, then numbers could look very different '123456', '004940123456', '040/123456', ... To enforce a certain format, you would write a function (because of the complexity of such a format) and use that in a check constraint. Or write an insert trigger (this should be a BEFORE INSERT trigger, because you want to change a value; as T-SQL doesn't provide this, you would use an INSTEAD OF INSERT trigger instead) to have the field formatted as you desire.
My recommendation is:
CREATE TABLE trial_table (phone_number VARCHAR(13));
The column can be used for international numbers too.