Agregue una columna a una tabla, si aún no existe

188

Quiero escribir una consulta para MS SQL Server que agrega una columna en una tabla. Pero no quiero que se muestre ningún error cuando ejecuto / ejecuto la siguiente consulta.

Estoy usando este tipo de consulta para agregar una tabla ...

IF EXISTS (
       SELECT *
       FROM   sys.objects
       WHERE  OBJECT_ID = OBJECT_ID(N'[dbo].[Person]')
              AND TYPE IN (N'U')
   )

Pero no sé cómo escribir esta consulta para una columna.

Tavousi
fuente
Debería usar en sys.tableslugar del "genérico" sys.objects- entonces no tiene que especificar el tipo explícitamente (es obvio por el sys.tablesya ...)
marc_s
La alternativa COL_LENGTH solo funciona desde SQL-Server 2008, pero funciona.
Paul-Henri

Respuestas:

219

Puede usar una construcción similar usando la sys.columnstabla io sys.objects.

IF NOT EXISTS (
  SELECT * 
  FROM   sys.columns 
  WHERE  object_id = OBJECT_ID(N'[dbo].[Person]') 
         AND name = 'ColumnName'
)
Lieven Keersmaekers
fuente
42
Tenga en cuenta que en este caso desea utilizar SI NO EXISTE en su código real.
Nat
2
Para una consulta optimizada, puede usar el top 1 con la instrucción select
Banketeshvar Narayan
11
@BanketeshvarNarayan esto es incorrecto. Los planes de ejecución para subconsultas en una EXISTScláusula son idénticos. Cosas como SELECT 1o SELECT TOP 1son innecesarias. La EXISTScláusula misma le dice al optimizador de consultas que solo realice las lecturas mínimas necesarias para evaluar el EXISTS... al menos en SQL Server. Otros motores de DB pueden tener un optimizador de consultas más o menos eficiente.
Kenneth Cochran
9
@BanketeshvarNarayan Si está optimizando sus ADD Columnconsultas ... ¡debe ejecutarlas con demasiada frecuencia!
Fenton
1
@ user391339 - He publicado una construcción similar a OP publicada pero sí, si desea tomar medidas si la columna no existe, la declaración sería SI NO EXISTE. Realmente no siento la necesidad de editar la respuesta para esto, pero siéntase libre de editarse si cree que es una mejora.
Lieven Keersmaekers
91
IF COL_LENGTH('table_name', 'column_name') IS NULL
BEGIN
    ALTER TABLE table_name
    ADD [column_name] INT
END
SPL
fuente
1
Intenté hacer esto pero devuelve un error que indica que la función COL_LENGTH no existe.
ThEpRoGrAmMiNgNoOb
3
Requiere SQL Server 2008+
Robert Brown
66
Pequeña adición: no se deben usar corchetes en el nombre de la columna, ya que COL_LENGTH('table_name', '[column_name]')siempre devuelve nulo en SQL Server 2016 ( COL_LENGTH('[table_name]', 'column_name') works as expected).
stop-cran
33

Otra alternativa Prefiero este enfoque porque es menos escrito pero los dos logran lo mismo.

IF COLUMNPROPERTY(OBJECT_ID('dbo.Person'), 'ColumnName', 'ColumnId') IS NULL
BEGIN
    ALTER TABLE Person 
    ADD ColumnName VARCHAR(MAX) NOT NULL
END

También noté que el tuyo está buscando dónde existe una tabla que obviamente es solo esto

 if COLUMNPROPERTY( OBJECT_ID('dbo.Person'),'ColumnName','ColumnId') is not null
JStead
fuente
2
Me gusta. Creo que la mejor parte de publicar aquí es encontrar gemas como esta.
JStead
2
¿Qué es 'ColumnId'?
Marius Stănescu
'ColumnId' es el nombre de la propiedad de columna con la que está comprobando. Probablemente podría haber utilizado cualquier nombre de propiedad que exista en una columna, como nombre, etc.
Jacques Bosch
5

Aquí hay otra variación que funcionó para mí.

IF NOT EXISTS (SELECT 1
        FROM INFORMATION_SCHEMA.COLUMNS
        WHERE upper(TABLE_NAME) = 'TABLENAME'
        AND upper(COLUMN_NAME) = 'COLUMNNAME')
BEGIN
    ALTER TABLE [dbo].[Person] ADD Column
END
GO

EDITAR: INFORMATION_SCHEMAtenga en cuenta que las vistas no siempre se pueden actualizar, use SYS.COLUMNSen su lugar:

IF NOT EXISTS (SELECT 1 FROM SYS.COLUMNS....

Adil H. Raza
fuente
0
IF NOT EXISTS (SELECT * FROM syscolumns
  WHERE ID=OBJECT_ID('[db].[Employee]') AND NAME='EmpName')
  ALTER TABLE [db].[Employee]
  ADD [EmpName] VARCHAR(10)
GO

Espero que esto ayude. Más información

ShaileshDev
fuente
Esto funcionó para mí en SqlServer 2000 mientras que la respuesta aceptada no. Las vistas sys. * Parecen haberse agregado en algún lugar alrededor de SqlServer 2005, cf. docs.microsoft.com/en-us/sql/relational-databases/…
ZeRemz
0

Al buscar una columna en otra base de datos, simplemente puede incluir el nombre de la base de datos:

IF NOT EXISTS (
  SELECT * 
  FROM   DatabaseName.sys.columns 
  WHERE  object_id = OBJECT_ID(N'[DatabaseName].[dbo].[TableName]') 
         AND name = 'ColumnName'
)
Ezra
fuente
-1
IF NOT EXISTS (SELECT 1  FROM SYS.COLUMNS WHERE  
OBJECT_ID = OBJECT_ID(N'[dbo].[Person]') AND name = 'DateOfBirth')
BEGIN
ALTER TABLE [dbo].[Person] ADD DateOfBirth DATETIME
END
Código Primero
fuente