it-swarm.com.de

Wie Sie prüfen, ob eine gespeicherte Prozedur vorhanden ist, bevor Sie sie erstellen?

Ich habe ein SQL-Skript, das jedes Mal ausgeführt werden muss, wenn ein Client die Funktionalität "Datenbankverwaltung" ausführt. Das Skript umfasst das Erstellen gespeicherter Prozeduren in der Clientdatenbank. Einige dieser Clients verfügen möglicherweise bereits über die gespeicherte Prozedur, während das Skript ausgeführt wird, andere nicht. Ich muss die fehlenden gespeicherten Prozeduren zur Client-Datenbank hinzugefügt haben, aber es ist egal, wie viel ich versuche, die T-SQL-Syntax zu verbiegen

CREATE/ALTER PROCEDURE 'muss die erste Anweisung in einem Query-Batch sein

Ich habe das lesen vor dem Erstellen von Werken gelesen, aber ich mag es nicht so.

IF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'MyProc')
DROP PROCEDURE MyProc
GO

CREATE PROCEDURE MyProc
...

Wie kann ich hinzufügen, ob eine gespeicherte Prozedur vorhanden ist, und sie erstellen, wenn sie nicht existiert, sie aber ändern, wenn sie existiert?

228
The Shaper

Sie können Verfahrenscode überall ausführen, wo Sie eine Abfrage ausführen können.

Kopieren Sie einfach alles nach AS:

BEGIN
    DECLARE @myvar INT
    SELECT  *
    FROM    mytable
    WHERE   @myvar ...
END

Dieser Code hat genau die gleichen Funktionen wie eine gespeicherte Prozedur, wird jedoch nicht auf der Datenbankseite gespeichert.

Das ist ähnlich wie in anonymen Prozeduren in PL/SQL.

Update:

Ihr Fragetitel ist etwas verwirrend.

Wenn Sie eine Prozedur nur erstellen müssen, wenn sie nicht existiert, ist Ihr Code in Ordnung.

Folgendes gibt SSMS im Erstellungsskript aus:

IF EXISTS ( SELECT  *
            FROM    sys.objects
            WHERE   object_id = OBJECT_ID(N'myproc')
                    AND type IN ( N'P', N'PC' ) ) 
DROP …
CREATE …

Update:

Beispiel für die Verwendung des Schemas:

IF EXISTS ( SELECT * 
            FROM   sysobjects 
            WHERE  id = object_id(N'[dbo].[MyProc]') 
                   and OBJECTPROPERTY(id, N'IsProcedure') = 1 )
BEGIN
    DROP PROCEDURE [dbo].[MyProc]
END

Im obigen Beispiel ist dbo das Schema.

Update:

In SQL Server 2016 und höher können Sie dies einfach tun

CREATE OR ALTER PROCEDURE dbo.MyProc

154
Quassnoi

Mir ist klar, dass dies bereits als beantwortet markiert wurde, aber wir haben das so gemacht:

IF NOT EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND OBJECT_ID = OBJECT_ID('dbo.MyProc'))
   exec('CREATE PROCEDURE [dbo].[MyProc] AS BEGIN SET NOCOUNT ON; END')
GO

ALTER PROCEDURE [dbo].[MyProc] 
AS
  ....

Nur um zu vermeiden, dass das Verfahren abgebrochen wird.

408
Geoff

Wenn Sie nach der einfachsten Methode suchen, um das Vorhandensein eines Datenbankobjekts zu prüfen, bevor Sie es entfernen, gibt es eine Möglichkeit (Beispiel verwendet einen SPROC wie Ihr Beispiel oben, könnte aber für Tabellen, Indizes usw. geändert werden)

IF (OBJECT_ID('MyProcedure') IS NOT NULL)
  DROP PROCEDURE MyProcedure
GO

Dies ist schnell und elegant, Sie müssen jedoch sicherstellen, dass Sie eindeutige Objektnamen für alle Objekttypen haben, da dies nicht berücksichtigt wird.

Ich hoffe das hilft!

111
MrChips

Ich weiß, Sie möchten "eine Prozedur ändern, wenn sie existiert, und sie nur löschen, wenn sie nicht existiert", aber ich glaube, es ist einfacher, die Prozedur einfach immer zu löschen und dann neu zu erstellen. So löschen Sie die Prozedur nur, wenn sie bereits existiert:

IF OBJECT_ID('MyProcedure', 'P') IS NOT NULL
    DROP PROCEDURE MyProcedure
GO

Der zweite Parameter gibt an, dass OBJECT_ID nur nach Objekten mit object_type = 'P', sucht, die gespeicherte Prozeduren sind:

AF = Aggregatfunktion (CLR)

C = CHECK-Einschränkung

D = DEFAULT (Einschränkung oder eigenständig)

F = FOREIGN KEY-Einschränkung

FN = SQL-Skalarfunktion

FS = Assembly (CLR) -Skalarfunktion

FT = Assembly (CLR) -Tabellenwertfunktion

IF = Inline-Tabellenwertfunktion von SQL

IT = Interne Tabelle

P = gespeicherte SQL-Prozedur

PC = Assembly (CLR) gespeicherte Prozedur

PG = Planführer

PK = PRIMARY KEY-Einschränkung

R = Regel (altmodisch, eigenständig)

RF = Replication-Filter-Verfahren

S = Systembasistabelle

SN = Synonym

SO = Sequenzobjekt

TF = SQL-Tabellenwertfunktion

Die vollständige Liste der Optionen erhalten Sie über:

SELECT name 
FROM master..spt_values
WHERE type = 'O9T'
25
Michael Currie

Ab SQL SERVER 2016 können Sie den neuen DROP PROCEDURE IF EXISTS verwenden.
DROP { PROC | PROCEDURE } [ IF EXISTS ] { [ schema_name. ] procedure } [ ,...n ]

Referenz: https://msdn.Microsoft.com/en-us/library/ms174969.aspx

17
Hybris95

Ich weiß, dass es ein sehr alter Beitrag ist, aber da dieser in den Top-Suchergebnissen angezeigt wird, wird das neueste Update für Benutzer hinzugefügt, die SQL Server 2016 SP1 verwenden 

create or alter procedure procTest
as
begin
 print (1)
end;
go

Dadurch wird eine gespeicherte Prozedur erstellt, wenn sie noch nicht vorhanden ist. Sie wird jedoch geändert, falls vorhanden.

Referenz

12
gkb

Ich hatte den gleichen Fehler. Ich weiß, dass dieser Thread schon ziemlich tot ist, aber ich möchte neben "anonymous procedure" noch eine weitere Option einstellen.

Ich habe es so gelöst:

  1. Überprüfen Sie, ob die gespeicherte Prozedur vorhanden ist:

    IF NOT EXISTS (SELECT * FROM sysobjects WHERE name='my_procedure') BEGIN
        print 'exists'  -- or watever you want
    END ELSE BEGIN
        print 'doesn''texists'   -- or watever you want
    END
    
  2. Der "CREATE/ALTER PROCEDURE' must be the first statement in a query batch" ist jedoch immer noch da. Ich habe es so gelöst:

    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    
    CREATE -- view procedure function or anything you want ...
    
  3. Ich ende mit diesem Code:

    IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID('my_procedure'))
    BEGIN
        DROP PROCEDURE my_procedure
    END
    
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    
    CREATE PROCEDURE [dbo].my_procedure ...
    
7
Oaxas

Hier ist eine Methode und einige Gründe für die Verwendung dieser Methode. Es ist nicht so schön, das gespeicherte Proc zu bearbeiten, aber es gibt Vor- und Nachteile ...

UPDATE: Sie können den gesamten Anruf auch in eine TRANSACTION einschließen. Einschließen vieler gespeicherter Prozeduren in einer einzigen Transaktion, die alle festschreiben oder alle zurücksetzen können. Ein weiterer Vorteil des Wraps in einer Transaktion besteht darin, dass die gespeicherte Prozedur immer für andere SQL-Verbindungen vorhanden ist, sofern sie nicht die Isolationsstufe READ UNCOMMITTED verwenden.

1) Änderungen nur als Prozessentscheidung vermeiden. Unsere Prozesse sind immer WENN EXISTEN DROP DANN CREATE. Wenn Sie das gleiche Muster annehmen und annehmen, dass der neue PROC die gewünschte Prozedur ist, ist die Anpassung an Änderungen etwas schwieriger, da Sie ein WENN EXISTS ALTER ELSE CREATE hätten.

2) Sie müssen CREATE/ALTER als ersten Aufruf in einem Batch eingeben, damit Sie eine Sequenz von Prozeduraktualisierungen nicht in eine Transaktion außerhalb von Dynamic SQL einschließen können. Wenn Sie einen ganzen Stapel von Prozeduraktualisierungen ausführen oder alle zurücksetzen möchten, ohne eine DB-Sicherung wiederherzustellen, können Sie dies in einem einzigen Stapel tun.

IF NOT EXISTS (select ss.name as SchemaName, sp.name as StoredProc 
    from sys.procedures sp
    join sys.schemas ss on sp.schema_id = ss.schema_id
    where ss.name = 'dbo' and sp.name = 'MyStoredProc')
BEGIN
    DECLARE @sql NVARCHAR(MAX)

    -- Not so aesthetically pleasing part. The actual proc definition is stored
    -- in our variable and then executed.
    SELECT @sql = 'CREATE PROCEDURE [dbo].[MyStoredProc]
(
@MyParam int
)
AS
SELECT @MyParam'
    EXEC sp_executesql @sql
END
5
Shiv

Ab SQL Server 2008 können Sie "INFORMATION_SCHEMA.ROUTINES" verwenden.

IF EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.ROUTINES 
  WHERE ROUTINE_NAME = 'MySP'
        AND ROUTINE_TYPE = 'PROCEDURE') 
4

Ich habe anscheinend nicht den nötigen Ruf, um zu stimmen oder zu kommentieren, aber ich wollte nur sagen, dass Geoffs Antwort mit EXEC (sp_executesql könnte besser sein) definitiv der richtige Weg ist. Wenn Sie die gespeicherte Prozedur löschen und dann erneut erstellen, wird der Job am Ende erledigt. Es gibt jedoch einen Zeitpunkt, an dem die gespeicherte Prozedur überhaupt nicht vorhanden ist. Dies kann sehr schlecht sein, insbesondere wenn dies der Fall ist wiederholt laufen. Ich hatte alle möglichen Probleme mit meiner Anwendung, da ein Hintergrund-Thread gleichzeitig IF EXISTS DROP ... CREATE ausführte, als ein anderer Thread versuchte, die gespeicherte Prozedur zu verwenden.

3
James

Hier ist das Skript, das ich verwende. Damit vermeide ich, dass die gespeicherten Procs unnötig gelöscht und wiederhergestellt werden.

IF NOT EXISTS (
    SELECT *
    FROM sys.objects
    WHERE object_id = OBJECT_ID(N'[dbo].[uspMyProcedure]')
    )
BEGIN
  EXEC sp_executesql N'CREATE PROCEDURE [dbo].[uspMyProcedure] AS select 1'
END
GO

ALTER PROCEDURE [dbo].[uspMyProcedure] 
    @variable1 INTEGER  
AS
BEGIN
   -- Stored procedure logic
END
3
myroslav

** Der einfachste Weg, eine gespeicherte Prozedur in T-Sql zu löschen und neu zu erstellen, ist **

Use DatabaseName
go
If Object_Id('schema.storedprocname') is not null
begin
   drop procedure schema.storedprocname
end
go

create procedure schema.storedprocname
as

begin
end
3
Rennish Joseph

Prüfen Sie, ob für gespeicherte Prozedur vorhanden ist

IF EXISTS (SELECT * FROM sys.objects 
            WHERE object_id = OBJECT_ID
             (N'[Schema].[Procedure_Name]') AND type IN (N'P', N'PC'))
BEGIN
       DROP PROCEDURE [Schema].[Procedure_Name]
       Print('Proceudre dropped => [Schema].[Procedure_Name]')
END

Überprüfen Sie, ob Existiert für Trigger, Funktion auch durch Klicken auf den folgenden Link http://www.gurujipoint.com/2017/05/check-if-exist-for-trigger-function-and.html

2
Jatin Phulera

DROP IF EXISTS Ist eine neue Funktion von SQL Server 2016

https://blogs.msdn.Microsoft.com/sqlserverstorageengine/2015/11/03/drop-if-exists-new-thing-in-sql-server-2016/

DROP  PROCEDURE IF EXISTS dbo.[procname]
2
JayJay

warum gehst du nicht den einfachen Weg? 

    IF EXISTS(SELECT * FROM sys.procedures WHERE NAME LIKE 'uspBlackListGetAll')
    BEGIN
         DROP PROCEDURE uspBlackListGetAll
    END
    GO

    CREATE Procedure uspBlackListGetAll

..........

1
dnxit

Ich wundere mich! Warum schreibe ich nicht die ganze Anfrage?

GO
create procedure [dbo].[spAddNewClass] @ClassName varchar(20),@ClassFee int
as
begin
insert into tblClass values (@ClassName,@ClassFee)
end

GO
create procedure [dbo].[spAddNewSection] @SectionName varchar(20),@ClassID       int
as
begin
insert into tblSection values(@SectionName,@ClassID)
end

Go
create procedure test
as
begin 
select * from tblstudent
end

ich weiß bereits, dass die ersten beiden Prozeduren bereits vorhanden sind. SQL wird ausgeführt. Die Abfrage gibt den Fehler der ersten beiden Prozeduren aus, aber es wird immer noch die letzte Prozedur erstellt. __ an alle meine Kunden! 

0

Neben der Antwort aus @Geoff habe ich ein einfaches Tool erstellt, das eine SQL-Datei generiert, die Anweisungen für gespeicherte Prozeduren, Ansichten, Funktionen und Trigger enthält.

Siehe MyDbUtils @ CodePlex .  enter image description here

0
Stef Heyenrath