setting the length of an integer column in Postgres - postgresql

I have a table called "User_details" in my Postgres database with a column as "Mobile_no" with data type as Integer.
Now when I try inserting an integer value of length 10, I get the following error
ERROR: integer out of range
I know this can be resolved if i set the data type to bigint or may be even numeric(10,0) but i want to use Int as the data type.
Any possible solution to set the length of an Integer column in Postgres?

On PostgreSQL an integer type can hold values between -2147483648 and +2147483647 so if the value to insert is "greater than" there is no way to store it on database, only by modifying the data type for example to bigint you will be able to store greater values (bigint can hold values between -9223372036854775808 to +9223372036854775807).
Please check https://www.postgresql.org/docs/current/static/datatype-numeric.html

Related

Postgres unsigned integer primary key maximum

Postgres integer range is from -2147483648 to +2147483647. In mysql as i know you can use unsigned integer as primary key and get twice values for pk when it starts from 1 (2147483647*2).
I'm not sure is there a way to increase postgres integer range pk sequence from 2147483647 to 2147483647*2 if i don't need negative values? Can i just change maximum to 2147483647*2?
Postgres doesn't have unsinged int. For a primary key with more than 2147483647, consider using bigserial.
You can simply set a large number for MAXIMUM and Postgresql will use the relevant numeric type for the counter. Here is an example:
CREATE SEQUENCE the_long_road
MINVALUE 1
MAXVALUE 123456789012345
START WITH 123456789000000;
-- try it several times
SELECT nextval('the_long_road');
Well if you really want an integer you can get the range of values you want. You just have the keep in mind that the only purpose of a generated key is making the row unique in the table - nothing else. In that view negative values work perfectly well. So
create sequence long_wrap_seq as integer
minvalue -2147483648
maxvalue +2147483647
start with 1
cycle;
create table long_wrap_seq(id integer default nextval('long_wrap_seq')
, ...
);
You now have a the sequence range 2147483647*2 (actually +1).

How to change type from array to primitive in PostgreSQL?

I'm trying to change a column type from integer[] to integer. The table has no row in it and I've already dropped the default.
alter table user alter column book_ids type integer USING book_ids::integer;
ERROR: cannot cast type integer[] to integer
I could only found how to change type from integer to integer[] but not the other way around.
arr[1] is the first element of arr.
alter table user alter column book_ids type integer USING book_ids[1];

Why does creating a table with a serial column create a sequence with a max val of a bigint?

I am a little confused and new to PostgreSql , I thought that serial = integer and bigserial = bigint, so I am confused why I see a sequence with a max val of 9223372036854775807 instead of 2147483647, when I create a table with a PK that is serial.
As stated in the PostgreSQL 9.4 docs for Data Type SERIAL a sequence is implicitly created using CREATE SEQUENCE tablename_colname_seq without any additional parameters.
The documentation for CREATE SEQUENCE says:
The optional clause MAXVALUE maxvalue determines the maximum value for the sequence. If this clause is not supplied or NO MAXVALUE is specified, then default values will be used. The defaults are 2^63-1 and -1 for ascending and descending sequences, respectively.
So it is documented behaviour that the sequence is created with the max value you are seing.
The sequence and the column are two separate things. A sequence could return an integer larger than an int4 column could store. When you specify SERIAL or BIGSERIAL, PostgreSQL roughly translates that into:
create an int4 or int8 column
create a sequence
make the sequence owned by the column
make the column default value the next value from the sequence
SERIAL is a convenience, but there is not an actual column type SERIAL.

PostgreSQL : converting existing double precision column to integer data type

I have a column in PostgreSQL that contains numbers. The column's data type is double precision, and the numbers have a lot of decimal digits. I don't need that level of accuracy. Integers would be enough.
How do I redefine the column as having an integer datatype, while rounding the current existing data to obtain integers ?
Just alter the table, Postgres will automatically cast the double values to integer by rounding the appropriately:
ALTER TABLE foo ALTER COLUMN some_column TYPE integer;
This will essentially do the same as:
ALTER TABLE foo ALTER COLUMN some_data TYPE integer
USING round(some_data)::integer;
SQLFiddle: http://sqlfiddle.com/#!15/4ea3c/1

How to change column datatype from character to numeric in PostgreSQL 8.4

I am using following query:
ALTER TABLE presales ALTER COLUMN code TYPE numeric(10,0);
to change the datatype of a column from character(20) to numeric(10,0) but I am getting the error:
column "code" cannot be cast to type numeric
You can try using USING:
The optional USING clause specifies how to compute the new column value from the old; if omitted, the default conversion is the same as an assignment cast from old data type to new. A USING clause must be provided if there is no implicit or assignment cast from old to new type.
So this might work (depending on your data):
alter table presales alter column code type numeric(10,0) using code::numeric;
-- Or if you prefer standard casting...
alter table presales alter column code type numeric(10,0) using cast(code as numeric);
This will fail if you have anything in code that cannot be cast to numeric; if the USING fails, you'll have to clean up the non-numeric data by hand before changing the column type.
If your VARCHAR column contains empty strings (which are not the same as NULL for PostgreSQL as you might recall) you will have to use something in the line of the following to set a default:
ALTER TABLE presales ALTER COLUMN code TYPE NUMERIC(10,0)
USING COALESCE(NULLIF(code, '')::NUMERIC, 0);
(found with the help of this answer)
Step 1: Add new column with integer or numeric as per your requirement
Step 2: Populate data from varchar column to numeric column
Step 3: drop varchar column
Step 4: change new numeric column name as per old varchar column