Ajouter une colonne à une table avec une valeur par défaut égale à la valeur d'une colonne existante

88

Comment ajouter une colonne à une table SQL Server avec une valeur par défaut égale à la valeur d'une colonne existante?

J'ai essayé cette instruction T-SQL:

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

mais cela donne une erreur:

Le nom "oldcolumn" n'est pas autorisé dans ce contexte. Les expressions valides sont des constantes, des expressions constantes et (dans certains contextes) des variables. Les noms de colonne ne sont pas autorisés.

dodos
la source
6
La valeur par défaut peut être une constante, pas une autre colonne. Cela a besoin d'un déclencheur, je pense.
ypercubeᵀᴹ
1
ok, comment puis-je faire cela, je suis nouveau sur sql.
dodos
1
Est-ce que ce sera toujours la valeur par défaut, ou est-ce juste pour remplir la colonne pour les lignes existantes pendant que la nouvelle colonne est ajoutée à la table?
Damien_The_Unbeliever
1
@Damien_The_Unbeliever juste pour remplir la colonne des lignes existantes.
dodos
2
Vous devez le faire séparément UPDATEalors, j'en ai bien peur.
Damien_The_Unbeliever

Réponses:

70

Essaye ça:

ALTER TABLE tablename ADD newcolumn type NOT NULL DEFAULT (0)
Go
Update tablename SET newcolumn = oldcolumn Where newcolumn = 0
Go
Kapil Khandelwal
la source
5
..oui, mais cela ne fonctionnera que pour les lignes existantes. Il ne définira pas la valeur [newcolumn] lorsque de nouvelles lignes sont insérées. Vous avez besoin du déclencheur APRÈS INSÉRER etc.
Milan
12
Cela ajoute une contrainte par défaut éventuellement involontaire sur la table
Romain Vergnory
1
@RomainVergnory Je suis d'accord, il vaut mieux aller sans restriction à NOT NULL au début, puis remplir les valeurs avec la colonne existante et ajouter plus tard un NOT NULL à nouveau
adkl
15

Je ne les aime pas beaucoup mais voici comment vous pouvez faire cela avec un AFTER INSERTdéclencheur:

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   
ypercubeᵀᴹ
la source
13

L' AFTER INSERTapproche de déclenchement implique une surcharge en raison de l' UPDATEinstruction supplémentaire . Je suggère d'utiliser un INSTEAD OF INSERTdéclencheur, comme suit:

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

Cela ne fonctionne pas si le oldcolumnest une colonne d'auto-identité.

Herman Kan
la source
2
INSTEAD OFles déclencheurs ne fonctionnent pas non plus lors de l'utilisation de tables temporelles:SYSTEM_VERSIONING = ON
CalvinDale
3

Pour étendre la réponse de Kapil et éviter la contrainte par défaut indésirable, essayez ceci:

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

Remplacez -9999 par 'noData' si votre type est varchar, nvarchar, datetime, ... ou par toute donnée compatible pour d'autres types: la valeur spécifique n'a pas d'importance, elle sera effacée par la 2ème instruction.

Frédéric Chauvière
la source
1

Vous pouvez utiliser une colonne calculée pour insérer une nouvelle colonne dans une table basée sur une valeur de colonne existante

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

OU, si vous souhaitez apporter des modifications à la valeur en fonction de la valeur de colonne existante, utilisez

ALTER TABLE dbo.TableName ADD NewColumn AS (OldColumn * 1.5) PERSISTED;
Vijai
la source
0

Pour mon cas, je souhaite ajouter une nouvelle colonne unique non nulle nommée CODE mais je ne connais pas la valeur au moment de la création. Je lui ai défini la valeur par défaut en obtenant une valeur par défaut de NewID (), puis je mets à jour plus tard.

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])
Trần Thanh Phong
la source
-3

Je pense que cela fonctionnera si vous utilisez Set Identity_Insert <TableName> OFFet après la déclaration d'insertion que vous avez écrite, utilisez simplement Set Identity_Insert <TableName> ON.

user7040891
la source