Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change type of a column with numbers from varchar to int

We have two columns in a database which is currently of type varchar(16). Thing is, it contains numbers and always will contain numbers. We therefore want to change its type to integer. But the problem is that it of course already contains data.

Is there any way we can change the type of that column from varchar to int, and not lose all those numbers that are already in there? Hopefully some sort of sql we can just run, without having to create temporary columns and create a C# program or something to do the conversion and so forth... I imagine it could be pretty easy if SQL Server have some function for converting strings to numbers, but I am very unstable on SQL. Pretty much only work with C# and access the database through LINQ to SQL.

Note: Yes, making the column a varchar in the first place was not a very good idea, but that is unfortunately the way they did it.

like image 976
Svish Avatar asked Feb 23 '09 13:02

Svish


People also ask

Can you convert varchar to int in SQL?

SQL Server's CAST() and CONVERT() methods can be used to convert VARCHAR to INT.

How do I convert varchar to numeric?

To convert a varchar type to a numeric type, change the target type as numeric or BIGNUMERIC as shown in the example below: SELECT CAST('344' AS NUMERIC) AS NUMERIC; SELECT CAST('344' AS BIGNUMERIC) AS big_numeric; The queries above should return the specified value converted to numeric and big numeric.


4 Answers

The only reliable way to do this will be using a temporary table, but it will not be much SQL:

select * into #tmp from bad_table
truncate table bad_table
alter bad_table alter column silly_column int
insert bad_table
select cast(silly_column as int), other_columns
from #tmp
drop table #tmp
like image 83
cjk Avatar answered Oct 11 '22 05:10

cjk


The easiest way to do this is:

alter table myTable alter column vColumn int;

This will work as long as

  1. all of the data will fit inside an int
  2. all of the data can be converted to int (i.e. a value of "car" will fail)
  3. there are no indexes that include vColumn. If there are indexes, you will need to include a drop and create for them to get back to where you were.
like image 41
jmoreno Avatar answered Oct 11 '22 05:10

jmoreno


Just change the datatype in SQL Server Management Studio.

(You may need to go to menu ToolsOptionsDesigners, and disable the option that prevents saving changes that re-create the table.)

like image 7
ctrlalt3nd Avatar answered Oct 11 '22 04:10

ctrlalt3nd


I totally appreciate the previous answers, but also thought a more complete answer would be helpful to other searchers...

There are a couple caveats that would be helpful if you making the changes on a production type table.

  1. If you have an identity column defined on the table you will have to set IDENTITY_INSERT on and off around the re-insert of data. You will also have to use an explicit column list.
  2. If you want to be sure of not killing data in the database, use TRANSACTIONS around the truncate/alter/reinsert process
  3. If you have a lot of data, then trying to just make the change in SQ Server Management Studio could fail with a timeout and you could lose data.

To expand the answer that @cjk gave, look at the following:

Note: 'tuc' is just a placeholder in this script for the real tablename

begin try 
  begin transaction

  print 'Selecting Data...'
  select * into #tmp_tuc from tuc

  print 'Truncating Table...'
  truncate table tuc

  alter table tuc alter column {someColumnName} {someDataType} [not null]
  ... Repeat above until done

  print 'Reinserting data...'
  set identity_insert tuc on
  insert tuc (
    <Explicit column list (all columns in table)>
  )
  select  
    <Explicit column list (all columns in table - same order as above)>
  from #tmp_tuc
  set identity_insert tuc off

  drop table #tmp_tuc
  commit
  print 'Successful!'
end try
begin catch
  print 'Error - Rollback'
  if @@trancount > 0
    rollback

  declare @ErrMsg nvarchar(4000), @ErrSeverity int
  select @ErrMsg = ERROR_MESSAGE(), @ErrSeverity = ERROR_SEVERITY()

  set identity_insert tuc off

  RAISERROR(@ErrMsg, @ErrSeverity, 1)
end catch
like image 2
scott-pascoe Avatar answered Oct 11 '22 05:10

scott-pascoe