Cara mendeteksi jika prosedur tersimpan sudah ada

Jawaban:

160

Jika Anda MENGHENTIKAN dan MENCIPTAKAN prosedur, Anda akan kehilangan pengaturan keamanan. Ini bisa mengganggu DBA Anda atau menghancurkan aplikasi Anda sama sekali.

Apa yang saya lakukan adalah membuat prosedur tersimpan sepele jika belum ada. Setelah itu, Anda dapat mengubah prosedur tersimpan sesuai dengan keinginan Anda.

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

Dengan cara ini, pengaturan keamanan, komentar dan meta deta lainnya akan selamat dari penyebaran.

Andomar
sumber
2
Setidaknya jika Anda menjatuhkannya, Anda tahu Anda harus menambahkan kembali izin. Jika Anda menjalankan sql ini, Anda tidak akan tahu apakah sproc memiliki izin yang benar atau tidak karena Anda tidak akan tahu apakah Anda telah membuatnya atau mengubahnya.
Liazy
@ Liazy solusi sederhana untuk menambahkan kode di if object_id('YourSp') is null BEGIN ... ENDuntuk menambahkan izin yang tepat setelah membuat prosedur tersimpan.
bernilai
4
pikir jawaban lain sedikit lebih lengkap karena hanya menarik id objek untuk prosedur tersimpan. tidak umum untuk memiliki nama yang sama untuk berbagai jenis tetapi itu bisa terjadi
workabyte
149

Cara terbersih adalah dengan menguji keberadaannya, jatuhkan jika ada, lalu buat ulang. Anda tidak dapat menanamkan pernyataan "buat proc" di dalam pernyataan IF. Ini harus dilakukan dengan baik:

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

CREATE PROC MySproc
AS
BEGIN
    ...
END
Aaron Alton
sumber
1
Ini akan berhasil, tetapi menghapus semua perubahan keamanan yang diterapkan pada prosedur tersimpan.
Andomar
18
Perubahan keamanan harus menjadi bagian dari skrip juga. Dengan begitu, itu akan didokumentasikan dengan baik. Ini adalah pendekatan yang tepat.
Ender Wiggin
@EnderWiggin Kecuali jika implementasi keamanan tidak tahu pada waktu desain ... Bagaimana jika pengembang tidak tahu pengguna mana yang membutuhkan hak eksekusi?
Adriaan Davel
2
@AdriaanDavel l untuk itulah DBA, dan membuat DBA untuk berbicara dengan pengembang disebut manajemen. Jika pengembang dan DBA tidak dapat bekerja bersama, ada masalah dengan perusahaan. Selain itu, sistem yang diimplementasikan dengan benar tidak bergantung pada hak istimewa pengguna untuk menyentuh database, itulah gunanya akun layanan, dan keamanan tingkat layanan harus dapat diterapkan di seluruh basis data, dengan cara ini DBA tidak perlu menghabiskan waktu dan uang untuk mengutak-atik keamanan pada sprocs individu.
Shaun Wilson
2
Saya tidak akan membiarkan pengembang menjatuhkan / membuat ulang sprocs milik produk komersial. Kalau dipikir-pikir, aku juga tidak akan meminta DBA. Saya melihat apa yang Anda maksud, yaitu, "bagaimana jika DBA perlu mengutak-atik keamanan pada sproc pasca-penempatan untuk produk komersial". Saya akan menegaskan kembali bahwa sistem yang diimplementasikan dengan benar tidak bergantung pada hak pengguna dan bahwa keamanan tingkat layanan harus diterapkan di seluruh basis data. Saya telah bekerja dengan DBA yang akan menginstal ke sistem demo / awal dan kemudian melakukan skema membandingkan untuk memastikan upgrade aman, IMO ini adalah apa yang mereka disewa untuk dilakukan.
Shaun Wilson
31

Jika Anda hanya berurusan dengan prosedur tersimpan, hal yang paling mudah untuk dilakukan adalah mungkin menjatuhkan proc, lalu membuatnya kembali. Anda bisa menghasilkan semua kode untuk melakukan ini menggunakan panduan Menghasilkan Script di 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...
JasonS
sumber
20

Dari SQL Server 2016 CTP3Anda dapat menggunakan pernyataan DIE baru, bukan IFpembungkus besar

Sintaksis:

DROP {PROC | PROSEDUR} [JIKA ADA] {[schema_name. ] prosedur} [, ... n]

Pertanyaan:

DROP PROCEDURE IF EXISTS usp_name

Info lebih lanjut di sini

P ரதீப்
sumber
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

dimana xxxnama proc

Luke Schafer
sumber
4

Selain apa yang telah dikatakan, saya juga ingin menambahkan pendekatan yang berbeda dan menganjurkan penggunaan strategi penyebaran skrip diferensial. Alih-alih membuat skrip stateful yang selalu memeriksa keadaan saat ini dan bertindak berdasarkan kondisi itu, gunakan melalui serangkaian skrip stateless yang meningkatkan versi dari versi terkenal . Saya telah menggunakan strategi ini dan itu menghasilkan banyak waktu karena skrip penerapan saya sekarang semuanya 'JIKA' gratis.

Remus Rusanu
sumber
Menarik! Dalam lima tahun sejak Anda memposting jawaban ini, apakah sudah ada perkembangan lebih lanjut dalam metode kontrol versi database Anda?
Thomas L Holaday
4

Anda dapat menulis kueri sebagai berikut:

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

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

Untuk lebih spesifik pada sintaks di atas:
OBJECT_ID adalah nomor id unik untuk objek dalam database, ini digunakan secara internal oleh SQL Server. Karena kita melewati ProcedureName diikuti oleh Anda objek tipe P yang memberitahu SQL Server bahwa Anda harus menemukan objek yang disebut ProcedureName yang merupakan tipe prosedur yaitu, P

Kueri ini akan menemukan prosedur dan jika tersedia itu akan menjatuhkannya dan membuat yang baru.

Untuk informasi terperinci tentang OBJECT_ID dan jenis Objek, silakan kunjungi: SYS.Objects

shary.sharath
sumber
3
IF OBJECT_ID('SPNAME') IS NULL
     -- Does Not Exists
ELSE
     -- Exists
Hemanshu Bhojak
sumber
0

Saya memiliki proc tersimpan yang memungkinkan pelanggan untuk memperpanjang validasi, jika ada, saya tidak ingin mengubahnya, jika tidak saya ingin membuatnya, cara terbaik yang saya temukan:

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
Adriaan Davel
sumber
2
Saya tidak memberikan down-vote, tetapi, pada tebakan, saya akan mengatakan bahwa itu down-vote karena solusi ini memperkenalkan komplikasi baru dengan lolosnya karakter kutipan dalam tubuh prosedur tersimpan.
donperk
0

Kode di bawah ini akan memeriksa apakah prosedur yang tersimpan sudah ada atau belum.

Jika ada itu akan berubah, jika tidak ada itu akan membuat prosedur tersimpan baru untuk Anda:

//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 
shiva kumar kella
sumber
0

Pilihan yang lebih baik mungkin menggunakan alat seperti Red-Gate SQL Compare atau SQL Examiner untuk secara otomatis membandingkan perbedaan dan menghasilkan skrip migrasi.

Kane
sumber