So erkennen Sie, ob bereits eine gespeicherte Prozedur vorhanden ist


130

Ich muss ein Bereitstellungsskript schreiben, das funktioniert, wenn eine gespeicherte Prozedur vorhanden ist oder nicht. dh wenn es existiert, muss ich es ändern, sonst erstelle ich es.

Wie kann ich das in der SQL tun.

Ich verwende SQL Server 2005


Antworten:


160

Wenn Sie die Prozedur fallen lassen und erstellen, verlieren Sie die Sicherheitseinstellungen. Dies kann Ihren DBA stören oder Ihre Anwendung insgesamt beschädigen.

Ich erstelle eine triviale gespeicherte Prozedur, wenn sie noch nicht existiert. Danach können Sie die gespeicherte Prozedur nach Ihren Wünschen ÄNDERN.

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

Auf diese Weise überleben Sicherheitseinstellungen, Kommentare und andere Meta-Details die Bereitstellung.


2
Zumindest wenn Sie es löschen, wissen Sie, dass Sie die Berechtigungen erneut hinzufügen müssen. Wenn Sie diese SQL ausführen würden, würden Sie nicht wissen, ob der Sproc die richtigen Berechtigungen hat oder nicht, da Sie nicht wissen würden, ob Sie ihn erstellt oder geändert haben.
Liazy

@Liazy die einfache Lösung besteht darin, Code hinzuzufügen if object_id('YourSp') is null BEGIN ... END, um die richtigen Berechtigungen nach dem Erstellen der gespeicherten Prozedur hinzuzufügen.
Salue

4
Ich denke, die andere Antwort ist etwas vollständiger, da nur die Objekt-ID für gespeicherte Prozeduren abgerufen wird. Es ist nicht üblich, den gleichen Namen für verschiedene Typen zu haben, aber es könnte passieren
Workabyte

148

Am saubersten ist es, die Existenz zu testen, sie zu löschen, falls vorhanden, und sie dann neu zu erstellen. Sie können eine "create proc" -Anweisung nicht in eine IF-Anweisung einbetten. Das sollte gut gehen:

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

CREATE PROC MySproc
AS
BEGIN
    ...
END

1
Dies funktioniert, entfernt jedoch alle Sicherheitsänderungen, die an der gespeicherten Prozedur vorgenommen wurden.
Andomar

18
Sicherheitsänderungen sollten auch Teil von Skripten sein. Auf diese Weise wird es ordnungsgemäß dokumentiert. Dies ist der richtige Ansatz.
Ender Wiggin

@EnderWiggin Außer wenn die Sicherheitsimplementierung zur Entwurfszeit nicht bekannt ist ... Was ist, wenn der Entwickler nicht weiß, welche Benutzer Ausführungsrechte benötigen?
Adriaan Davel

2
@AdriaanDavel l Dafür sind DBAs gedacht, und DBAs dazu zu bringen, mit Entwicklern zu sprechen, wird als Management bezeichnet. Wenn Entwickler und Datenbankadministratoren nicht zusammenarbeiten können, liegt ein Problem mit dem Unternehmen vor. Außerdem sind ordnungsgemäß implementierte Systeme nicht auf Benutzerrechte angewiesen, um eine Datenbank zu berühren. Dafür sind Dienstkonten vorgesehen, und die Sicherheit auf Serviceebene sollte datenbankweit anwendbar sein. Auf diese Weise müssen Datenbankadministratoren keine Zeit und Geld für die Optimierung der Sicherheit aufwenden einzelne Sprocs.
Shaun Wilson

2
Ich hätte keine Entwickler, die Sprocs, die zu einem kommerziellen Produkt gehörten, fallen ließen / neu erstellten. Kommen Sie und denken Sie darüber nach, ich hätte auch keine DBAs, die das tun. Ich sehe jedoch, worauf Sie hinaus wollen, dh "was ist, wenn Datenbankadministratoren die Sicherheit eines Sproc-Post-Deployments für ein kommerzielles Produkt optimieren müssen". Ich werde wiederholen, dass ordnungsgemäß implementierte Systeme nicht auf Benutzerberechtigungen beruhen und dass die Sicherheit auf Serviceebene datenbankweit angewendet werden sollte. Ich habe mit DBAs gearbeitet, die auf einem Demo / Scratch-System installiert werden, und dann einen Schema-Vergleich durchgeführt, um sicherzustellen, dass ein Upgrade sicher ist. IMO ist dies, wofür sie beauftragt sind.
Shaun Wilson

31

Wenn Sie nur mit gespeicherten Prozeduren arbeiten, ist es am einfachsten, den Prozess wahrscheinlich zu löschen und dann neu zu erstellen. Sie können den gesamten Code dazu mithilfe des Assistenten zum Generieren von Skripten in SQL Server generieren.

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

Von können SQL Server 2016 CTP3Sie neue DIE- Anweisungen anstelle von großen IFWrappern verwenden

Syntax:

DROP {PROC | VERFAHREN} [WENN EXISTIERT] {[Schemaname. ] Prozedur} [, ... n]

Abfrage:

DROP PROCEDURE IF EXISTS usp_name

Mehr Infos hier


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

Wo xxxist der Proc-Name?


4

Zusätzlich zu dem, was bereits gesagt wurde, möchte ich auch einen anderen Ansatz hinzufügen und die Verwendung einer differenziellen Skriptbereitstellungsstrategie befürworten. Anstatt ein statusbehaftetes Skript zu erstellen, das immer den aktuellen Status überprüft und basierend auf diesem Status handelt, stellen Sie es über eine Reihe zustandsloser Skripts bereit, die von bekannten Versionen aktualisiert werden . Ich habe diese Strategie angewendet und sie zahlt sich aus, da meine Bereitstellungsskripte jetzt alle "IF" -frei sind.


Interessant! Wurden in den fünf Jahren, seit Sie diese Antwort veröffentlicht haben, Ihre Methoden zur Versionskontrolle Ihrer Datenbank weiterentwickelt?
Thomas L Holaday

4

Sie können eine Abfrage wie folgt schreiben:

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

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

Um die obige Syntax genauer zu beschreiben:
OBJECT_ID ist eine eindeutige ID-Nummer für ein Objekt in der Datenbank, die intern von SQL Server verwendet wird. Da wir ProcedureName gefolgt von Ihrem Objekttyp P übergeben , teilt dies dem SQL Server mit, dass Sie das Objekt ProcedureName finden sollen, das vom Typ procedure ist, dh P.

Diese Abfrage findet die Prozedur und wenn sie verfügbar ist, wird sie gelöscht und eine neue erstellt.

Ausführliche Informationen zu OBJECT_ID und Objekttypen finden Sie unter: SYS.Objects



0

Ich habe einen gespeicherten Prozess, mit dem der Kunde die Validierung erweitern kann. Wenn er vorhanden ist, möchte ich ihn nicht ändern. Wenn er nicht erstellt werden soll, habe ich den besten Weg gefunden:

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
Ich habe die Abwärtsabstimmung nicht bereitgestellt, aber ich würde sagen, dass sie herabgestimmt wurde, da diese Lösung neue Komplikationen mit dem Entkommen von Anführungszeichen im Hauptteil der gespeicherten Prozedur mit sich bringt.
Donperk

0

Der folgende Code prüft, ob die gespeicherte Prozedur bereits vorhanden ist oder nicht.

Wenn es existiert, ändert es sich, wenn es nicht existiert, erstellt es eine neue gespeicherte Prozedur für Sie:

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

Eine bessere Option könnte darin bestehen, ein Tool wie Red-Gate SQL Compare oder SQL Examiner zu verwenden, um die Unterschiede automatisch zu vergleichen und ein Migrationsskript zu generieren.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.