2009-02-23 12 views
24

Abbiamo due colonne in un database che è attualmente di tipo varchar (16). Il fatto è che contiene numeri e sempre conterrà numeri. Pertanto, vogliamo cambiare il suo tipo in intero. Ma il problema è che ovviamente contiene già dei dati.Cambia il tipo di una colonna con i numeri da varchar a int

C'è un modo per modificare il tipo di quella colonna da varchar a int e non perdere tutti quei numeri che sono già presenti? Speriamo che una sorta di sql possiamo solo eseguire, senza dover creare colonne temporanee e creare un programma C# o qualcosa per fare la conversione e così via ... Immagino che potrebbe essere piuttosto semplice se SQL Server ha qualche funzione per convertire le stringhe in numeri, ma io sono molto instabile su SQL. Praticamente funziona solo con C# e accede al database tramite LINQ a SQL.

Nota: Sì, rendere la colonna un varchar in primo luogo non era un'idea molto buona, ma sfortunatamente è così che l'hanno fatto.

risposta

30

L'unico modo affidabile per fare questo sarà utilizzando una tabella temporanea, ma non sarà molto 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 
+0

# tmp è un nome casuale di una tabella tmp? – Svish

+1

Buona risposta: eseguirò questa prima opzione - seleziona cast (silly_column come int), other_columns da bad_table Per assicurarti che non ci siano problemi di conversione e che siano tutti di fatto inte. – brendan

+3

Di tutti i nomi che ho inventato, hai fatto un'osservazione sul # tmp? – cjk

8

basta cambiare il tipo di dati in studio gestione

(potrebbe essere necessario andare a Strumenti> Opzioni> Designer e disabilita l'opzione che impedisce di salvare le modifiche che ricreano la tabella)

+0

non perdere tutti i valori allora ?? – Svish

+0

No. Provalo su un tavolo di prova, se vuoi? – ctrlalt3nd

+0

L'ho appena fatto e ha funzionato perfettamente. Per prima cosa ho controllato se tutti i valori esistenti fossero numeri memorizzati nel tipo stringa e se potessi convertire tutti i varchars in tipo numerico. Dopo aver disabilitato tutti i riferimenti alla colonna (Indexes, Keys, Trigger, ...), ho proseguito e ho applicato la modifica in MSSMS. Ottimo! – Rynkadink

1

Apprezzo totalmente le risposte precedenti, ma ho anche pensato che una risposta più completa sarebbe stata utile ad altri utenti ...

Ci sono un paio di avvertimenti che potrebbero essere utili se si apportano le modifiche su una tabella dei tipi di produzione.

  1. Se si dispone di una colonnaidentità definita sul tavolo si dovrà impostare IDENTITY_INSERT dentro e fuori intorno al re-inserimento dei dati. Dovrai inoltre utilizzare un elenco di colonne esplicito.
  2. Se si vuole essere sicuri di non uccidere i dati nel database, utilizzare TRANSACTIONS tutto il troncamento/modificare/reinserire processo
  3. Se si dispone di un sacco di dati, poi cercando di fare solo il cambiamento di SQ Server Management Studio potrebbe fallire con un timeout e potresti perdere dati.

di ampliare la risposta che ha dato @cjk, guardare il seguente:

Nota: 'tuc' è solo un segnaposto in questo script per il vero tablename cominciano provare iniziare la transazione

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 
18

Il modo più semplice per farlo è:

alter table myTable alter column vColumn int; 

Ciò funzionerà come lon g come

  1. tutti i dati si adatta all'interno di un int
  2. tutti i dati possono essere convertiti in int (cioè il valore di "auto" non funzionerà)
  3. non ci sono indici che includono vColumn.Se ci sono indici, dovrai includere una goccia e creare per loro di tornare dove sei stato.
+2

@svish: volevo davvero che fosse "car" e non "char". – jmoreno

+0

Oh! Scusate. Capire cosa volevi dire ora, hehe :) – Svish

+0

questo ha funzionato a meraviglia. Stava fallendo quando si tentava attraverso lo studio di gestione – PowerMan2015

Problemi correlati