¿Cómo verificar si existe una columna en una tabla de SQL Server?

1853

Necesito agregar una columna específica si no existe. Tengo algo como lo siguiente, pero siempre devuelve falso:

IF EXISTS(SELECT *
          FROM   INFORMATION_SCHEMA.COLUMNS
          WHERE  TABLE_NAME = 'myTableName'
                 AND COLUMN_NAME = 'myColumnName') 

¿Cómo puedo verificar si existe una columna en una tabla de la base de datos de SQL Server?

Maciej
fuente
12
En realidad, no creo que haya nada malo con el código en la pregunta: funciona muy bien para mí en 2008 R2. (¿Tal vez lo estaba ejecutando en la base de datos incorrecta? ¿Quizás su base de datos distingue entre mayúsculas y minúsculas y no tenía el caso correcto en sus cadenas myTableName / myColumnName? Este tipo de consulta parece más flexible que la solución COL_LENGTH: soy capaz para ejecutarlo en una base de datos diferente e incluso en un enlace de base de datos con el prefijo adecuado "INFORMATION_SCHEMA". No pude ver cómo hacerlo con la función de metadatos COL_LENGTH.
mwardm
3
@mwardm: COL_LENGTH('AdventureWorks2012.HumanResources.Department ','ModifiedDate')funciona bien.
Martin Smith
66
Pequeña sugerencia relacionada: si desea actualizar una columna justo después de la adición de la columna (creo que muchos usuarios estaban buscando este artículo para ese propósito), podría usar una declaración EXEC sp_executesqlformada UPDATE.
cassandrad
La verdadera respuesta es que debe agregar la base de datos con la que está comprobando, por lo que esFROM [YourDatabase].INFORMATION_SCHEMA.COLUMNS
Alex Kwitny

Respuestas:

2054

SQL Server 2005 en adelante:

IF EXISTS(SELECT 1 FROM sys.columns 
          WHERE Name = N'columnName'
          AND Object_ID = Object_ID(N'schemaName.tableName'))
BEGIN
    -- Column Exists
END

La versión de Martin Smith es más corta:

IF COL_LENGTH('schemaName.tableName', 'columnName') IS NOT NULL
BEGIN
    -- Column Exists
END
Trigo Mitch
fuente
En la versión de Martin Smith, una cosa para mencionar es no incluir columnName entre corchetes []. Cuando columnName está entre corchetes [], dará un valor nulo incluso si la columna existe en la tabla
Hemendra
@HemendraSinghChauhan, eso es porque no son parte del nombre. También lo encontrará al comparar con el nombre ensys.columns
Martin Smith
@MartinSmith no lo sabía, estaba usando tu respuesta y me encontré con esto. Generalmente uso corchetes durante la adición de columnas, así que también los uso dentro de la función COL_LENGTH. Mi código era así:Alter table Table_Name Add [ColumnName] NVarchar(max) NULL; Select COL_LENGTH('[TABLE_NAME]', '[COLUMN_NAME]')
Hemendra
Sí, eso no es válido. Los argumentos COL_LENGTHdeben ser sin comillas. En teoría, es posible que alguien cree una columna que realmente tenga un nombre de [COLUMN_NAME], por ejemplo, CREATE TABLE #T([[COLUMN_NAME]]] INT); SELECT * FROM #Ty sería ambiguo si esta no fuera la regla.
Martin Smith
987

Una versión más concisa

IF COL_LENGTH('table_name','column_name') IS NULL
BEGIN
/* Column does not exist or caller does not have permission to view the object */
END

El punto sobre los permisos para ver metadatos se aplica a todas las respuestas, no solo a esta.

Tenga en cuenta que el nombre de la primera tabla de parámetros COL_LENGTHpuede estar en uno, dos o tres formatos de nombre de parte, según sea necesario.

Un ejemplo que hace referencia a una tabla en una base de datos diferente es

COL_LENGTH('AdventureWorks2012.HumanResources.Department','ModifiedDate')

Una diferencia con esta respuesta en comparación con el uso de las vistas de metadatos es que las funciones de metadatos, como COL_LENGTHsiempre, solo devuelven datos sobre cambios comprometidos, independientemente del nivel de aislamiento vigente.

Martin Smith
fuente
11
Esto es menos legible que algunas de las otras respuestas, probablemente por qué no tiene una calificación tan alta.
Bill Yang
38
@Bill: ¿menos legible de qué manera? Se ve bien en Firefox. Esta respuesta se publicó más de 2 años después que la aceptada, lo que explica la calificación de la OMI. Si quisiste decir menos claro que es una existencia, verifica que este tipo de lenguaje es bastante común en SQL Server. por ejemplo, IF OBJECT_ID('TableName','U') IS NULLpara verificar la existencia de objetos o DB_ID('foo')para verificar la existencia de la base de datos.
Martin Smith
59
@ MartininSmith Estoy seguro de que quiso decir menos legible porque si no conocieras este idioma y heredases este código de otra persona, no entenderías de inmediato lo que hace el código. Algo así como escribir en x>>2lugar de x/4en C ++. El código más detallado ( if exists (select column_name from information_schema ...)) ocupa mucho más espacio, pero nadie se rascaría la cabeza tratando de descubrir qué hace.
Kip
22
Además de más conciso, esta es una solución mucho más rápida. Acceder a INFORMATION_SCHEMAvistas o sys.columnsvisitas al disco, mientras COL_LENGTHutiliza metadatos de base de datos en caché.
wqw
77
Probablemente esta no sea la respuesta mejor valorada porque se le dio 2,5 años después de la otra. Es por eso que siempre verifico las fechas cuando comparo las calificaciones en dos respuestas. Lleva mucho más tiempo superar una respuesta que se dio mucho antes. ;)
Sean
149

Ajusta lo siguiente para adaptarlo a tus requisitos específicos:

if not exists (select
                     column_name
               from
                     INFORMATION_SCHEMA.columns
               where
                     table_name = 'MyTable'
                     and column_name = 'MyColumn')
    alter table MyTable add MyColumn int

Editar para lidiar con la edición a la pregunta : Eso debería funcionar: revise cuidadosamente su código para ver si hay errores estúpidos; ¿está consultando INFORMACIÓN_SCHEMA en la misma base de datos a la que se aplica su inserción, por ejemplo? ¿Tiene un error tipográfico en el nombre de su tabla / columna en cualquiera de las declaraciones?

Luke Bennett
fuente
3
Me acabo de enterar de que agregar TABLE_SCHEMA = 'mySchema' después de que la cláusula soluciona el problema.
Maciej
12
-1: no responde la pregunta de OP, solo agrega la nueva información sobre cómo agregar una nueva columna a pesar de que OP no pregunta nada de eso, no aborda el comentario de OP.
ANeves
1
+1 Responde perfectamente a la pregunta de OP con una bonificación de la información adicional que el OP tenía para el próximo de todos modos. Y esto era lo que estaba buscando.
Bitterblue
74

Prueba esto...

IF NOT EXISTS(
  SELECT TOP 1 1
  FROM INFORMATION_SCHEMA.COLUMNS
  WHERE 
    [TABLE_NAME] = 'Employees'
    AND [COLUMN_NAME] = 'EmployeeID')
BEGIN
  ALTER TABLE [Employees]
    ADD [EmployeeID] INT NULL
END
Leon Tayson
fuente
66
Este método también funciona con SQL CE, mientras que algunos de los otros métodos mencionados no.
SWalters - Reincorporar a Monica el
99
Puedes usar en SELECT 1lugar de SELECT TOP 1 1;).
shA.t
44
Dentro de una EXISTSdeclaración, SQL optimiza automáticamente las columnas (al igual que count(*)), por lo que SELECT *será suficiente.
Marc L.
En aras de la exhaustividad, debe considerar agregar and [TABLE_SCHEMA] = '???'a la cláusula WHERE.
Andrew Jens el
51

Para las personas que están comprobando la existencia de la columna, para dejarla caer.

Desde SQL Server 2016 puede usar nuevas instrucciones DIE en lugar de grandes IFcontenedores

ALTER TABLE Table_name DROP COLUMN IF EXISTS Column_name
P ரதீப்
fuente
47

Preferiría INFORMATION_SCHEMA.COLUMNSuna tabla del sistema porque Microsoft no garantiza preservar las tablas del sistema entre versiones. Por ejemplo, dbo.syscolumnstodavía funciona en SQL 2008, pero está en desuso y podría eliminarse en cualquier momento en el futuro.

Christian Hayter
fuente
55
Bueno, sí, eso es evidente, ya que las INFORMATION_SCHEMAvistas contienen solo metadatos estándar ANSI. Sin embargo, eso es suficiente para una prueba de existencia.
Christian Hayter
3
Microsoft dice "En futuras versiones de SQL Server, Microsoft puede aumentar la definición de cualquier vista de catálogo del sistema agregando columnas al final de la lista de columnas. Recomendamos no usar la sintaxis SELECT * FROM sys.catalog_view_name en el código de producción porque el número de las columnas devueltas pueden cambiar y romper su aplicación ". Eso implica que no eliminarán columnas ni cambiarán su orden. Eso es lo suficientemente bueno para la compatibilidad con versiones anteriores para todos los casos, excepto los extremos.
siride
42

Puede usar las vistas del sistema de esquema de información para averiguar casi cualquier cosa sobre las tablas que le interesan:

SELECT *
  FROM INFORMATION_SCHEMA.COLUMNS
 WHERE TABLE_NAME = 'yourTableName'
 ORDER BY ORDINAL_POSITION

También puede interrogar vistas, procedimientos almacenados y prácticamente cualquier cosa sobre la base de datos utilizando las vistas Information_schema.

anónimo
fuente
Esto es exactamente lo que está utilizando el cuestionario, necesitaba saber cómo agregar la columna si no existiera.
Birel
35

Intenta algo como:

CREATE FUNCTION ColumnExists(@TableName varchar(100), @ColumnName varchar(100))
RETURNS varchar(1) AS
BEGIN
DECLARE @Result varchar(1);
IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.Columns WHERE TABLE_NAME = @TableName AND COLUMN_NAME = @ColumnName)
BEGIN
    SET @Result = 'T'
END
ELSE
BEGIN
    SET @Result = 'F'
END
RETURN @Result;
END
GO

GRANT EXECUTE ON  [ColumnExists] TO [whoever]
GO

Entonces úsalo así:

IF ColumnExists('xxx', 'yyyy') = 'F'
BEGIN
  ALTER TABLE xxx
  ADD yyyyy varChar(10) NOT NULL
END
GO

Debería funcionar tanto en SQL Server 2000 como en SQL Server 2005. No estoy seguro acerca de SQL Server 2008, pero no veo por qué no.

Matt Lacey
fuente
34

Primero verifique si la combinación table/ column( id/ name) existe en dbo.syscolumns(una tabla interna de SQL Server que contiene definiciones de campo), y si no, emita la ALTER TABLEconsulta apropiada para agregarla. Por ejemplo:

IF NOT EXISTS ( SELECT  *
            FROM    syscolumns
            WHERE   id = OBJECT_ID('Client')
                    AND name = 'Name' ) 
ALTER TABLE Client
ADD Name VARCHAR(64) NULL
mdb
fuente
28

Un buen amigo y colega mío me mostró cómo también puede usar un IFbloque con funciones SQL OBJECT_IDy COLUMNPROPERTYen SQL SERVER 2005+ para verificar una columna. Puede usar algo similar a lo siguiente:

Puedes verlo por ti mismo aquí

IF (OBJECT_ID(N'[dbo].[myTable]') IS NOT NULL AND
    COLUMNPROPERTY( OBJECT_ID(N'[dbo].[myTable]'), 'ThisColumnDoesNotExist', 'ColumnId') IS NULL)
BEGIN
    SELECT 'Column does not exist -- You can add TSQL to add the column here'
END
Jaguar brasileño
fuente
1
Y, por supuesto, si está seguro de que la tabla existe, puede omitir la primera parte de la condición y verificar COLUMNPROPERTYsolo.
Ruud Helderman
26
declare @myColumn   as nvarchar(128)
set @myColumn = 'myColumn'
if not exists (
    select  1
    from    information_schema.columns columns 
    where   columns.table_catalog   = 'myDatabase'
        and columns.table_schema    = 'mySchema' 
        and columns.table_name      = 'myTable' 
        and columns.column_name     = @myColumn
    )
begin
    exec('alter table myDatabase.mySchema.myTable add'
    +'    ['+@myColumn+'] bigint       null')
end
Tuomo Kämäräinen
fuente
22

Esto funcionó para mí en SQL 2000:

IF EXISTS 
(
    SELECT * 
    FROM INFORMATION_SCHEMA.COLUMNS 
    WHERE table_name = 'table_name' 
    AND column_name = 'column_name'
)
BEGIN
...
END
Joe M
fuente
21

Prueba esto

SELECT COLUMNS.*
FROM   INFORMATION_SCHEMA.COLUMNS COLUMNS,
       INFORMATION_SCHEMA.TABLES TABLES
WHERE  COLUMNS.TABLE_NAME = TABLES.TABLE_NAME
       AND Upper(COLUMNS.COLUMN_NAME) = Upper('column_name') 
Douglas Tondo
fuente
No necesita INFORMATION_SCHEMA.TABLESy no filtra columnas para una tabla específica, por lo que a veces devolverá más de una fila para los mismos nombres de columna en tablas separadas;).
shA.t
19

Necesitaba algo similar para SQL SERVER 2000 y, como señala @Mitch, esto solo funciona en 2005+.

En caso de que ayude a alguien más, esto es lo que funcionó para mí al final:

if exists (
    select * 
    from 
        sysobjects, syscolumns 
    where 
        sysobjects.id = syscolumns.id 
        and sysobjects.name = 'table' 
        and syscolumns.name = 'column')
Congelación XIII
fuente
15
if exists (
  select * 
  from INFORMATION_SCHEMA.COLUMNS 
  where TABLE_NAME = '<table_name>' 
  and COLUMN_NAME = '<column_name>'
) begin
  print 'Column you have specified exists'
end else begin
  print 'Column does not exist'
end
BYRAKUR SURESH BABU
fuente
13
IF NOT EXISTS( SELECT NULL
            FROM INFORMATION_SCHEMA.COLUMNS
           WHERE table_name = 'TableName'
             AND table_schema = 'SchemaName'
             AND column_name = 'ColumnName')  BEGIN

  ALTER TABLE [SchemaName].[TableName] ADD [ColumnName] int(1) NOT NULL default '0';

END;
Na30m
fuente
2
Creo que te referías a table_schema = 'schema_name'.
Tab Alleman
11

Una versión de la tabla temporal de la respuesta aceptada :

if (exists(select 1 
             from tempdb.sys.columns  
            where Name = 'columnName'
              and Object_ID = object_id('tempdb..#tableName')))
begin
...
end
crokusek
fuente
1
¿Cómo es eso diferente de la respuesta aceptada? ¿No funcionaría una tabla temporal en la respuesta aceptada?
John Saunders
1
Correcto. La respuesta aceptada no funciona para las tablas temporales porque 'sys.columns' debe especificarse como 'tempdb.sys.columns' y el nombre de la tabla debe estar precedido por 'tempdb ..'.
crokusek
10
select distinct object_name(sc.id)
from syscolumns sc,sysobjects so  
where sc.name like '%col_name%' and so.type='U'
Nishad
fuente
8

La respuesta de Wheat es buena, pero supone que no tiene pares de nombres de tabla / columna idénticos en ningún esquema o base de datos. Para que sea seguro para esa condición, use esto ...

select *
from Information_Schema.Columns
where Table_Catalog = 'DatabaseName'
  and Table_Schema = 'SchemaName'
  and Table_Name = 'TableName'
  and Column_Name = 'ColumnName'
Daniel Barbalace
fuente
8

Hay varias formas de verificar la existencia de una columna. Recomiendo encarecidamente usarlo INFORMATION_SCHEMA.COLUMNSya que está creado para comunicarse con el usuario. Considere las siguientes tablas:

 sys.objects
 sys.columns

e incluso algunos otros métodos de acceso disponibles para verificar system catalog.

Además, no es necesario usar SELECT *, simplemente pruébeloNULL value

IF EXISTS(
           SELECT NULL 
           FROM INFORMATION_SCHEMA.COLUMNS
           WHERE
             TABLE_NAME = 'myTableName'
             AND COLUMN_NAME = 'myColumnName'
         ) 
Ali Elmi
fuente
1
No importa incluso si SELECT *con EXISTS, porque cuando se utiliza que existe en realidad no seleccionar todas las filas y todas las columnas, internamente que sólo comprueba la existencia y en realidad no comprueba todas las filas y columnas
Pawan Nogariya
7

Una de las soluciones más simples y comprensibles es:

IF COL_LENGTH('Table_Name','Column_Name') IS NULL
 BEGIN
    -- Column Not Exists, implement your logic
 END 
ELSE
 BEGIN
    -- Column Exists, implement your logic
 END
Arsman Ahmad
fuente
7

Aquí hay un script simple que uso para administrar la adición de columnas en la base de datos:

IF NOT EXISTS (
        SELECT *
        FROM sys.Columns
        WHERE Name = N'QbId'
            AND Object_Id = Object_Id(N'Driver')
        )
BEGIN
    ALTER TABLE Driver ADD QbId NVARCHAR(20) NULL
END
ELSE
BEGIN
    PRINT 'QbId is already added on Driver'
END

En este ejemplo, Namese ColumnNamedebe agregar el y Object_Ides elTableName

UJS
fuente
4

La consulta a continuación se puede usar para verificar si la columna buscada existe o no en la tabla. Podemos tomar una decisión basada en el resultado buscado también como se muestra a continuación.

IF EXISTS (SELECT 'Y' FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = <YourTableName> AND COLUMN_NAME = <YourColumnName>)
  BEGIN
    SELECT 'Column Already Exists.'
  END
  ELSE
  BEGIN
    ALTER TABLE <YourTableName> ADD <YourColumnName> <DataType>[Size]
  END
Suraj Kumar
fuente
3

Otra variación más ...

SELECT 
  Count(*) AS existFlag 
FROM 
  sys.columns 
WHERE 
  [name] = N 'ColumnName' 
  AND [object_id] = OBJECT_ID(N 'TableName')
Manuel Alves
fuente
1

table -> script table as -> new windows - tiene un script de diseño. verificar y encontrar el nombre de la columna en nuevas ventanas

arnav
fuente
1

Ejecute la consulta a continuación para verificar si la columna existe en la tabla dada:

IF(SELECT COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = 'TableName' AND COLUMN_NAME = 'ColumnName') IS NOT NULL
PRINT 'Column Exists in the given table';
S Krishna
fuente
1

Otra contribución es la siguiente muestra que agrega la columna si no existe.

    USE [Northwind]
    GO

    IF NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS 
                    WHERE TABLE_NAME = 'Categories'
                        AND COLUMN_NAME = 'Note')
    BEGIN

    ALTER TABLE Categories ADD Note NVARCHAR(800) NULL

    END
    GO

Espero eso ayude. Simone

Simone Spagna
fuente
0
IF EXISTS(SELECT 1 FROM sys.columns 
      WHERE Name = N'columnName'
      AND Object_ID = Object_ID(N'schemaName.tableName'))

Esta debería ser la forma más fácil y la solución directa a este problema. Lo he usado varias veces para escenarios similares. Funciona de maravilla, no hay dudas al respecto.

Ilangeeran
fuente
0
IF EXISTS (
SELECT *
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_CATALOG = 'Database Name'
and TABLE_SCHEMA = 'Schema Name'
and TABLE_NAME = 'Table Name'
and COLUMN_NAME = 'Column Name'
and DATA_TYPE = 'Column Type') -- Where statement lines can be deleted.

BEGIN
--COLUMN EXISTS IN TABLE
END

ELSE BEGIN
--COLUMN DOES NOT EXISTS IN TABLE
END
Mohamad Reza Shahrestani
fuente
0

Haga algo si la columna no existe:

BEGIN
    IF (COL_LENGTH('[dbo].[Table]', 'Column ') IS NULL)
    BEGIN
        //Do something
    END
END;

Haga algo si la columna existe:

BEGIN
    IF (COL_LENGTH('[dbo].[Table]', 'Column ') IS NOT NULL)
    BEGIN
        //Do something
    END
END;
Jagjit Singh
fuente