Adicione uma coluna a uma tabela com um valor padrão igual ao valor de uma coluna existente

88

Como adicionar uma coluna a uma tabela do SQL Server com um valor padrão igual ao valor de uma coluna existente?

Tentei esta instrução T-SQL:

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

mas está dando um erro:

O nome "oldcolumn" não é permitido neste contexto. As expressões válidas são constantes, expressões constantes e (em alguns contextos) variáveis. Nomes de colunas não são permitidos.

fazes
fonte
6
O valor padrão pode ser uma constante, não outra coluna. Isso precisa de um gatilho, eu acho.
ypercubeᵀᴹ
1
ok, como posso fazer isso, sou novo no sql.
dodos
1
Esse sempre será o padrão ou é apenas para preencher a coluna para as linhas existentes enquanto a nova coluna está sendo adicionada à tabela?
Damien_The_Unbeliever
1
@Damien_The_Unbeliever apenas para preencher a coluna para linhas existentes.
dodos
2
Você tem que fazer isso separadamente UPDATE, então, eu temo.
Damien_The_Unbeliever

Respostas:

70

Experimente isto:

ALTER TABLE tablename ADD newcolumn type NOT NULL DEFAULT (0)
Go
Update tablename SET newcolumn = oldcolumn Where newcolumn = 0
Go
Kapil Khandelwal
fonte
5
..sim, mas isso funcionará apenas para as linhas existentes. Não definirá o valor de [nova coluna] quando novas linhas forem inseridas. Você precisa do gatilho APÓS INSERIR etc.
Milão
12
Isso adiciona uma restrição padrão possivelmente não intencional na mesa
Romain Vergnory
1
@RomainVergnory Concordo, é melhor ir sem uma restrição para NOT NULL no início, em seguida, preencher os valores com a coluna existente e depois adicionar NOT NULL novamente
adkl
15

Não gosto muito deles, mas aqui está como você pode fazer isso com um AFTER INSERTgatilho:

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

A AFTER INSERTabordagem do gatilho envolve sobrecarga devido à UPDATEinstrução extra . Eu sugiro usar um INSTEAD OF INSERTgatilho, como segue:

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

Porém, isso não funciona se oldcolumnfor uma coluna de identidade automática.

Herman Kan
fonte
2
INSTEAD OFgatilhos também não funcionam ao usar tabelas temporais:SYSTEM_VERSIONING = ON
CalvinDale
3

Para estender a resposta de Kapil e evitar a restrição padrão indesejada, tente o seguinte:

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

Substitua -9999 por 'noData' se seu tipo for varchar, nvarchar, datetime, ... ou por qualquer dado compatível para outros tipos: o valor específico não importa, ele será apagado pela 2ª instrução.

Frédéric Chauvière
fonte
1

Você pode usar a coluna computada para inserir uma nova coluna em uma tabela com base em um valor de coluna existente

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

OU, se você quiser fazer algumas alterações no valor com base no valor da coluna existente, use

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

Para o meu caso, quero adicionar uma nova coluna exclusiva não nula chamada CODE, mas não sei sobre o valor no momento da criação. Eu defino o valor padrão para ele obtendo um valor padrão de NewID () e atualizando mais 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
fonte
-3

Acho que vai funcionar se você usar Set Identity_Insert <TableName> OFFe após a instrução insert que você escreveu basta usar Set Identity_Insert <TableName> ON.

user7040891
fonte