Jak wykryć, czy procedura składowana już istnieje

Odpowiedzi:

161

Jeśli upuścisz i utworzysz procedurę, utracisz ustawienia zabezpieczeń. Może to zdenerwować administratora lub całkowicie zepsuć aplikację.

Tworzę trywialną procedurę składowaną, jeśli jeszcze nie istnieje. Następnie możesz ZMIENIĆ procedurę składowaną według własnych upodobań.

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

W ten sposób ustawienia bezpieczeństwa, komentarze i inne meta deta przetrwają wdrożenie.

Andomar
źródło
2
Przynajmniej jeśli go upuścisz, wiesz, że musisz ponownie dodać uprawnienia. Gdybyś uruchomił ten sql, nie wiedziałbyś, czy sproc ma odpowiednie uprawnienia, czy nie, ponieważ nie wiedziałbyś, czy go utworzyłeś, czy zmieniłeś.
Liazy,
@Liazy proste rozwiązanie polega na dodaniu kodu w if object_id('YourSp') is null BEGIN ... ENDcelu dodania odpowiednich uprawnień po utworzeniu procedury składowanej.
saluce
4
Myślę, że druga odpowiedź jest trochę bardziej kompletna, ponieważ pobiera tylko identyfikator obiektu dla procedur składowanych. nie jest powszechne, aby mieć tę samą nazwę dla różnych typów, ale może się zdarzyć
workabyte
149

Najczystszym sposobem jest sprawdzenie jego istnienia, porzucenie go, jeśli istnieje, a następnie odtworzenie go. Nie możesz osadzić instrukcji „create proc” wewnątrz instrukcji IF. To powinno ładnie wystarczyć:

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

CREATE PROC MySproc
AS
BEGIN
    ...
END
Aaron Alton
źródło
1
To zadziała, ale usunie wszelkie zmiany zabezpieczeń zastosowane do procedury składowanej.
Andomar
18
Zmiany bezpieczeństwa również powinny być częścią skryptów. W ten sposób zostanie odpowiednio udokumentowany. To jest właściwe podejście.
Ender Wiggin
@EnderWiggin Z wyjątkiem sytuacji, gdy implementacja zabezpieczeń nie jest znana w czasie projektowania ... Co zrobić, jeśli programista nie wie, którzy użytkownicy potrzebują uprawnień do wykonywania?
Adriaan Davel
2
@AdriaanDavel l Po to są administratorzy baz danych, a zachęcanie ich do rozmowy z programistami nazywa się zarządzaniem. Jeśli programiści i administratorzy baz danych nie mogą współpracować, pojawia się problem z firmą. Poza tym prawidłowo wdrożone systemy nie polegają na uprawnieniach użytkownika do dotykania bazy danych, do tego służą konta usług, a zabezpieczenia na poziomie usług powinny mieć zastosowanie w całej bazie danych, w ten sposób administratorzy baz danych nie muszą tracić czasu i pieniędzy na ulepszanie zabezpieczeń poszczególne sprocesy.
Shaun Wilson
2
Nie pozwoliłbym programistom upuszczać / odtwarzać sprocesów należących do komercyjnego produktu. Pomyśl o tym, nie chciałbym też, żeby DBA to robili. Rozumiem jednak, do czego zmierzasz, tj. „Co by było, gdyby administratorzy baz danych musieli poprawić zabezpieczenia po wdrożeniu sproc dla produktu komercyjnego”. Powtórzę, że prawidłowo zaimplementowane systemy nie opierają się na uprawnieniach użytkowników i że zabezpieczenia na poziomie usług powinny być stosowane w całej bazie danych. Pracowałem z administratorami baz danych, którzy zainstalują się w systemie demo / scratch, a następnie porównają schematy, aby upewnić się, że aktualizacja jest bezpieczna. IMO to jest to, do czego zostali zatrudnieni.
Shaun Wilson
31

Jeśli masz do czynienia tylko z procedurami składowanymi, najłatwiejszą rzeczą do zrobienia jest prawdopodobnie porzucenie procesu, a następnie jego ponowne utworzenie. Możesz wygenerować cały kod, aby to zrobić, używając kreatora Generuj skrypty w 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
źródło
21

Od SQL Server 2016 CTP3można korzystać z nowych Die oświadczenia zamiast dużych IFowijarki

Składnia:

DROP {PROC | PROCEDURA} [JEŚLI ISTNIEJE] {[nazwa_schematu. ] procedura} [, ... n]

Pytanie:

DROP PROCEDURE IF EXISTS usp_name

Więcej informacji tutaj

P ரதீப்
źródło
12
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

gdzie xxxjest nazwa proc

Luke Schafer
źródło
5

Możesz napisać zapytanie w następujący sposób:

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

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

Aby być bardziej szczegółowym w powyższej składni:
OBJECT_ID to unikalny numer identyfikacyjny obiektu w bazie danych, używany wewnętrznie przez SQL Server. Ponieważ przekazujemy nazwę procedury, a następnie typ obiektu P, który mówi SQL Server, że należy znaleźć obiekt o nazwie nazwa_procedury, który jest typu procedura, tj. P

To zapytanie znajdzie procedurę i jeśli jest dostępna, porzuci ją i utworzy nową.

Aby uzyskać szczegółowe informacje na temat OBJECT_ID i typów obiektów, odwiedź: SYS.Objects

shary.sharath
źródło
4

Oprócz tego, co już zostało powiedziane, chciałbym również dodać inne podejście i zalecać stosowanie strategii wdrażania skryptów różnicowych. Zamiast tworzyć skrypt pełnostanowy, który zawsze sprawdza bieżący stan i działa w oparciu o ten stan, należy wdrożyć serię skryptów bezstanowych, które aktualizują dobrze znane wersje . Użyłem tej strategii i bardzo się opłaca, ponieważ moje skrypty wdrożeniowe są teraz wszystkie wolne od „IF”.

Remus Rusanu
źródło
Ciekawy! Czy w ciągu pięciu lat od opublikowania tej odpowiedzi nastąpił dalszy rozwój metod kontroli wersji bazy danych?
Thomas L Holaday,
3
IF OBJECT_ID('SPNAME') IS NULL
     -- Does Not Exists
ELSE
     -- Exists
Hemanshu Bhojak
źródło
0

Mam przechowywany proces, który pozwala klientowi przedłużyć walidację, jeśli istnieje, nie chcę go zmieniać, jeśli nie, chcę go utworzyć, najlepszy sposób, jaki znalazłem:

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
źródło
2
Nie zapewniłem głosowania „w dół”, ale zgaduję, że głosowano „w dół”, ponieważ to rozwiązanie wprowadza nowe komplikacje związane ze znakami cudzysłowu w treści procedury składowanej.
donperk
0

Poniższy kod sprawdzi, czy procedura składowana już istnieje, czy nie.

Jeśli istnieje, ulegnie zmianie, jeśli nie istnieje, utworzy nową procedurę składowaną:

//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
źródło
0

Lepszą opcją może być użycie narzędzia takiego jak Red-Gate SQL Compare lub SQL Examiner, aby automatycznie porównać różnice i wygenerować skrypt migracji.

Kane
źródło