如何在创build之前检查存储过程是否存在

每次客户端执行“数据库pipe理”function时,都必须运行一个SQL脚本。 该脚本包括在客户端数据库上创build存储过程。 这些客户端中的一些在运行脚本时可能已经具有存储过程,而另一些则可能不具有。 我需要将缺less的存储过程添加到客户端数据库中,但是我试图弯曲T-SQL语法的次数并不重要

CREATE / ALTER PROCEDURE'必须是查询批处理中的第一条语句

我在创作作品之前已经读过,但我不喜欢这样做。

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

如何添加检查存储过程的存在,并创build它,如果它不存在但改变它,如果它存在?

您可以在任何能够运行查询的地方运行程序代码。

AS之后复制所有内容:

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

这段代码和存储过程完全一样,但不存储在数据库端。

这很像在PL/SQL所谓的匿名过程。

更新:

你的问题标题有点混乱。

如果你只需要创build一个程序,如果它不存在,那么你的代码就好了。

这是SSMS在创build脚本中输出的内容:

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

更新:

包含模式时如何实现的示例:

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

在上面的例子中, dbo是模式。

我意识到这已经被标记为回答,但我们曾经这样做:

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

只是为了避免丢弃程序。

如果你正在寻找最简单的方法来检查一个数据库对象的存在之前,删除它,这里有一种方法(例如使用SPROC,就像上面的例子,但可以修改表,索引等):

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

这是快速和优雅的,但你需要确保你有所有对象types的唯一对象名称,因为它没有考虑到这一点。

我希望这有帮助!

我有同样的错误。 我知道这个线程已经非常死了,但我想设置除“匿名过程”之外的另一个选项。

我解决了这个问题:

  1. 检查存储过程是否存在:

     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. 但是"CREATE/ALTER PROCEDURE' must be the first statement in a query batch"仍然存在。 我解决了这个问题:

     SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE -- view procedure function or anything you want ... 
  3. 我结束了这个代码:

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

从SQL SERVER 2016起,您可以使用新的DROP PROCEDURE IF EXISTS
DROP { PROC | PROCEDURE } [ IF EXISTS ] { [ schema_name. ] procedure } [ ,...n ]

参考: https : //msdn.microsoft.com/en-us/library/ms174969.aspx

这里有一个方法和使用它的背后的一些推理。 编辑存储过程并不是很好,但是有利有弊。

更新:你也可以把这个整个调用包装在一个TRANSACTION中。 在单个事务中包含许多存储过程,可以全部提交或全部回滚。 包装在事务中的另一个优点是只要不使用READ UNCOMMITTED事务隔离级别,存储过程总是存在于其他SQL连接中!

1)避免改变只是一个过程决定。 我们的过程总是如果存在,那么创build。 如果你假设新PROC是相同的模式,那么迎合更改就更困难了,因为你将会有一个IF EXTERS ALTER ELSE CREATE。

2)您必须将CREATE / ALTER作为批处理中的第一个调用,所以您不能在dynamicSQL之外的事务中包装一系列过程更新。 基本上,如果你想运行一整套过程更新,或者不用恢复数据库备份,就可以在单个批处理中完成所有操作。

 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 

我显然没有投票或评论所需的声望,但我只是想说,杰夫的答案使用EXEC(sp_executesql可能会更好)是绝对要走的路。 删除然后重新创build存储过程最终完成了工作,但是存在一个存储过程根本不存在的时刻,这可能是非常糟糕的,特别是如果这将是反复运行。 我有我的应用程序的各种问题,因为后台线程正在做一个IF EXISTS DROP …同时创build另一个线程试图使用存储过程。

**在T-Sql中删除和重新创build存储过程最简单的方法是**

 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 

我知道这是一个非常古老的post,但是因为这出现在顶级search结果中,因此为那些使用SQL Server 2016 SP1的用户添加了最新的更新 –

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

这将创build一个存储过程(如果尚不存在),但如果存在则更改它。

参考

我知道你想“改变一个过程,如果它存在,只删除它,如果它不存在”,但我相信只是总是删除过程,然后重新创build它更简单。 只有在程序已经存在的情况下,

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

第二个参数告诉OBJECT_ID只查找object_type = 'P' , 它们是存储过程:

AF =聚合函数(CLR)

C = CHECK约束

D = DEFAULT(约束或独立)

F = FOREIGN KEY约束

FN = SQL标量函数

FS =汇编(CLR)标量函数

FT = Assembly(CLR)表值函数

IF = SQL内联表值函数

IT =内部表

P = SQL存储过程

PC =程序集(CLR)存储过程

PG =计划指南

PK = PRIMARY KEY约束

R =规则(旧式,独立式)

RF =复制filter过程

S =系统基表

SN =同义词

SO =序列对象

TF = SQL表值函数

您可以通过以下方式获得完整的选项列表:

 SELECT name FROM master..spt_values WHERE type = 'O9T' 

你为什么不去简单的方式

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

……….

在Sql server 2008之后,你可以使用“ INFORMATION_SCHEMA.ROUTINES

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

检查存在的程序是否存在

 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 

检查IF存在触发器,function也可以通过点击下面的链接http://www.gurujipoint.com/2017/05/check-if-exist-for-trigger-function-and.html

这是添加新元素并且不想破坏现有实体时创build数据库的标准方式。

如果您需要在每次启动之前修改存储过程,那么也许可以将其文本作为纯文本存储在varchar(max)列中,然后使用sp_executesql执行。

虽然我看不出为什么ALTER PROCEDURE会比这更糟糕。

除了@Geoff的回答,我创build了一个简单的工具,它生成一个SQL文件,其中包括存储过程,视图,函数和触发器的语句。

请参阅MyDbUtils @ CodePlex 。 在这里输入图像描述

我在想! 为什么我不写整个查询

 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 

我已经知道,前两个程序已经存在sql将运行查询将给出前两个程序的错误,但它仍然会创build最后一个程序SQl本身正在处理已经存在的东西这是我一直对我所有客户!

这是我使用的脚本。 有了它,我可以避免不必要的丢弃和重新创build存储的特效。

 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 

创build过程如果不存在'你的proc-name'()BEGIN … END