web-dev-qa-db-fra.com

Changer le type d'une colonne avec des nombres de varchar à int

Nous avons deux colonnes dans une base de données qui est actuellement de type varchar (16). La chose est, il contient des nombres et contiendra toujours des nombres. Nous voulons donc changer son type en entier. Mais le problème est qu'il contient bien sûr déjà des données.

Existe-t-il un moyen de changer le type de cette colonne de varchar en int, et de ne pas perdre tous les numéros qui s'y trouvent déjà? J'espère qu'une sorte de sql que nous pouvons simplement exécuter, sans avoir à créer des colonnes temporaires et créer un programme C # ou quelque chose pour faire la conversion et ainsi de suite ... J'imagine que cela pourrait être assez facile si SQL Server a une fonction pour convertir des chaînes en chiffres, mais je suis très instable sur SQL. À peu près, ne travaillez qu'avec C # et accédez à la base de données via LINQ to SQL.

Note: Oui, faire de la colonne un varchar en premier lieu n'était pas une très bonne idée, mais c'est malheureusement comme ça qu'ils l'ont fait.

32
Svish

La seule façon fiable de le faire sera d'utiliser une table temporaire, mais ce ne sera pas beaucoup de 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
38
cjk

La façon la plus simple de procéder est:

alter table myTable alter column vColumn int;

Cela fonctionnera tant que

  1. toutes les données rentreront dans un int
  2. toutes les données peuvent être converties en int (c'est-à-dire qu'une valeur de "car" échouera)
  3. aucun index n'inclut vColumn. S'il y a des index, vous devrez inclure une goutte et créer pour qu'ils reviennent où vous étiez.
22
jmoreno

Modifiez simplement le type de données dans SQL Server Management Studio.

(Vous devrez peut-être aller dans le menu OutilsOptionsDesigners, et désactiver l'option qui empêche d'enregistrer les modifications qui recréent la table. )

7
ctrlalt3nd

J'apprécie totalement les réponses précédentes, mais j'ai également pensé qu'une réponse plus complète serait utile aux autres chercheurs ...

Il y a quelques mises en garde qui seraient utiles si vous apportez les modifications sur une table de type de production.

  1. Si vous avez une colonne identité définie sur la table, vous devrez définir IDENTITY_INSERT on et off autour de la réinsertion des données. Vous devrez également utiliser une liste de colonnes explicite.
  2. Si vous voulez être sûr de ne pas tuer les données dans la base de données, utilisez TRANSACTIONS autour du processus tronquer/modifier/réinsérer
  3. Si vous avez beaucoup de données, essayer de simplement effectuer la modification dans SQ Server Management Studio peut échouer avec un délai d'attente et vous pouvez perdre des données.

Pour développer la réponse donnée par @cjk, regardez ce qui suit:

Remarque: 'tuc' est juste un espace réservé dans ce script pour le vrai nom de table

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
1
scott-pascoe