Thêm một cột vào bảng, nếu nó chưa tồn tại


187

Tôi muốn viết một truy vấn cho MS SQL Server có thêm một cột vào bảng. Nhưng tôi không muốn hiển thị lỗi khi tôi chạy / thực hiện truy vấn sau.

Tôi đang sử dụng loại truy vấn này để thêm bảng ...

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

Nhưng tôi không biết làm thế nào để viết truy vấn này cho một cột.



Bạn nên sử dụng sys.tablesthay vì "chung chung" sys.objects- sau đó bạn không phải chỉ định loại rõ ràng (rõ ràng từ sys.tablesđã ....)
marc_s

COL_LENGTH Thay thế chỉ hoạt động từ SQL-Server 2008, nhưng nó hoạt động.
Paul-Henri

Câu trả lời:


218

Bạn có thể sử dụng một cấu trúc tương tự bằng cách sử dụng sys.columnsbảng io sys.objects.

IF NOT EXISTS (
  SELECT * 
  FROM   sys.columns 
  WHERE  object_id = OBJECT_ID(N'[dbo].[Person]') 
         AND name = 'ColumnName'
)

42
Lưu ý rằng trong trường hợp này, bạn muốn sử dụng NẾU KHÔNG EXISTS trong mã thực tế của mình.
Nat

2
Đối với truy vấn được tối ưu hóa, bạn có thể sử dụng top 1 với câu lệnh chọn
Banketeshvar Narayan

11
@BanketeshvarNarayan điều này không chính xác. Các kế hoạch thực hiện cho các truy vấn con trong một EXISTSmệnh đề là giống hệt nhau. Những thứ như SELECT 1hoặc SELECT TOP 1không cần thiết. Bản EXISTSthân mệnh đề yêu cầu trình tối ưu hóa truy vấn chỉ thực hiện các lần đọc tối thiểu cần thiết để đánh giá EXISTS... ít nhất là trong SQL Server. Các công cụ DB khác có thể có trình tối ưu hóa truy vấn hiệu quả hơn hoặc kém hơn.
Kenneth Cochran

9
@BanketeshvarNarayan Nếu bạn đang tối ưu hóa các ADD Columntruy vấn của mình ... bạn phải chạy chúng quá thường xuyên!
Fenton

1
@ user391339 - Tôi đã đăng một cấu trúc tương tự như OP đã đăng nhưng có, nếu bạn muốn thực hiện hành động nếu cột không tồn tại, câu lệnh sẽ là NẾU KHÔNG BỎ QUA. Tôi thực sự không cảm thấy cần phải chỉnh sửa câu trả lời cho điều này nhưng hãy thoải mái tự chỉnh sửa nếu bạn nghĩ đó là một sự cải tiến.
Lieven Keersmaekers

91
IF COL_LENGTH('table_name', 'column_name') IS NULL
BEGIN
    ALTER TABLE table_name
    ADD [column_name] INT
END

1
Tôi đã thử làm điều này nhưng nó trả về một lỗi cho biết hàm COL_LENGTH không tồn tại.
ThEpRoGrAmMiNgNoOb

3
Yêu cầu SQL Server 2008+
Robert Brown

6
Bổ sung nhỏ - người ta không nên sử dụng dấu ngoặc vuông trong tên cột, vì COL_LENGTH('table_name', '[column_name]')luôn trả về null trong SQL Server 2016 ( COL_LENGTH('[table_name]', 'column_name') works as expected).
stop-cran

33

Một lựa chọn khác. Tôi thích cách tiếp cận này vì nó ít viết hơn nhưng cả hai đều hoàn thành cùng một điều.

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

Tôi cũng nhận thấy rằng bạn đang tìm kiếm nơi bảng tồn tại rõ ràng chỉ là cái này

 if COLUMNPROPERTY( OBJECT_ID('dbo.Person'),'ColumnName','ColumnId') is not null

2
Tôi thích nó. Tôi nghĩ phần tốt nhất về việc đăng bài ở đây là tìm đá quý như thế này.
JStead

1
'CộtId' là gì?
Marius Stănescu

'CộtId' là tên của thuộc tính cột bạn đang kiểm tra. Bạn có thể đã sử dụng bất kỳ tên tài sản nào tồn tại trên một cột, chẳng hạn như tên, v.v.
Jacques Bosch

5

Đây là một biến thể khác làm việc cho tôi.

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

EDIT: Lưu ý rằng các INFORMATION_SCHEMAkhung nhìn có thể không phải lúc nào cũng được cập nhật, SYS.COLUMNSthay vào đó hãy sử dụng :

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


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

Tôi hy vọng điều này sẽ giúp. Thêm thông tin


Điều này làm việc cho tôi trên SqlServer 2000 trong khi câu trả lời được chấp nhận thì không. Các khung nhìn sys. * Dường như đã được thêm vào đâu đó xung quanh SqlServer 2005, cf docs.microsoft.com/en-us/sql/relational-databases/...
ZeRemz

0

Khi kiểm tra một cột trong cơ sở dữ liệu khác, bạn chỉ cần bao gồm tên cơ sở dữ liệu:

IF NOT EXISTS (
  SELECT * 
  FROM   DatabaseName.sys.columns 
  WHERE  object_id = OBJECT_ID(N'[DatabaseName].[dbo].[TableName]') 
         AND name = 'ColumnName'
)

-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
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.