Cách kiểm tra xem một hàm có tồn tại trên cơ sở dữ liệu SQL không


138

Tôi cần tìm hiểu xem một hàm có tồn tại trên cơ sở dữ liệu hay không, để tôi có thể bỏ nó và tạo lại nó. Về cơ bản nó phải giống như đoạn mã sau mà tôi sử dụng cho các thủ tục được lưu trữ:

IF EXISTS (
     SELECT  *
     FROM    dbo.sysobjects
     WHERE   id = OBJECT_ID(N'[dbo].[SP_TEST]')
             AND OBJECTPROPERTY(id, N'IsProcedure') = 1 )

Câu trả lời:


206

Đây là những gì SSMS sử dụng khi tập lệnh của bạn sử dụng DROP and CREATEtùy chọn

IF EXISTS (SELECT *
           FROM   sys.objects
           WHERE  object_id = OBJECT_ID(N'[dbo].[foo]')
                  AND type IN ( N'FN', N'IF', N'TF', N'FS', N'FT' ))
  DROP FUNCTION [dbo].[foo]

GO 

Cách tiếp cận này để triển khai các thay đổi có nghĩa là bạn cần tạo lại tất cả các quyền trên đối tượng để bạn có thể xem xét ALTER-ing nếu tồn tại thay thế.


17
Làm cho tôi tự hỏi nhiều hơn tại sao không có chế độ xem danh mục hệ thống sys.fifts .....
marc_s

61

Tôi có xu hướng sử dụng Information_Schema:

IF EXISTS ( SELECT  1
            FROM    Information_schema.Routines
            WHERE   Specific_schema = 'dbo'
                    AND specific_name = 'Foo'
                    AND Routine_Type = 'FUNCTION' ) 

cho các chức năng và thay đổi Routine_Typecho các thủ tục được lưu trữ

IF EXISTS ( SELECT  1
            FROM    Information_schema.Routines
            WHERE   Specific_schema = 'dbo'
                    AND specific_name = 'Foo'
                    AND Routine_Type = 'PROCEDURE' ) 

2
Thật tuyệt, tôi đang tìm kiếm một cái gì đó như thế này và không bao giờ tìm thấy nó. Tôi tin rằng tốt hơn là sử dụng information_schema nói chung vì nó không bị ràng buộc với một RDBMS cụ thể. (btw khái niệm tương thích đa nền tảng xuất phát từ câu trả lời này: stackoverflow.com/a/14290099/420667 )
user420667 4/11/2015

40

Tại sao không chỉ:

IF object_id('YourFunctionName', 'FN') IS NOT NULL
BEGIN
    DROP FUNCTION [dbo].[YourFunctionName]
END
GO

Đối số thứ hai object_idlà tùy chọn, nhưng có thể giúp xác định đúng đối tượng. Có rất nhiều giá trị có thể cho đối số loại này, đặc biệt:

  • FN: Hàm vô hướng
  • IF: Hàm nội tuyến có giá trị bảng
  • TF: Hàm có giá trị bảng
  • FS: Hàm vô hướng (CLR)
  • Hàm có giá trị bảng FT: hội (CLR)

4
Về mặt kỹ thuật điều này có thể thất bại vì nó chỉ kiểm tra rằng có một đối tượng của tên đó. Không phải là có một đối tượng và đó là một chức năng. EG Nếu CREATE TABLE YourFunctionName(X INT);sau đó chạy mã sẽ thất bại.
Martin Smith

1
@MartinSmith: Dễ dàng để làm cho mạnh mẽ. Chỉ cần sử dụng object_id('YourFunction', 'FN')hoặc bất kỳ chỉ định nào khác (đối số thứ hai) để làm rõ loại đối tượng bạn đang đề cập đến.
darlove

@darlove sử dụng 'FN' làm tham số thứ hai có thể không hoạt động. Tôi vừa học được. 'FN' có nghĩa là hàm vô hướng. Liên kết này cho bạn biết các giá trị tham số khác nhau mà bạn có thể vượt qua sqlhints.com/tag/how-to-check-if-feft-exists . Tôi tiếp tục sử dụng 'FN' để kiểm tra chức năng giá trị Bảng hiện có và nó không hoạt động. Tôi phải sử dụng 'TF'
user12345

9

Tôi thấy rằng bạn có thể sử dụng một cách tiếp cận rất dài dòng và đơn giản để kiểm tra sự tồn tại của các đối tượng SQL Server khác nhau theo cách này:

IF OBJECTPROPERTY (object_id('schemaname.scalarfuncname'), 'IsScalarFunction') = 1
IF OBJECTPROPERTY (object_id('schemaname.tablefuncname'), 'IsTableFunction') = 1
IF OBJECTPROPERTY (object_id('schemaname.procname'), 'IsProcedure') = 1

Điều này dựa trên hàm OBRIPROPERTY có sẵn trong SQL 2005+. Bài viết MSDN có thể được tìm thấy ở đây .

Hàm OBRIPROPERTY sử dụng chữ ký sau:

OBJECTPROPERTY ( id , property ) 

Bạn chuyển một giá trị bằng chữ vào tham số thuộc tính, chỉ định loại đối tượng bạn đang tìm kiếm. Có một danh sách lớn các giá trị bạn có thể cung cấp.


Tôi nghĩ sẽ dễ dàng hơn để thấy sự đơn giản của câu trả lời này nếu nó bao gồm một ví dụ if / drop hoàn chỉnh.
Jonathan

6

Tôi biết chủ đề này đã cũ nhưng tôi chỉ muốn thêm câu trả lời này cho những người tin rằng nó an toàn Alterhơn DropCreate. Dưới đây sẽ AlterFunctionnếu nó tồn tại hoặc Createnếu nó không:

  IF NOT EXISTS (SELECT *
               FROM   sys.objects
               WHERE  object_id = OBJECT_ID(N'[dbo].[foo]')
                      AND type IN ( N'FN', N'IF', N'TF', N'FS', N'FT' ))
       EXEC('CREATE FUNCTION [dbo].[foo]() RETURNS INT AS BEGIN RETURN 0 END')
  GO
  ALTER FUNCTION [dbo].[foo]
  AS
  ...

2
Tôi thích điều này, nhưng tôi nghĩ nó nên là "THAY ĐỔI CHỨC NĂNG", phải không?
Erik

Tôi thíchALTER OR CREATE
AgentFire
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.