我有一个每次客户端执行“数据库管理”功能时都必须运行的 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
...
如何添加对存储过程是否存在的检查并在它不存在时创建它但如果它存在则对其进行更改?
我意识到这已经被标记为已回答,但我们曾经这样做过:
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
....
只是为了避免放弃程序。
您可以在任何可以运行查询的地方运行程序代码。
只需复制 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
@astander
:您也可以从存储过程中调用匿名代码。要在 INSERT
中使用它们的输出,您需要使用同样适用于匿名代码的 OPENROWSET
或 OPENQUERY
。当然,匿名代码也有缺点:例如,它只能在调用者的权限下运行。我的观点是这是可能的,而不是首选的做事方式:)
如果您正在寻找在删除之前检查数据库对象是否存在的最简单方法,这是一种方法(示例使用 SPROC,就像您上面的示例一样,但可以针对表、索引等进行修改...):
IF (OBJECT_ID('MyProcedure') IS NOT NULL)
DROP PROCEDURE MyProcedure
GO
这既快速又优雅,但您需要确保在所有对象类型中都有唯一的对象名称,因为它没有考虑到这一点。
我希望这有帮助!
我知道你想“如果它存在就改变一个过程,如果它不存在就创建它”,但我相信它更简单:
删除该过程(如果它已经存在),然后重新创建它。
像这样:
IF OBJECT_ID('MyProcedure', 'P') IS NOT NULL
DROP PROCEDURE MyProcedure
GO
CREATE PROCEDURE MyProcedure AS
BEGIN
/* ..... */
END
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 = 主键约束 R = 规则(旧式,独立)RF = 复制-filter-procedure S = 系统基表 SN = 同义词 SO = 序列对象 TF = SQL 表值函数 TR = 触发器
您可以通过以下方式获取完整的选项列表:
SELECT name
FROM master..spt_values
WHERE type = 'O9T'
从 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
我知道这是一篇非常古老的帖子,但由于它出现在热门搜索结果中,因此为使用 SQL Server 2016 SP1 的用户添加了最新更新 -
create or alter procedure procTest
as
begin
print (1)
end;
go
如果不存在,这将创建一个存储过程,但如果存在则更改它。
DROP IF EXISTS 是 SQL Server 2016 的新功能
DROP PROCEDURE IF EXISTS dbo.[procname]
我有同样的错误。我知道这个线程几乎已经死了,但我想设置除“匿名程序”之外的另一个选项。
我是这样解决的:
检查存储过程是否存在: IF NOT EXISTS (SELECT * FROM sysobjects WHERE name='my_procedure') BEGIN print 'exists' -- 或者你想要的水 END ELSE BEGIN print 'doesn''texists' -- 或者你想要的水 END但是,“CREATE/ALTER PROCEDURE”必须是查询批处理中的第一条语句”仍然存在。我这样解决它: SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE -- 查看过程函数或任何你想要的......我最终得到这个代码: IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID('my_procedure ')) BEGIN DROP PROCEDURE my_procedure END SET ANSI_NULLS ON SET QUOTED_IDENTIFIER ON GO CREATE PROCEDURE [dbo].my_procedure ...
这是一种方法以及以这种方式使用它的一些原因。编辑存储过程并不那么漂亮,但有利也有弊......
更新:您还可以将整个调用包装在 TRANSACTION 中。在单个事务中包含许多可以全部提交或全部回滚的存储过程。包装在事务中的另一个优点是存储过程总是存在于其他 SQL 连接中,只要它们不使用 READ UNCOMMITTED 事务隔离级别!
1) 避免将更改作为流程决策。我们的流程始终是“如果存在则删除然后创建”。如果您采用相同的模式假设新的 PROC 是所需的 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
在 Sql server 2008 及更高版本中,您可以使用“INFORMATION_SCHEMA.ROUTINES
”
IF EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.ROUTINES
WHERE ROUTINE_NAME = 'MySP'
AND ROUTINE_TYPE = 'PROCEDURE')
**在 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
这是我使用的脚本。有了它,我避免了不必要的删除和重新创建存储的过程。
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
你为什么不走简单的路
IF EXISTS(SELECT * FROM sys.procedures WHERE NAME LIKE 'uspBlackListGetAll')
BEGIN
DROP PROCEDURE uspBlackListGetAll
END
GO
CREATE Procedure uspBlackListGetAll
…………
%
,因此 LIKE
表现为 =
除了来自 @Geoff 的答案之外,我还创建了一个简单的工具,它生成一个 SQL 文件,其中包含存储过程、视图、函数和触发器的语句。
https://i.stack.imgur.com/7rInr.png
我想知道!为什么我不写整个查询
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 本身会处理已经存在的内容这是我一直对我所有的人所做的客户!
CREATE Procedure IF NOT EXISTS 'Your proc-name' () BEGIN ... END
GRANT
语句以防它们发生变化;所以仍然有理由使用DROP
而不是ALTER
。SET NOCOUNT ON
是临时存储过程体的好选择?此处询问:stackoverflow.com/questions/40849374/…