Agregar una columna a una tabla con un valor predeterminado igual al valor de una columna existente

90

¿Cómo agregar una columna a una tabla de SQL Server con un valor predeterminado que es igual al valor de una columna existente?

Probé esta declaración T-SQL:

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

pero está dando un error:

El nombre "columna antigua" no está permitido en este contexto. Las expresiones válidas son constantes, expresiones constantes y (en algunos contextos) variables. No se permiten los nombres de columna.

dodos
fuente
6
El valor predeterminado puede ser una constante, no otra columna. Esto necesita un disparador, creo.
ypercubeᵀᴹ
1
ok, ¿cómo puedo hacer eso? Soy nuevo en sql.
Dodos
1
¿Siempre será el valor predeterminado o es solo para completar la columna de las filas existentes mientras se agrega la nueva columna a la tabla?
Damien_The_Unbeliever
1
@Damien_The_Unbeliever solo para completar la columna para las filas existentes.
Dodos
2
Tienes que hacerlo por separado UPDATE, entonces, me temo.
Damien_The_Unbeliever

Respuestas:

73

Prueba esto:

ALTER TABLE tablename ADD newcolumn type NOT NULL DEFAULT (0)
Go
Update tablename SET newcolumn = oldcolumn Where newcolumn = 0
Go
Kapil Khandelwal
fuente
5
..sí, pero esto funcionará solo para las filas existentes. No establecerá el valor de [nueva columna] cuando se inserten nuevas filas. Es necesario DESPUÉS DE INSERTAR gatillo etc
Milán
14
Esto agrega una restricción predeterminada posiblemente no intencionada en la mesa
Romain Vergnory
1
@RomainVergnory Estoy de acuerdo, es mejor ir sin una restricción a NOT NULL al principio, luego completar los valores con la columna existente y luego agregar un NOT NULL nuevamente
adkl
15

No me gustan mucho, pero así es como puedes hacer esto con un AFTER INSERTdisparador:

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ᵀᴹ
fuente
13

El AFTER INSERTenfoque de activación implica gastos generales debido a la UPDATEdeclaración adicional . Sugiero usar un INSTEAD OF INSERTdisparador, de la siguiente manera:

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

Sin embargo, esto no funciona si oldcolumnes una columna de identidad automática.

Herman Kan
fuente
2
INSTEAD OFlos disparadores tampoco funcionan cuando se usan tablas temporales:SYSTEM_VERSIONING = ON
CalvinDale
3

Para extender la respuesta de Kapil y evitar la restricción predeterminada no deseada, intente esto:

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

Reemplace -9999 por 'noData' si su tipo es varchar, nvarchar, datetime, ... o por cualquier dato compatible para otros tipos: el valor específico no importa, será borrado por la segunda instrucción.

Frédéric Chauvière
fuente
1

Puede usar la columna calculada para insertar una nueva columna en una tabla basada en un valor de columna existente

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

O, si desea realizar algunos cambios en el valor según el valor de la columna existente, utilice

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

Para mi caso, quiero agregar una nueva columna única no nula llamada CÓDIGO, pero no sé sobre el valor en el momento de la creación. Establezco el valor predeterminado obteniendo un valor predeterminado de NewID () y luego actualizo más tarde.

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
fuente
-3

Creo que funcionará si usa Set Identity_Insert <TableName> OFFy después de insertar la Declaración que escribió, simplemente use Set Identity_Insert <TableName> ON.

usuario7040891
fuente