Converting varchar to int in psql - sql

so I am trying to convert a varchar to an int. I started without the numeric type and I got an error probably because of the . in the varchar. I searched online and found that I should add the numeric type. Now I have another error which is probably because of the , which is used as the thousands separator. Any suggestions?
I would like to use the alter table command if possible not cast or anything else because we have not learned it yet and it's for a school assignment. I have also added a screenshot of the query.
ALTER TABLE table_name
ALTER COLUMN column_name TYPE type USING column_name::type::type,
ALTER COLUMN column_name TYPE type USING column_name::type::type;

You can use a number of ways to convert your text value to integer (assuming the number in text field is actually an integer). For example:
REPLACE(price, ',', '')::numeric::int
TO_NUMBER(price, translate(price, '1234567890', '9999999999'))::int
Your alter table statement should look like this:
ALTER TABLE calendar
ALTER COLUMN price TYPE integer USING REPLACE(price , ',', '')::numeric::integer,
ALTER COLUMN adjusted_price TYPE integer USING REPLACE(adjusted_price, ',', '')::numeric::integer;
I've chosen the shorter way to cast, but TO_NUMBER case would work as well.

Use to_number, that can understand group separators:
ALTER TABLE calendar
ALTER price TYPE integer
USING to_number(price, '999,999,999,999.99')::integer,
ALTER adjusted_price TYPE integer
USING to_number(adjusted_price, '999,999,999,999.99')::integer;

My example/test script.
-- █ Droping and creating the table for test purposes. Don't do this with table with production data.
DROP TABLE IF EXISTS calendar;
CREATE TABLE calendar
(
id bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY ( INCREMENT 1 START 100 MINVALUE 1 MAXVALUE 9223372036854775807 CACHE 1 ),
price character varying(10) COLLATE pg_catalog."default" NOT NULL,
adjusted_price character varying(10) COLLATE pg_catalog."default" NOT NULL,
CONSTRAINT pk_calendar_id PRIMARY KEY (id)
);
-- █ For test purposes, creating example data if table exists.
DO $$ -- DO executes an anonymous code block
BEGIN
IF EXISTS(SELECT * FROM information_schema.tables WHERE table_schema = 'public' AND table_name = 'calendar') THEN
INSERT INTO calendar (price, adjusted_price) VALUES('8,000.00', '8,001.00');
INSERT INTO calendar (price, adjusted_price) VALUES('7,000.00', '7,355.00');
END IF;
END;
$$;
-- █ Alter table columns from varchar to int.
ALTER TABLE calendar
ALTER COLUMN price TYPE int USING SPLIT_PART(REPLACE(price, ',', ''), '.', 1)::int,
ALTER COLUMN adjusted_price TYPE int USING SPLIT_PART(REPLACE(adjusted_price, ',', ''), '.', 1)::int;
-- REPLACE(source, old_text, new_text ) comma is replaced by empty string '8,000.00' -> '8000.00'
-- SPLIT_PART(string, delimiter, position) '8000.00' is splitted in 2 parts ['8000', '00'] we need the part 1 ->'8000'
-- ::int using cast operator ::, convert from varchar to int.
-- █ Select all columns with new types.
select * from calendar;
Example data
id price adjusted_price
100 "8,000.00" "8,001.00"
101 "7,000.00" "7,355.00"
After alter the table
id price adjusted_price
100 8000 8001
101 7000 7355
References
PostgreSql SPLIT_PART
PostgreSql REPLACE
PostgreSql CAST
PostgreSql DO
Check if table exists

Related

SQL CREATE FUNCTION generates 'no such function' error

I am trying to generate a column which is not stored in the database. The column obtains its value from a function. The problem is there is an error of 'no such function:'
What should I do to get the value from this function and assign it to the column?
My SQL script so far:
CREATE FUNCTION GETAVERAGE (#locationID AS INTEGER)
RETURNS NUMERIC
AS
BEGIN
DECLARE #avg AS NUMERIC
SET #avg = SELECT AVG(value) FROM properties WHERE location_id = #locationID
END;
CREATE TABLE IF NOT EXISTS properties
(
property_id INTEGER PRIMARY KEY,
location_id INTEGER,
address VARCHAR (100),
value NUMERIC,
average_prop_value NUMERIC GENERATED ALWAYS AS (GETAVERAGE(location_id)) VIRTUAL,
FOREIGN KEY (location_id) REFERENCES locations (location_id)
);
CREATE TABLE IF NOT EXISTS locations
(
location_id INTEGER PRIMARY KEY,
name VARCHAR (50) UNIQUE
);
Not sure which database you are using. If you add a specific tag (and version detail) to the question, that could help. It could be MySQL. Here's standard SQL that would work with most databases (of a recent version):
SELECT t.*
, AVG(value) OVER (PARTITION BY location_id) AS avg_value
FROM properties t
;
Use this in a VIEW, if you wish.

How to set datatype of SQL column in Alias?

If I have a query such as:
select name as first_name
from my_table
How can I set the datatype of that column in Postgresql to be character varying or anything in future - is there a way such as:
select name as first_name character varying
from my_table
I assume there is a way to set a datatype of a column after the aliasing - unsure how in postgresql
I am using postgresql and pgadmin4
Use cast to change the data type:
select cast(name as character varying(100)) as first_name
from my_table
But I'd consider altering the table column instead, to be varchar(100):
alter table my_table alter column name type character varying(100)
Use new datatype for column after TYPE keyword in PostgreSQL
ALTER TABLE table_name ALTER COLUMN column_name TYPE new_datatype;
Let's take an example -
CREATE TABLE Test (
emp_id serial PRIMARY KEY,
emp_name TEXT NOT NULL,
);
INSERT INTO Test (emp_id, emp_name) VALUES ('abc00012','Shubham');
ALTER TABLE Test ALTER COLUMN emp_name TYPE VARCHAR;
In Postgres, I would use the short-hand syntax for type conversion :::
select name::varchar as first_name
Of course, the right thing to do is to fix the type in the table, but that is already covered by other answers.
To easily cast your result to any datatype use :: datatype as in below:
select name as first_name ::varchar from my_table

generate sequence in sql server 2014

I am trying to generate a sequence varchar text type, but I do not want to have to create another column to get the id to format it and insert it I want to generate it in the same column, help
create table tbl (
Id int identity not null,
CusId as 'CUS' + format(Id, '00000'),
-- ...
)
You can use sequence object that appeared in SQL Server 2012 + default value like this:
create sequence dbo.ids as int
minvalue 1;
create table dbo.tbl (
CusId varchar(100) default 'CUS' + format(NEXT VALUE FOR dbo.ids, '00000'));
insert into dbo.tbl (CusId) default values;
insert into dbo.tbl (CusId) default values;
insert into dbo.tbl (CusId) default values;
select *
from dbo.tbl;
-----
--CusId
--CUS00001
--CUS00002
--CUS00003
Believe the only viable solution is using 2 columns as you mentioned, and discussed here:
Autoincrement of primary key column with varchar datatype in it
Have not seen it achieved in a single column on its own.

H2 equivalent of Postgres `SERIAL` or `BIGSERIAL` column?

In Postgres, defining a column with SERIAL/BIGSERIAL has a triple effect as discussed here:
Define a int/bigint column.
Create a sequence object to generate auto-incrementing numbers.
Set the default of the column to call nextval() on the sequence.
Is there a similar shortcut command in H2 to get this related set of behavior?
If not, what would the long version of the SQL be?
Where does the sequence live? How can you adjust its value or reset it?
If you create a column as auto_increment (or identity) H2 creates a sequence in the background. The name of that sequence can be obtained by looking at information_schema.columns:
create table foo
(
id integer auto_increment,
other_column varchar(20)
);
If you then run:
select column_name, column_default
from information_schema.columns
where table_name = 'FOO'
and table_schema = 'PUBLIC';
You'll get something like this:
COLUMN_NAME | COLUMN_DEFAULT
-------------+-----------------------------------------------------------------------------
ID | (NEXT VALUE FOR PUBLIC.SYSTEM_SEQUENCE_C1C36118_ED1C_44D6_B573_6C00C5923EAC)
OTHER_COLUMN |
You can alter that sequence without problems:
alter sequence SYSTEM_SEQUENCE_C1C36118_ED1C_44D6_B573_6C00C5923EAC
restart with 42;
This is essentially identical to Postgres' serial data type
If not, what would the long version of the SQL be?
create sequence foo_id_seq;
create table foo
(
id integer default foo_id_seq.nextval,
other_column varchar(20)
);
The big difference between this and a Postgres serial is that H2 does not know that the sequence "belongs" to the column. You need to drop it manually when the table is dropped.
foo_id_seq.nextval will actually be converted to (NEXT VALUE FOR PUBLIC.FOO_ID_SEQ) when the table is created (and it will be stored like that in information_schema.columns.

SQL Server Database unique number generation on any record insertion

I have like 11 columns in my database table and i am inserting data in 10 of them. i want to have a unique number like "1101 and so on" in the 11th column.
Any idea what should i do?? Thanks in advance.
SQL Server 2012 and above you can generate Sequence
Create SEQUENCE RandomSeq
start with 1001
increment by 1
Go
Insert into YourTable(Id,col1...)
Select NEXT VALUE FOR RandomSeq,col1....
or else you can use Identity
Identity(seed,increment)
You can start the seed from 1101 and increment the sequence by 1
Create table YourTable
(
id INT IDENTITY(1101,1),
Col varchar(10)
)
If you want to have that unique number in a different field then you can manipulate that field with primary key and insert that value.
If you want in primary key value, then open the table in design mode, go to 'Identity specification', set 'identity increment' and 'identity seed' as you want.
Alternatively you can use table script like,
CREATE TABLE Persons
(
ID int IDENTITY(12,1) PRIMARY KEY,
FName varchar(255) NOT NULL,
)
here the primary key will start seeding from 12 and seed value will be 1.
If you have your table definition already in place you can alter the column and add Computed column marked as persisted as:
ALTER TABLE tablename drop column column11;
ALTER TABLE tablename add column11 as '11'
+right('000000'+cast(ID as varchar(10)), 2) PERSISTED ;
--You can change the right operator value from 2 to any as per the requirements.
--Also replace ID with the identity column in your table.
create table inc
(
id int identity(1100,1),
somec char
)