Làm thế nào để phát hiện nếu một thủ tục được lưu trữ đã tồn tại


130

Tôi phải viết một kịch bản triển khai sẽ hoạt động nếu một thủ tục được lưu trữ tồn tại hoặc không tồn tại. tức là nếu nó tồn tại, thì tôi cần phải thay đổi nó, nếu không thì tạo nó.

Làm thế nào tôi có thể làm điều này trong sql.

Tôi đang sử dụng SQL Server 2005


Câu trả lời:


160

Nếu bạn DROP và TẠO quy trình, bạn sẽ mất các cài đặt bảo mật. Điều này có thể gây khó chịu cho DBA của bạn hoặc phá vỡ ứng dụng của bạn hoàn toàn.

Những gì tôi làm là tạo ra một thủ tục lưu trữ tầm thường nếu nó chưa tồn tại. Sau đó, bạn có thể THAY ĐỔI thủ tục được lưu trữ theo ý thích của bạn.

IF object_id('YourSp') IS NULL
    EXEC ('create procedure dbo.YourSp as select 1')
GO
ALTER PROCEDURE dbo.YourSp
AS
...

Bằng cách này, cài đặt bảo mật, nhận xét và meta Deta khác sẽ tồn tại khi triển khai.


2
Ít nhất nếu bạn thả nó, bạn biết bạn phải thêm lại các quyền. Nếu bạn chạy sql này, bạn sẽ không biết liệu sproc có quyền chính xác hay không vì bạn sẽ không biết liệu bạn đã tạo ra nó hay thay đổi nó.
Liazy

@Liazy giải pháp đơn giản là thêm mã vào if object_id('YourSp') is null BEGIN ... ENDđể thêm quyền thích hợp sau khi tạo thủ tục được lưu trữ.
sốt

4
nghĩ rằng câu trả lời khác hoàn chỉnh hơn một chút vì nó chỉ kéo id đối tượng cho các thủ tục được lưu trữ. không phổ biến để có cùng tên cho các loại khác nhau nhưng điều đó có thể xảy ra
workabyte

149

Cách sạch nhất là kiểm tra sự tồn tại của nó, thả nó nếu nó tồn tại và sau đó tạo lại nó. Bạn không thể nhúng câu lệnh "tạo Proc" bên trong câu lệnh IF. Điều này nên làm độc đáo:

IF OBJECT_ID('MySproc', 'P') IS NOT NULL
DROP PROC MySproc
GO

CREATE PROC MySproc
AS
BEGIN
    ...
END

1
Điều này sẽ hoạt động, nhưng nó loại bỏ bất kỳ thay đổi bảo mật được áp dụng cho thủ tục được lưu trữ.
Andomar

18
Thay đổi bảo mật cũng là một phần của tập lệnh. Bằng cách đó, nó sẽ được ghi lại đúng cách. Đây là cách tiếp cận đúng.
Ender Wiggin

@EnderWiggin Ngoại trừ nếu không biết triển khai bảo mật tại thời điểm thiết kế ... Điều gì xảy ra nếu nhà phát triển không biết người dùng nào cần quyền thực thi?
Adriaan Davel

2
@AdriaanDavel l đó là những gì DBA dành cho và để các DBA nói chuyện với các nhà phát triển được gọi là quản lý. Nếu các nhà phát triển và DBA không thể làm việc cùng nhau thì có vấn đề với công ty. Ngoài ra, các hệ thống được triển khai đúng cách không dựa vào đặc quyền của người dùng để chạm vào cơ sở dữ liệu, đó là tài khoản dịch vụ dành cho và bảo mật cấp dịch vụ nên được áp dụng trên toàn cơ sở dữ liệu, theo cách này, các DBA không phải mất thời gian và tiền bạc để điều chỉnh bảo mật sprocs cá nhân.
Shaun Wilson

2
Tôi sẽ không có nhà phát triển bỏ / tái tạo các sprocs thuộc về một sản phẩm thương mại. Hãy suy nghĩ về điều đó, tôi cũng sẽ không có các DBA làm điều đó. Tuy nhiên, tôi thấy những gì bạn đang nhận được, tức là "điều gì sẽ xảy ra nếu các DBA cần phải điều chỉnh bảo mật trên một triển khai hậu kỳ cho một sản phẩm thương mại". Tôi sẽ nhắc lại rằng các hệ thống được triển khai đúng cách không dựa vào đặc quyền của người dùng và bảo mật cấp dịch vụ nên được áp dụng trên toàn cơ sở dữ liệu. Tôi đã làm việc với các DBA sẽ cài đặt vào hệ thống demo / cào và sau đó thực hiện so sánh lược đồ để đảm bảo nâng cấp an toàn, IMO đây là việc họ được thuê để làm.
Shaun Wilson

31

Nếu bạn đang xử lý chỉ với các thủ tục được lưu trữ, điều dễ nhất để làm là có thể bỏ Proc, sau đó tạo lại nó. Bạn có thể tạo tất cả các mã để thực hiện việc này bằng trình hướng dẫn Tạo tập lệnh trong SQL Server.

IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[YourSproc]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[YourSproc]

CREATE PROCEDURE YourSproc...

20

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

Cú pháp:

DROP {PROC | THỦ TỤC} [NẾU EXISTS] {[lược đồ tên. ] thủ tục} [, ... n]

Truy vấn:

DROP PROCEDURE IF EXISTS usp_name

Thêm thông tin ở đây


11
if not exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[xxx]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
BEGIN
CREATE PROCEDURE dbo.xxx

nơi xxxlà tên proc


4

Ngoài những gì đã được nói, tôi cũng muốn thêm một cách tiếp cận khác và ủng hộ việc sử dụng chiến lược triển khai tập lệnh khác biệt. Thay vì tạo một tập lệnh trạng thái luôn kiểm tra trạng thái hiện tại và hành động dựa trên trạng thái đó, hãy triển khai thông qua một loạt các tập lệnh không trạng thái nâng cấp từ các phiên bản nổi tiếng . Tôi đã sử dụng chiến lược này và nó mang lại kết quả lớn vì các kịch bản triển khai của tôi giờ đây hoàn toàn miễn phí 'NẾU'.


Hấp dẫn! Trong năm năm kể từ khi bạn đăng câu trả lời này, sau đó có những phát triển hơn nữa trong phương pháp kiểm soát phiên bản cơ sở dữ liệu của bạn không?
Thomas L Holaday

4

Bạn có thể viết một truy vấn như sau:

IF OBJECT_ID('ProcedureName','P') IS NOT NULL
    DROP PROC ProcedureName
GO

CREATE PROCEDURE [dbo].[ProcedureName]
...your query here....

Để cụ thể hơn về cú pháp trên:
OBJECT_ID là số id duy nhất cho một đối tượng trong cơ sở dữ liệu, điều này được SQL Server sử dụng nội bộ. Vì chúng tôi đang truyền cho RoutureName theo sau là đối tượng P của bạn , thông báo cho SQL Server rằng bạn sẽ tìm thấy đối tượng có tên là RoutureName , thuộc loại thủ tục, tức là P

Truy vấn này sẽ tìm thủ tục và nếu có sẵn, nó sẽ bỏ nó và tạo một thủ tục mới.

Để biết thông tin chi tiết về các loại OBRI_ID và Object, vui lòng truy cập: SYS.Objects



0

Tôi có một Proc được lưu trữ cho phép khách hàng mở rộng xác nhận, nếu nó tồn tại tôi không muốn thay đổi nó, nếu tôi không muốn tạo nó, cách tốt nhất tôi đã tìm thấy:

IF OBJECT_ID('ValidateRequestPost') IS NULL
BEGIN
    EXEC ('CREATE PROCEDURE ValidateRequestPost 
    @RequestNo VARCHAR(30),
    @ErrorStates VARCHAR(255) OUTPUT
AS
BEGIN
    SELECT @ErrorStates = @ErrorStates
END')
END

2
Tôi đã không cung cấp phiếu bầu xuống, nhưng theo phỏng đoán, tôi sẽ nói rằng nó đã bị bỏ phiếu vì giải pháp này đưa ra các biến chứng mới với việc thoát các ký tự trích dẫn trong phần thân của thủ tục được lưu trữ.
donperk

0

Mã dưới đây sẽ kiểm tra xem thủ tục được lưu trữ đã tồn tại hay chưa.

Nếu nó tồn tại, nó sẽ thay đổi, nếu nó không tồn tại, nó sẽ tạo ra một thủ tục lưu trữ mới cho bạn:

//syntax for Create and Alter Proc 
DECLARE @Create NVARCHAR(200) = 'Create PROCEDURE sp_cp_test'; 
DECLARE @Alter NVARCHAR(200) ='Alter PROCEDURE sp_cp_test'; 
//Actual Procedure 
DECLARE @Proc NVARCHAR(200)= ' AS BEGIN select ''sh'' END'; 
//Checking For Sp
IF EXISTS (SELECT * 
           FROM   sysobjects 
           WHERE  id = Object_id('[dbo].[sp_cp_test]') 
                  AND Objectproperty(id, 'IsProcedure') = 1 
                  AND xtype = 'p' 
                  AND NAME = 'sp_cp_test') 
  BEGIN 
      SET @Proc=@Alter + @Proc 

      EXEC (@proc) 
  END 
ELSE 
  BEGIN 
      SET @Proc=@Create + @Proc 

      EXEC (@proc) 
  END 

go 

0

Tùy chọn tốt hơn có thể là sử dụng một công cụ như So sánh SQL cổng đỏ hoặc SQL Examiner để tự động so sánh sự khác biệt và tạo tập lệnh di chuyển.

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.