Can't convert postgresql table column from type varchar to int - sql

I have a database table of that I have used to store the data returned from a web spider. I have a column that contains ticket prices for different events all in the varchar type (as the scrapy spider has to scrape the data in unicode). I'm trying to return the min price of the column and since the min() function only works for data of type INT, I tried to convert the column to integers using a solution from this SO post:
ALTER TABLE vs_tickets ALTER COLUMN ticketprice TYPE integer USING (ticketprice::integer);
but I got the error: ERROR: invalid input syntax for integer:
I also tried: change_column :vs_tickets, :ticketprice, 'integer USING CAST(ticketprice AS integer)' but that didn't work either.
What is the proper way to convert the column to type INT?
Edit:

You have decimal places in the string, so a simple cast is not going to work. You can do a double conversion:
cast(cast(ticketprice as decimal(10, 2)) as int)
or:
(ticketprice::decimal(10, 2))::int
(The parens are not strictly necessary.)
EDIT:
Or, as Erwin points out, just use numeric:
(ticketprice::numeric)::int
Postgres is much smarter about numeric than most other databases . . . after all, it supports numbers that are egregiously large ;)
The final query is:
ALTER TABLE vs_tickets
ALTER COLUMN ticketprice TYPE integer USING (ticketprice::numeric::integer);

I'm going to bet on your column have wrong characters.
Also you may want use float or numeric because you will lose decimals if convert to integers.
You need create a function to check if a text is numeric like this isnumeric-with-postgresql
Then check each row like this
select ticketprice
from vs_tickets
where ISNUMERIC(ticketprice) = false;
As your comment you also should try
SELECT ticketprice::float

You will be best off adding an INT column, moving your data with a cast and then removing the old varchar column.
ALTER TABLE vs_tickets ADD COLUMN ticketprice_int TYPE int;
GO
update vs_tickets SET ticketprice_int = cast(ticketprice as int);
// if you fail to cast the varchar to int you can use Gordon's method
// update vs_tickets SET ticketprice_int = cast(cast(ticketprice as decimal(10, 2)) as int);
GO
ALTER TABLE vs_tickets DROP COLUMN ticketprice;
GO
ALTER TABLE vs_tickets RENAME COLUMN ticketprice_int to ticketprice;
GO
With this at minimum you will be able to tell if and where a cast/convert fails and be able to check and recheck at each step before you can't turn back.

Related

Does altering column type corrupt the column's existing data?

I am trying to change a column's datatype. The column of type VARCHAR has thousands of GUID values like look those shown below:
b1f4ff32-48d4-494e-a32c-044014cea9
bc5a1158-b310-49ff-a1f3-09d4f8707f69
4b7ebc9d-9fa1-42d9-811e-0b7b4b7297a
fc7ba848-98ea-4bc6-add7-11f0ee9c6917a21
485741ff-2ab2-4705-91b3-136389948b7c
I need to convert the column type to unqiqueidentifier using the script below. Can I do that safely without corrupting the column data?
alter table MyTable
alter column guidColumn uniqueidentifier not null
If you change the data type SQL Server will first check if all the values in the columns can be implicitly converted to the new data type; if they cannot then the ALTER will fail. If they can, then they will be implicitly converted and the ALTER will be successful (assuming no dependencies of course).
For a uniqueidentifier then either it's a valid value or it's not, so either the data will all convert or the ALTER won't take place. For something like a date and time data type, however, you could very easily end up with incorrect data if the data is stored in an ambiguous format like dd/MM/yyyy. This could mean a value like '12/05/2022' ends up being stored as the date value 2022-12-05 rather than 2022-05-12. For such scenarios you would therefore want to UPDATE the data to an unambiguous format first, and then ALTER the data type of the column.
The uniqueidentifier type is considered a character type for the purposes of conversion from a character expression, and therefore is subject to the truncation rules for converting to a character type.
Also there are limitations, uniqueidentifier type is limited to 36 char
So if you decide to truncate the table like in this example:
DECLARE #ID NVARCHAR(max) = N'0E984725-C51C-4BF4-9960-E1C80E27ABA0wrong';
SELECT #ID, CONVERT(uniqueidentifier, #ID) AS TruncatedValue;
This will be the result:
String
Truncated Value
0E984725-C51C-4BF4-9960-E1C80E27ABA0wrong
0E984725-C51C-4BF4-9960-E1C80E27ABA0
So, if your string is more or less than 36 it will not truncate correctly.
For more information check Microsoft documentation:
https://learn.microsoft.com/en-us/sql/t-sql/data-types/uniqueidentifier-transact-sql?view=sql-server-ver15

Convert ntext to numeric

One of my column is defined as ntext datatype which is no longer supported by many streams. I'm trying my best to convert that column to numeric or int and every attempt is reaching anywhere.
reg_no #my ntext field | name | country | etc |
I tried to alter the col using the command we all use, but failed
alter table tabl1
alter column [reg_no] numeric(38,0)
Error:
Error converting data type nvarchar to numeric
Any suggestions on fixing this or has anyone come across this in the past, if yes how did you get over it
You should be able to do this in two steps:
alter table tabl1 alter column [reg_no] nvarchar(max);
alter table tabl1 alter column [reg_no] numeric(38,0);
ntext is deprecated and conversion to numeric is not supported, but converting to nvarchar() is supported.
This assumes that the values are compatible with numeric. Otherwise you will get a type conversion error. If this happens, you can get the offending values by using:
select *
from t
where try_convert(numeric(38, 0), try_convert(nvarchar(max), x)) is null
Try,
select convert(int,convcert(varchar(40), reg_no)) as newfieldname from tabl1

Convert column from varchar to datetime and update it in the table

I have a question related to the conversion of varchar to datetime.
This topic was covered already in the thread
SQL Server Convert Varchar to Datetime
but I would like to advance it bit further.
I have performed BULK INSERT into predefined tables where VARCHAR(255)
is the destination. I have a table dbo.USR_02_ALL_RAW and the field GLTGB which
holds strings in the following format: 07/16/2016.
I can convert it as a single string by the following code:
DECLARE #Date varchar(255)
set #Date= '07/16/2016'
SELECT CONVERT(datetime,RIGHT(#Date,4)+LEFT(#Date,2)+SUBSTRING(#Date,4,2))
and it gives me a result:
2016-07-16 00:00:00.000
However I would like to pass to the code the whole field GLTGB from the table
dbo.USR_02_ALL_RAW, convert it from VARCHAR into DATETIME and update the field GLTGB with these results.(converting the whole field from varchar to datetime)
Thank you!
First clear this, you want to Bulk insert or Bulk update. Since you already have a column GLTGB. If you want to update the value only.
update tab set GLTGB =
CONVERT(datetime,RIGHT(GLTGB,4)+LEFT(GLTGB,2)+SUBSTRING(GLTGB,4,2))
Or
If you want to update the field from varchar to datetime. Then process is little bit lengthy.
Alter table tab add newcol datetime --- Add new datetime type column
update tab set newcol =
CONVERT(datetime,RIGHT(GLTGB,4)+LEFT(GLTGB,2)+SUBSTRING(GLTGB,4,2)) --- update value in new column
Alter table tab drop column GLTGB --- drop GLGTB column
Alter table tab add GLGTB datetime --- add GLGTB column as datetime type
update tab set GLGTB = newcol --- update value from GLGTB from newcol
Alter table tab drop column newcol ---- remove unnecessary newcol
If you convert a value to datetime, then update the same database column it came from with the value then, since that column is still varchar, SQL will have to convert the value back to varchar again in order to store it. So you can't achieve anything useful with that kind of simple approach.
f you want to actually change the data type of the column, and also convert all the values, then I think you need to go through the following process:
1) Create a new varchar column in your table (which will be temporary)
2) copy all the data values from the GLTGB column into the new column (using an UPDATE statement)
3) Drop the GLTGB column
4) Re-create it with the same name but with datetime type
5) Use an UPDATE statement to re-populate the new GLTGB column from your temporary column
6) Finally, drop the temporary column
There may be a simpler way but that seems like the obvious process.
You can use the following code for updating but before that, you need to change the data type of your field to DateTime
update dbo.USR_02_ALL_RAW
set GLTGB=cast(CONVERT(datetime,RIGHT(#Date,4)+LEFT(#Date,2)+SUBSTRING(#Date,4,2)) as datetime)

Error converting data type nvarchar to float - nvarchar to float to int

I don't have that much experience with writing SQL queries and I have hit upon a problem. I have read in a table of data into a temporary table (#Temp_Results) and need to change the format of various columns before moving the data to the end table.
What Im trying to do below is take a column (Oil2) that is an nvarchar and convert it to a tinyint and put the result into a new column (Oil4) then drop Oil2 - I realise I will loose decimal places but thats not a problem. The CASE statement is designed to capture anything that is not a number, seeing as the original datatype is nvarchar there could be anything in there and I'm only interested in the numbers.
However when I run the code I get 'Error converting data type nvarchar to float' pointing towards the 'UPDATE' line of code and I cant figure out how to get round it.
Can any of you guys spot my rookie mistake?
ALTER TABLE tempdb..#Temp_Results /*Add new column with datatype of tinyint*/
ADD Oil4 tinyint
GO
UPDATE tempdb..#Temp_Results
SET tempdb..#Temp_Results.Oil4 = CASE
WHEN ISNUMERIC(tempdb..#Temp_Results.Oil2)=1
THEN CAST(ROUND(CAST(tempdb..#Temp_H_Results.Oil2 as float), 0) AS tinyint)
ELSE NULL
END
ALTER TABLE tempdb..#Temp_H_Results /*Drop redundant column of data in wrong (nvarchar) format*/
DROP COLUMN Oil2
Go
Try casting to Decimal in stead of float
CONVERT(varchar(28), cast(tempdb..#Temp_H_Results.Oil2 as decimal(28,0)))

Datetime colum to float type conversion is getting issue in sql server

I'd like alter a column type from Datetime to float. Hence, I executed the below query but it was getting a issue
alter table dbo.purchasedate
alter column supp_dt float null
Error :: Implicit conversion from data type datetime to float is not allowed. Use the CONVERT function to run this query.
Without knowing your desired output, you could just: Add Float column, populate, drop date column.
To my knowledge you cannot add a CONVERT to an ALTER statement, anyone know otherwise?