我有一个SQL脚本,每次客户端执行“数据库管理”功能时都必须运行该脚本。该脚本包括在客户端数据库上创建存储过程。其中一些客户端在运行脚本时可能已经有了存储过程,有些可能没有。我需要将缺少的存储过程添加到客户端数据库中,但是我尝试弯曲T-SQL语法并不重要,我得到了
CREATE / ALTER PROCEDURE'必须是查询批处理中的第一个语句
我在创作作品之前就已经读过了,但是我不喜欢这样做。
IF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'MyProc')
DROP PROCEDURE MyProc
GO
CREATE PROCEDURE MyProc
...
如何添加对存储过程是否存在的检查,如果它不存在则创建它,但如果它存在则更改它?
答案 0 :(得分:426)
我意识到这已被标记为已回答,但我们过去常常这样做:
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
....
只是为了避免丢弃程序。
答案 1 :(得分:163)
您可以在任何能够运行查询的位置运行过程代码。
只需复制AS
之后的所有内容:
BEGIN
DECLARE @myvar INT
SELECT *
FROM mytable
WHERE @myvar ...
END
此代码与存储过程执行的操作完全相同,但不存储在数据库端。
这与PL/SQL
中所谓的匿名程序非常相似。
<强>更新强>
你的问题标题有点令人困惑。
如果您只需要创建一个不存在的过程,那么您的代码就可以了。
以下是创建脚本中的SSMS
输出:
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 是架构。
<强>更新强>
在SQL Server 2016+中,您可以执行
CREATE OR ALTER PROCEDURE dbo.MyProc
答案 2 :(得分:112)
如果您正在寻找在删除数据库对象之前检查数据库对象的最简单方法,那么这是一种方式(示例使用SPROC,就像上面的示例一样,但可以针对表,索引等进行修改... ):
IF (OBJECT_ID('MyProcedure') IS NOT NULL)
DROP PROCEDURE MyProcedure
GO
这是快速而优雅的,但您需要确保在所有对象类型中都有唯一的对象名称,因为它没有考虑到这一点。
我希望这有帮助!
答案 3 :(得分:27)
我知道你想要修改一个程序(如果它存在的话),只有当它不存在时才删除它&#34;但我相信只是总是丢弃程序然后重新创建它更简单。以下是仅在已存在的情况下放弃该过程的方法:
IF OBJECT_ID('MyProcedure', 'P') IS NOT NULL
DROP PROCEDURE MyProcedure
GO
第二个参数告诉OBJECT_ID
仅查找object_type = 'P'
,which are stored procedures:
AF =聚合函数(CLR)
C = CHECK约束
D = DEFAULT(约束或独立)
F = FOREIGN KEY约束
FN = SQL标量函数
FS =汇编(CLR)标量函数
FT =汇编(CLR)表值函数
IF = SQL内联表值函数
IT =内部表
P = SQL存储过程
PC =汇编(CLR)存储过程
PG =计划指南
PK = PRIMARY KEY约束
R =规则(旧式,独立)
RF =复制过滤器程序
S =系统基表
SN =同义词
SO =序列对象
TF = SQL table-valued-function
您可以通过以下方式获取完整的选项列表:
SELECT name
FROM master..spt_values
WHERE type = 'O9T'
答案 4 :(得分:20)
从SQL SERVER 2016开始,您可以使用新的DROP PROCEDURE IF EXISTS
DROP { PROC | PROCEDURE } [ IF EXISTS ] { [ schema_name. ] procedure } [ ,...n ]
答案 5 :(得分:17)
我知道这是一篇非常古老的帖子,但由于它出现在热门搜索结果中,因此为使用 SQL Server 2016 SP1 的用户添加了最新更新 -
create or alter procedure procTest
as
begin
print (1)
end;
go
这会创建一个存储过程(如果尚不存在),但如果存在则会更改它。
答案 6 :(得分:7)
我有同样的错误。我知道这个帖子已经死了但我想在“匿名程序”之外设置另一个选项。
我解决了这个问题:检查存储过程是否存在:
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 ...
答案 7 :(得分:5)
这是一种以这种方式使用它的方法和一些推理。编辑存储过程并不是很好,但有利有弊......
更新:您还可以在TRANSACTION中包装整个调用。在单个事务中包含许多存储过程,可以全部提交或全部回滚。包装在事务中的另一个优点是存储过程始终存在于其他SQL连接,只要它们不使用READ UNCOMMITTED事务隔离级别即可!
1)避免改变过程决策。我们的流程总是如果EXISTS DROP THEN CREATE。如果你采用相同的模式来假设新的PROC是所需的过程,那么为改变它而烦恼是因为你有一个IF EXISTS ALTER ELSE CREATE。
2)您必须将CREATE / ALTER作为批处理中的第一个调用,因此您无法在动态SQL之外的事务中包装一系列过程更新。基本上,如果您想要运行整个过程更新堆栈或将它们全部回滚而不恢复数据库备份,这是一种在一个批处理中执行所有操作的方法。
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
答案 8 :(得分:4)
在Sql server 2008及更高版本中,您可以使用“INFORMATION_SCHEMA.ROUTINES
”
IF EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.ROUTINES
WHERE ROUTINE_NAME = 'MySP'
AND ROUTINE_TYPE = 'PROCEDURE')
答案 9 :(得分:3)
如果存在则下降 是SQL Server 2016的新功能
DROP PROCEDURE IF EXISTS dbo.[procname]
答案 10 :(得分:3)
这是我使用的脚本。有了它,我避免不必要地删除并重新创建存储过程。
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
答案 11 :(得分:3)
**在T-Sql中删除和重新创建存储过程的最简单方法是**
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
答案 12 :(得分:3)
我显然没有投票或评论所需的声誉,但我只想说Geoff使用EXEC(sp_executesql可能更好)的答案绝对是可行的方法。删除然后重新创建存储过程最终会完成工作,但是有一段时间存储过程根本不存在,这可能非常糟糕,特别是如果这将是反复运行。我的应用程序遇到了各种各样的问题,因为后台线程正在执行IF EXISTS DROP ... CREATE,同时另一个线程正在尝试使用存储过程。
答案 13 :(得分:2)
检查存储过程是否存在
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
点击以下链接http://www.gurujipoint.com/2017/05/check-if-exist-for-trigger-function-and.html
,检查IF是否存在触发功能答案 14 :(得分:1)
为什么你不像
那样简单 IF EXISTS(SELECT * FROM sys.procedures WHERE NAME LIKE 'uspBlackListGetAll')
BEGIN
DROP PROCEDURE uspBlackListGetAll
END
GO
CREATE Procedure uspBlackListGetAll
..........
答案 15 :(得分:0)
我好奇!为什么我不写
这样的整个查询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会运行查询会给出前两个程序的错误但是仍然会创建最后一个程序 SQl本身就是在处理已经存在的东西,这是我一直对所有客户所做的事情!
答案 16 :(得分:0)
除了@Geoff的答案之外,我还创建了一个简单的工具,可以生成一个SQL文件,其中包含存储过程,视图,函数和触发器的语句。
答案 17 :(得分:-2)
创建程序如果不存在&#39;您的程序名称&#39; ()BEGIN ... END