J'ai un script SQL qui doit être exécuté à chaque fois qu'un client exécute la fonctionnalité "gestion de base de données". Le script inclut la création de procédures stockées sur la base de données client. Certains de ces clients peuvent déjà avoir la procédure stockée lors de l'exécution du script, et d'autres non. J'ai besoin que les procédures stockées manquantes soient ajoutées à la base de données du client, mais peu importe combien j'essaie de modifier la syntaxe T-SQL
CREATE/ALTER PROCEDURE 'doit être la première instruction d'un lot de requêtes
J'ai lu cette chute avant de créer des œuvres, mais je n'aime pas le faire de cette façon.
IF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'MyProc')
DROP PROCEDURE MyProc
GO
CREATE PROCEDURE MyProc
...
Comment puis-je ajouter un contrôle pour l'existence d'une procédure stockée et le créer s'il n'existe pas, mais le modifier s'il existe?
Vous pouvez exécuter du code de procédure partout où vous pouvez exécuter une requête.
Il suffit de tout copier après AS
:
BEGIN
DECLARE @myvar INT
SELECT *
FROM mytable
WHERE @myvar ...
END
Ce code fait exactement la même chose qu'un processus stocké ferait, mais n'est pas stocké du côté base de données.
Cela ressemble beaucoup à ce qu'on appelle la procédure anonyme dans PL/SQL
.
Mettre à jour:
Le titre de votre question est un peu déroutant.
Si vous n'avez besoin de créer une procédure que si elle n'existe pas, votre code suffit.
Voici ce que SSMS
génère dans le script de création:
IF EXISTS ( SELECT *
FROM sys.objects
WHERE object_id = OBJECT_ID(N'myproc')
AND type IN ( N'P', N'PC' ) )
DROP …
CREATE …
Mettre à jour:
Exemple de procédure à suivre pour inclure le schéma:
IF EXISTS ( SELECT *
FROM sysobjects
WHERE id = object_id(N'[dbo].[MyProc]')
and OBJECTPROPERTY(id, N'IsProcedure') = 1 )
BEGIN
DROP PROCEDURE [dbo].[MyProc]
END
Dans l'exemple ci-dessus, dbo est le schéma.
Mettre à jour:
Dans SQL Server 2016+, vous pouvez simplement faire
CREATE OR ALTER PROCEDURE dbo.MyProc
Je réalise que cela a déjà été marqué comme réponse, mais nous le faisions comme ceci:
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
....
Juste pour éviter de laisser tomber la procédure.
Si vous recherchez le moyen le plus simple de vérifier l'existence d'un objet de base de données avant de le supprimer, voici un moyen (l'exemple utilise un SPROC, tout comme votre exemple ci-dessus mais peut être modifié pour les tables, les index, etc.):
IF (OBJECT_ID('MyProcedure') IS NOT NULL)
DROP PROCEDURE MyProcedure
GO
Ceci est rapide et élégant, mais vous devez vous assurer que vous avez des noms d’objet uniques pour tous les types d’objets, car cela n’en tient pas compte.
J'espère que ça aide!
Je sais que vous souhaitez "modifier une procédure si elle existe et ne la supprimer que si elle n'existe pas", mais je pense qu'il est plus simple de simplement supprimer la procédure, puis de la recréer. Voici comment supprimer la procédure uniquement si elle existe déjà:
IF OBJECT_ID('MyProcedure', 'P') IS NOT NULL
DROP PROCEDURE MyProcedure
GO
Le deuxième paramètre indique à OBJECT_ID
de ne rechercher que les objets avec object_type = 'P'
, qui sont des procédures stockées:
AF = fonction d'agrégation (CLR)
C = contrainte de vérification
D = DEFAULT (contrainte ou autonome)
F = contrainte de clé étrangère
FN = fonction scalaire SQL
FS = fonction scalaire d'assemblage (CLR)
FT = fonction table de valeur d'assemblage (CLR)
IF = fonction de table inline SQL
IT = table interne
P = Procédure stockée SQL
PC = Assembly (CLR) procédure stockée
PG = guide de plan
PK = contrainte PRIMARY KEY
R = règle (ancien style, autonome)
RF = procédure de filtrage de réplication
S = table de base du système
SN = synonyme
SO = objet séquence
TF = fonction de table SQL
Vous pouvez obtenir la liste complète des options via:
SELECT name
FROM master..spt_values
WHERE type = 'O9T'
À partir de SQL SERVER 2016, vous pouvez utiliser le nouveau DROP PROCEDURE IF EXISTS
.DROP { PROC | PROCEDURE } [ IF EXISTS ] { [ schema_name. ] procedure } [ ,...n ]
Référence: https://msdn.Microsoft.com/en-us/library/ms174969.aspx
Je sais que c'est un très vieux message, mais puisque cela apparaît dans les premiers résultats de la recherche, nous avons donc ajouté la dernière mise à jour pour ceux qui utilisent SQL Server 2016 SP1 -
create or alter procedure procTest
as
begin
print (1)
end;
go
Cela crée une procédure stockée si elle n’existe pas déjà, mais la modifie si elle existe.
J'ai eu la même erreur. Je sais que ce fil est déjà pratiquement mort mais je souhaite définir une autre option en plus de "procédure anonyme".
Je l'ai résolu comme ça:
Vérifiez si la procédure stockée existe:
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
Cependant, le "CREATE/ALTER PROCEDURE' must be the first statement in a query batch"
est toujours là. Je l'ai résolu comme ça:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE -- view procedure function or anything you want ...
Je me retrouve avec ce 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 ...
Voici une méthode et un raisonnement derrière l’utiliser de cette façon. Ce n'est pas aussi joli d'éditer le proc stocké mais il y a des avantages et des inconvénients ...
UPDATE: Vous pouvez également envelopper tout cet appel dans une TRANSACTION. Inclure plusieurs procédures stockées dans une seule transaction pouvant toutes être validées ou annulées. Un autre avantage du wrapping dans une transaction est que la procédure stockée existe toujours pour les autres connexions SQL tant qu'elles n'utilisent pas le niveau d'isolement de la transaction READ UNCOMMITTED!
1) Pour éviter les modifications comme une décision de processus. Nos processus sont à toujours SI EXISTE DROP ALORS CRÉER. Si vous procédez de la même manière en supposant que le nouveau PROC est le proc souhaité, la restauration des modifications est un peu plus difficile, car vous auriez un IF EXISTS ALTER ELSE CREATE.
2) Vous devez mettre CREATE/ALTER en tant que premier appel d'un lot afin de ne pas encapsuler une séquence de mises à jour de procédures dans une transaction en dehors du SQL dynamique. En gros, si vous souhaitez exécuter une pile complète de mises à jour de procédures ou les restaurer toutes sans restaurer une sauvegarde de base de données, vous pouvez tout faire en un seul lot.
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
À partir de Sql Server 2008, vous pouvez utiliser "INFORMATION_SCHEMA.ROUTINES
"
IF EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.ROUTINES
WHERE ROUTINE_NAME = 'MySP'
AND ROUTINE_TYPE = 'PROCEDURE')
Je n'ai apparemment pas la réputation requise pour voter ou commenter, mais je voulais juste dire que la réponse de Geoff en utilisant EXEC (sp_executesql pourrait être meilleure) est certainement la voie à suivre. Si vous abandonnez puis recréez la procédure stockée, le travail est fini, mais il existe un moment où la procédure stockée n’existe pas du tout, et cela peut être très grave, surtout si cela se produit courir à plusieurs reprises. J'avais toutes sortes de problèmes avec mon application car un thread d'arrière-plan exécutait IF EXISTS DROP ... CREATE en même temps qu'un autre thread essayait d'utiliser la procédure stockée.
Voici le script que j'utilise. Avec cela, j'évite de perdre et de recréer inutilement les procs stockés.
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
** Le moyen le plus simple de supprimer et de recréer un processus stocké dans T-Sql est **
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
Vérifier si la procédure stockée existe
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
Cochez SI existe pour le déclencheur, Fonction également en cliquant sur le lien ci-dessous http://www.gurujipoint.com 2017/05/check-if-exist-for-trigger-function-and.html
DROP IF EXISTS Est une nouvelle fonctionnalité de SQL Server 2016
DROP PROCEDURE IF EXISTS dbo.[procname]
pourquoi tu ne vas pas comme ça
IF EXISTS(SELECT * FROM sys.procedures WHERE NAME LIKE 'uspBlackListGetAll')
BEGIN
DROP PROCEDURE uspBlackListGetAll
END
GO
CREATE Procedure uspBlackListGetAll
..........
Je me demande! Pourquoi je n'écris pas toute la requête comme
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
je sais déjà que les deux premières procédures existent déjà. SQL exécutera la requête donnera l'erreur des deux premières procédures mais créera la dernière procédure. à tous mes clients!
En plus de la réponse de @ Geoff j'ai créé un outil simple qui génère un fichier SQL contenant des instructions pour les procédures stockées, les vues, les fonctions et les déclencheurs.
Voir MyDbUtils @ CodePlex .