Aggiungi una colonna a una tabella con un valore predefinito uguale al valore di una colonna esistente


90

Come aggiungere una colonna a una tabella di SQL Server con un valore predefinito uguale al valore di una colonna esistente?

Ho provato questa istruzione T-SQL:

ALTER TABLE tablename 
ADD newcolumn type NOT NULL DEFAULT (oldcolumn) 

ma dà un errore:

Il nome "oldcolumn" non è consentito in questo contesto. Le espressioni valide sono costanti, espressioni costanti e (in alcuni contesti) variabili. I nomi delle colonne non sono consentiti.


6
Il valore predefinito può essere una costante, non un'altra colonna. Questo ha bisogno di un grilletto, credo.
ypercubeᵀᴹ

1
ok, come posso farlo, sono nuovo in sql.
fa il

1
Sarà sempre l'impostazione predefinita o è solo per popolare la colonna per le righe esistenti mentre la nuova colonna viene aggiunta alla tabella?
Damien_The_Unbeliever

1
@Damien_The_Unbeliever solo per aver popolato la colonna per le righe esistenti.
fa il

2
UPDATEAllora devi farlo separatamente , temo.
Damien_The_Unbeliever

Risposte:


73

Prova questo:

ALTER TABLE tablename ADD newcolumn type NOT NULL DEFAULT (0)
Go
Update tablename SET newcolumn = oldcolumn Where newcolumn = 0
Go

5
..sì, ma funzionerà solo per le righe esistenti. Non imposterà il valore [newcolumn] quando vengono inserite nuove righe. È necessario il trigger AFTER INSERT ecc.
Milano

14
Questo aggiunge un vincolo predefinito forse non intenzionale sul tavolo
Romain Vergnory

1
@RomainVergnory Sono d'accordo, è meglio andare senza restrizioni a NOT NULL all'inizio, quindi popolare i valori con la colonna esistente e successivamente aggiungere di nuovo un NOT NULL
adkl

15

Non mi piacciono molto, ma ecco come potresti farlo con un AFTER INSERTtrigger:

CREATE TRIGGER TableX_AfterInsert_TRG 
  ON TableX 
AFTER INSERT
AS
  UPDATE TableX AS t
  SET t.newcolumn = t.oldcolumn
  FROM Inserted AS i
  WHERE t.PK = i.PK ;              -- where PK is the PRIMARY KEY of the table   

13

L' AFTER INSERTapproccio trigger comporta un sovraccarico dovuto UPDATEall'istruzione extra . Suggerisco di utilizzare un INSTEAD OF INSERTtrigger, come segue:

CREATE TRIGGER tablename_on_insert ON tablename 
INSTEAD OF INSERT 
AS
INSERT INTO tablename (oldcolumn, newcolumn)
SELECT oldcolumn, ISNULL(newcolumn, oldcolumn)
FROM inserted

Tuttavia, questo non funziona se oldcolumnè una colonna di identità automatica.


2
INSTEAD OFanche i trigger non funzionano quando si utilizzano tabelle temporali:SYSTEM_VERSIONING = ON
CalvinDale

3

Per estendere la risposta di Kapil ed evitare il vincolo predefinito indesiderato, prova questo:

ALTER TABLE tablename ADD newcolumn type NOT NULL CONSTRAINT DF_TMP_TABLENAME_NEWCOLUMN DEFAULT -9999
Go
Update tablename SET newcolumn = oldcolumn
Go
ALTER TABLE tablename DROP CONSTRAINT DF_TMP_TABLENAME_NEWCOLUMN
Go

Sostituisci -9999 con "noData" se il tuo tipo è varchar, nvarchar, datetime, ... o con qualsiasi dato compatibile per altri tipi: il valore specifico non ha importanza, verrà cancellato dalla seconda istruzione.


1

È possibile utilizzare la colonna calcolata per inserire una nuova colonna in una tabella basata su un valore di colonna esistente

ALTER TABLE dbo.TableName ADD NewColumn AS (OldColumn) PERSISTED;

OPPURE, se desideri apportare alcune modifiche al valore in base al valore della colonna esistente, utilizza

ALTER TABLE dbo.TableName ADD NewColumn AS (OldColumn * 1.5) PERSISTED;

0

Per il mio caso, voglio aggiungere una nuova colonna univoca non nulla denominata CODICE ma non conosco il valore al momento della creazione. Ho impostato il valore predefinito per esso ottenendo un valore predefinito da NewID () quindi aggiornato in seguito.

ALTER TABLE [WIDGET] ADD [CODE] CHAR(5) NOT NULL DEFAULT(SUBSTRING(CONVERT(CHAR(36), NEWID()), 1, 5))

ALTER TABLE [dbo].[WIDGET] WITH CHECK ADD CONSTRAINT [UQ_WIDGET_CODE] UNIQUE ([CODE])

-3

Penso che funzionerà se usi Set Identity_Insert <TableName> OFFe dopo l'inserto Statement che hai scritto lo usi solo Set Identity_Insert <TableName> ON.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.