Làm cách nào để kiểm tra xem một cột có tồn tại trong bảng SQL Server không?


1853

Tôi cần thêm một cột cụ thể nếu nó không tồn tại. Tôi có một cái gì đó như sau, nhưng nó luôn trả về false:

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

Làm cách nào để kiểm tra xem một cột có tồn tại trong bảng của cơ sở dữ liệu SQL Server không?


12
Tôi thực sự không nghĩ có gì sai với mã trong câu hỏi: Hoạt động tốt đối với tôi trong năm 2008 R2. (Có lẽ bạn đang chạy nó trong cơ sở dữ liệu sai? Có lẽ cơ sở dữ liệu của bạn phân biệt chữ hoa chữ thường và bạn không có trường hợp đúng trong chuỗi myTableName / myColumnName của bạn? Loại truy vấn này có vẻ linh hoạt hơn giải pháp COL_LENGTH: Tôi có thể để chạy nó với một cơ sở dữ liệu khác và thậm chí qua một liên kết cơ sở dữ liệu bằng cách đặt tiền tố phù hợp "THÔNG TIN_SCHema". Không thể thấy cách thực hiện với chức năng siêu dữ liệu COL_LENGTH.
mwardm

3
@mwardm - COL_LENGTH('AdventureWorks2012.HumanResources.Department ','ModifiedDate')hoạt động tốt.
Martin Smith

6
Gợi ý nhỏ liên quan: nếu bạn muốn cập nhật một cột ngay sau khi thêm cột (tôi tin rằng nhiều người dùng đã tìm kiếm bài viết này cho mục đích đó), bạn có thể sử dụng EXEC sp_executesqlvới UPDATEcâu lệnh được tạo .
cassandrad

Câu trả lời thực sự là bạn nên thêm cơ sở dữ liệu mà bạn đang kiểm tra vì vậyFROM [YourDatabase].INFORMATION_SCHEMA.COLUMNS
Alex Kwitny

Câu trả lời:


2054

SQL Server 2005 trở đi:

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

Phiên bản của Martin Smith ngắn hơn:

IF COL_LENGTH('schemaName.tableName', 'columnName') IS NOT NULL
BEGIN
    -- Column Exists
END

Trong phiên bản của Martin Smith, một điều cần đề cập là không bao gồm tên cột trong dấu ngoặc vuông []. Khi cộtName nằm trong dấu ngoặc vuông [], nó sẽ không có giá trị ngay cả khi cột tồn tại trong bảng
Hemendra

@HemendraSinghChauhan - đó là vì họ không phải là một phần của tên. Bạn cũng sẽ thấy rằng khi so sánh với tên trongsys.columns
Martin Smith

@MartinSmith không biết rằng, tôi đã sử dụng câu trả lời của bạn và tình cờ thấy điều này. Nói chung, tôi sử dụng dấu ngoặc vuông trong khi thêm các cột, vì vậy tôi cũng đã sử dụng chúng trong hàm COL_LENGTH. Mã của tôi là như thế này:Alter table Table_Name Add [ColumnName] NVarchar(max) NULL; Select COL_LENGTH('[TABLE_NAME]', '[COLUMN_NAME]')
Hemendra

vâng, điều đó không hợp lệ. Các đối số COL_LENGTHcần phải được bỏ qua. Về mặt lý thuyết, ai đó có thể tạo một cột thực sự có tên [COLUMN_NAME]- ví dụ CREATE TABLE #T([[COLUMN_NAME]]] INT); SELECT * FROM #Tvà sau đó sẽ là mơ hồ nếu đây không phải là quy tắc.
Martin Smith

987

Một phiên bản ngắn gọn hơn

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

Điểm về quyền về xem siêu dữ liệu áp dụng cho tất cả các câu trả lời không chỉ câu trả lời này.

Lưu ý rằng tên bảng tham số đầu tiên COL_LENGTHcó thể ở định dạng một, hai hoặc ba phần tên theo yêu cầu.

Một ví dụ tham chiếu một bảng trong cơ sở dữ liệu khác nhau là

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

Một điểm khác biệt với câu trả lời này so với việc sử dụng các chế độ xem siêu dữ liệu là các hàm siêu dữ liệu như COL_LENGTHluôn chỉ trả về dữ liệu về các thay đổi đã cam kết bất kể mức độ cô lập có hiệu lực.


11
Điều này ít đọc hơn một số câu trả lời khác, có lẽ tại sao nó không được đánh giá cao.
Bill Yang

38
@Bill - Ít đọc theo cách nào? Có vẻ tốt trong Firefox. Câu trả lời này đã được đăng muộn hơn 2 năm so với câu trả lời được chấp nhận, điều này giải thích cho xếp hạng IMO. Nếu bạn muốn nói rõ hơn rằng đó là sự tồn tại, hãy kiểm tra loại thành ngữ này khá phổ biến trong SQL Server. ví dụ: sử dụng IF OBJECT_ID('TableName','U') IS NULLđể kiểm tra sự tồn tại của đối tượng hoặc DB_ID('foo')để kiểm tra sự tồn tại của cơ sở dữ liệu.
Martin Smith

59
@MartinSmith Tôi chắc chắn rằng anh ta có nghĩa là ít đọc hơn vì nếu bạn không biết thành ngữ này và bạn đã thừa hưởng mã này từ người khác, bạn sẽ không hiểu ngay mã đó làm gì. Kiểu như viết x>>2thay vì x/4trong C ++. Mã verbose nhiều hơn ( if exists (select column_name from information_schema ...)) chiếm nhiều không gian hơn, nhưng không ai có thể gãi đầu cố gắng tìm ra nó làm gì.
Kip

22
Bên cạnh đó ngắn gọn hơn đây là một giải pháp nhanh hơn. Truy cập INFORMATION_SCHEMAlượt xem hoặc sys.columnslượt truy cập đĩa, trong khi COL_LENGTHsử dụng siêu dữ liệu được lưu trong bộ nhớ cache.
wqw

7
Đây có lẽ không phải là câu trả lời được đánh giá cao nhất bởi vì nó đã được đưa ra 2,5 năm sau câu trả lời khác. Đó là lý do tại sao tôi luôn kiểm tra ngày tháng khi so sánh xếp hạng trên hai câu trả lời. Phải mất nhiều thời gian hơn để vượt qua một câu trả lời đã được đưa ra sớm hơn nhiều. ;)
Sean

149

Tinh chỉnh dưới đây để phù hợp với yêu cầu cụ thể của bạn:

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

Chỉnh sửa để đối phó với chỉnh sửa thành câu hỏi : Điều đó sẽ hoạt động - hãy xem xét kỹ mã của bạn cho những sai lầm ngu ngốc; bạn có đang truy vấn Information_SCHema trên cùng một cơ sở dữ liệu khi chèn của bạn đang được áp dụng không? Bạn có một lỗi đánh máy trong tên bảng / cột của bạn trong một trong hai câu không?


3
Tôi mới phát hiện ra rằng việc thêm TABLE_SCHema = 'mySchema' sau khi mệnh đề sửa lỗi.
Maciej

12
-1: không trả lời câu hỏi của OP, chỉ thêm thông tin mới về cách thêm một đồng nghiệp mới mặc dù OP hoàn toàn không hỏi về điều đó, không giải quyết bình luận của OP.
ANeves

1
+1 Câu trả lời Câu hỏi của OP hoàn hảo với phần thưởng là thông tin bổ sung mà OP sẽ thực hiện cho các lần tiếp theo. Và đây là những gì tôi đang tìm kiếm.
Bitterblue

74

Thử cái này...

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

6
Phương pháp này cũng hoạt động với SQL CE, trong khi một số phương thức khác được đề cập thì không.
SWalters - Tái lập lại

9
Bạn có thể sử dụng SELECT 1thay vì SELECT TOP 1 1;).
shA.t

4
Trong một EXISTScâu lệnh, SQL sẽ tự động tối ưu hóa các cột đi (giống như count(*)) vì vậy SELECT *sẽ đủ.
Marc L.

Để hoàn thiện, bạn nên xem xét thêm and [TABLE_SCHEMA] = '???'vào mệnh đề WHERE.
Andrew Jens

51

Đối với những người đang kiểm tra sự tồn tại của cột để thả nó.

Từ SQL Server 2016, bạn có thể sử dụng các câu lệnh DIE mới thay vì các IFhàm bao lớn

ALTER TABLE Table_name DROP COLUMN IF EXISTS Column_name

47

Tôi thích INFORMATION_SCHEMA.COLUMNShơn một bảng hệ thống vì Microsoft không đảm bảo duy trì các bảng hệ thống giữa các phiên bản. Ví dụ, dbo.syscolumnsvẫn hoạt động trong SQL 2008, nhưng nó không dùng nữa và có thể bị xóa bất cứ lúc nào trong tương lai.



5
Vâng, không cần phải nói vì các INFORMATION_SCHEMAkhung nhìn chỉ chứa siêu dữ liệu tiêu chuẩn ANSI. Tuy nhiên, điều đó là đủ cho một bài kiểm tra tồn tại.
Christian Hayter

3
Microsoft cho biết "Trong các bản phát hành SQL Server trong tương lai, Microsoft có thể tăng định nghĩa của bất kỳ chế độ xem danh mục hệ thống nào bằng cách thêm các cột vào cuối danh sách cột. Chúng tôi khuyên bạn không nên sử dụng cú pháp CHỌN * TỪ sys.catalog_view_name trong mã sản xuất vì số lượng các cột được trả về có thể thay đổi và phá vỡ ứng dụng của bạn. " Điều đó ngụ ý rằng họ sẽ không xóa cột hoặc thay đổi thứ tự của họ. Đó là khả năng tương thích đủ tốt cho tất cả trừ trường hợp cạnh.
siride

42

Bạn có thể sử dụng các khung nhìn hệ thống lược đồ thông tin để tìm hiểu khá nhiều thứ về các bảng bạn quan tâm:

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

Bạn cũng có thể thẩm vấn các khung nhìn, các thủ tục được lưu trữ và hầu hết mọi thứ về cơ sở dữ liệu bằng cách sử dụng các khung nhìn Information_schema.


Đây chính xác là những gì bảng câu hỏi đang sử dụng, anh ta cần biết cách thêm cột nếu nó không tồn tại.
Birel

35

Hãy thử một cái gì đó như:

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

Sau đó sử dụng nó như thế này:

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

Nó nên hoạt động trên cả SQL Server 2000 & SQL Server 2005. Không chắc chắn về SQL Server 2008, nhưng không hiểu tại sao không.


34

Trước tiên hãy kiểm tra xem tổ hợp table/ column( id/ name) có tồn tại trong dbo.syscolumns(bảng SQL Server bên trong có chứa các định nghĩa trường không) và nếu không đưa ra ALTER TABLEtruy vấn thích hợp để thêm nó. Ví dụ:

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

28

Một người bạn tốt và đồng nghiệp của tôi đã chỉ cho tôi cách bạn cũng có thể sử dụng một IFkhối với các hàm SQL OBJECT_IDCOLUMNPROPERTYtrong SQL SERVER 2005+ để kiểm tra một cột. Bạn có thể sử dụng một cái gì đó tương tự như sau:

Bạn có thể thấy cho chính mình ở đây

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

1
Và tất nhiên, nếu bạn tự tin rằng bảng tồn tại, bạn có thể bỏ qua phần đầu tiên của điều kiện và chỉ kiểm tra COLUMNPROPERTY.
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

22

Điều này làm việc cho tôi trong SQL 2000:

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

21

Thử cái này

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') 

Bạn không cần INFORMATION_SCHEMA.TABLESvà bạn không lọc các cột cho một bảng cụ thể, do đó, đôi khi nó sẽ trả về nhiều hơn một hàng cho cùng một tên cột trong các bảng riêng biệt;).
shA.t

19

Tôi cần tương tự cho SQL SERVER 2000 và, như @Mitch chỉ ra, điều này chỉ hoạt động trong năm 2005+.

Nếu nó giúp được ai khác, đây là điều làm việc cho tôi cuối cùng:

if exists (
    select * 
    from 
        sysobjects, syscolumns 
    where 
        sysobjects.id = syscolumns.id 
        and sysobjects.name = 'table' 
        and syscolumns.name = 'column')

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

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;

2
Tôi nghĩ bạn có nghĩa là bảng_schema = 'giản đồ tên'.
Tab Alleman

11

Một phiên bản bảng tạm thời của câu trả lời được chấp nhận :

if (exists(select 1 
             from tempdb.sys.columns  
            where Name = 'columnName'
              and Object_ID = object_id('tempdb..#tableName')))
begin
...
end

1
Làm thế nào khác với câu trả lời được chấp nhận? Một bảng tạm thời không hoạt động trong câu trả lời được chấp nhận?
John Saunders

1
Chính xác. Câu trả lời được chấp nhận không hoạt động đối với các bảng tạm thời vì 'sys.columns' phải được chỉ định là 'tempdb.sys.columns' và tên bảng phải được đặt trước 'tempdb ..'.
crokusek

10
select distinct object_name(sc.id)
from syscolumns sc,sysobjects so  
where sc.name like '%col_name%' and so.type='U'

8

Câu trả lời của Wheat là tốt, nhưng giả sử bạn không có bất kỳ cặp tên / tên cột giống hệt nhau trong bất kỳ lược đồ hoặc cơ sở dữ liệu nào. Để đảm bảo an toàn cho tình trạng đó, hãy sử dụng ...

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

8

Có một số cách để kiểm tra sự tồn tại của một cột. Tôi thực sự khuyên bạn nên sử dụng INFORMATION_SCHEMA.COLUMNSvì nó được tạo ra để giao tiếp với người dùng. Xem xét các bảng sau:

 sys.objects
 sys.columns

và thậm chí một số phương thức truy cập khác có sẵn để kiểm tra system catalog.

Ngoài ra, không cần sử dụng SELECT *, chỉ cần kiểm tra nó bằng cáchNULL value

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

1
Cho dù bạn SELECT *EXISTSsử dụng, bởi vì khi tồn tại được sử dụng, nó không thực sự chọn tất cả các hàng và tất cả các cột, bên trong nó chỉ kiểm tra sự tồn tại và không thực sự kiểm tra tất cả các hàng và cột
Pawan Nogariya

7

Một trong những giải pháp đơn giản và dễ hiểu nhất là:

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

7

Đây là một tập lệnh đơn giản tôi sử dụng để quản lý việc thêm các cột trong cơ sở dữ liệu:

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

Trong ví dụ này, NameColumnNameđể được thêm vào và Object_IdTableName


4

Truy vấn dưới đây có thể được sử dụng để kiểm tra xem cột tìm kiếm có tồn tại hay không trong bảng. Chúng tôi có thể đưa ra quyết định dựa trên kết quả tìm kiếm cũng như dưới đây.

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

3

Một biến thể khác ...

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

1

bảng -> bảng kịch bản dưới dạng -> cửa sổ mới - bạn có tập lệnh thiết kế. kiểm tra và tìm tên cột trong các cửa sổ mới


1

Thực hiện truy vấn dưới đây để kiểm tra xem cột có tồn tại trong bảng đã cho không:

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';

1

Một đóng góp khác là mẫu sau đây thêm cột nếu không tồn tại.

    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

Hy vọng nó giúp. Simone


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

Đây phải là cách khá dễ dàng và giải pháp thẳng cho vấn đề này. Tôi đã sử dụng điều này nhiều lần cho các kịch bản tương tự. Nó hoạt động như một sự quyến rũ, không có nghi ngờ về điều đó.


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

0

Làm gì đó nếu cột không tồn tại:

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

Làm gì đó nếu cột tồn tại:

BEGIN
    IF (COL_LENGTH('[dbo].[Table]', 'Column ') IS NOT NULL)
    BEGIN
        //Do something
    END
END;
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.