如何在创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的唯一对象名称,因为它没有考虑到这一点。
我希望这有帮助!
我有同样的错误。 我知道这个线程已经非常死了,但我想设置除“匿名过程”之外的另一个选项。
我解决了这个问题:
-
检查存储过程是否存在:
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
-
但是
"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 ...
-
我结束了这个代码:
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