Sea*_*yth 22 sql t-sql sql-server stored-procedures
我想检查是否存在存储过程列表.我希望这一切都在一个脚本中逐一完成.到目前为止我有这种格式:
USE [myDatabase]
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'sp_1')
BEGIN
CREATE PROCEDURE sp_1
AS
.................
END
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'sp_2')
BEGIN
CREATE PROCEDURE sp_2
AS
.................
END
GO
Run Code Online (Sandbox Code Playgroud)
等等.但是,我收到以下错误:
关键字"过程"附近的语法不正确.
为什么我的工作不正常呢?
Cod*_*ian 32
CREATE PROCEDURE
必须是批次中的第一个语句.我通常做这样的事情:
IF EXISTS (
SELECT type_desc, type
FROM sys.procedures WITH(NOLOCK)
WHERE NAME = 'procname'
AND type = 'P'
)
DROP PROCEDURE dbo.procname
GO
CREATE PROC dbo.procname
AS
....
GO
GRANT EXECUTE ON dbo.MyProc TO MyUser
Run Code Online (Sandbox Code Playgroud)
(不要忘记授权语句,因为如果你重新创建你的proc,它们将会丢失)
在部署存储过程时要考虑的另一件事是丢弃可以成功并且创建失败.如果出现问题,我总是编写带有回滚的SQL脚本.只是确保你不会在最后意外删除提交/回滚代码,否则你的DBA可能会在气管中重新启动你:)
BEGIN TRAN
IF EXISTS (
SELECT type_desc, type
FROM sys.procedures WITH(NOLOCK)
WHERE NAME = 'myProc'
AND type = 'P'
)
DROP PROCEDURE myProc GO
CREATE PROCEDURE myProc
AS
--proc logic here
GO
-- BEGIN DO NOT REMOVE THIS CODE (it commits or rolls back the stored procedure drop) IF EXISTS (
SELECT 1
FROM sys.procedures WITH(NOLOCK)
WHERE NAME = 'DatasetDeleteCleanup'
AND type = 'P'
)
COMMIT TRAN
ELSE
ROLLBACK TRAN
-- END DO NOT REMOVE THIS CODE
Run Code Online (Sandbox Code Playgroud)
Ben*_*hul 23
我最近一直在使用的一个我非常喜欢的习语是:
if exists (select 1 from sys.objects where object_id = object_id('dbo.yourProc'))
set noexec on
go
create procedure dbo.yourProc as
begin
select 1 as [not yet implemented]
end
go
set noexec off
alter procedure dbo.yourProc as
begin
/*body of procedure here*/
end
Run Code Online (Sandbox Code Playgroud)
基本上,如果过程不存在,则创建存根,然后更改存根(如果刚刚创建)或预先存在的过程.关于这一点的好处是你不要删除一个删除所有权限的预先存在的过程.您也可能会在任何不存在的短暂瞬间内发生任何需要它的应用程序.
[编辑2018年2月9日] -在SQL 2016 SP1,create procedure
并drop procedure
得到了一些语法糖,随着这种事情有帮助.具体来说,您现在可以这样做:
create or alter dbo.yourProc as
go
drop procedure if exists dbo.yourProc;
Run Code Online (Sandbox Code Playgroud)
两者都在预期的语句中提供幂等性(即,您可以多次运行它并获得所需的状态).这就是我现在的做法(假设您使用的是支持它的SQL Server版本).
Ron*_*Ron 15
我知道有一个已接受的答案,但答案并没有完全解决原始问题所要求的问题,即如果不存在则创建程序.以下始终有效,并且具有不需要删除过程的好处,如果使用sql身份验证,则可能会出现问题.
USE [MyDataBase]
GO
IF OBJECT_ID('mySchema.myProc') IS NULL
EXEC('CREATE PROCEDURE mySchema.myProc AS SET NOCOUNT ON;')
GO
ALTER PROCEDURE mySchema.myProc
@DeclaredParmsGoHere DataType
AS
BEGIN
DECLARE @AnyVariablesINeed Their DataType
SELECT myColumn FROM myTable WHERE myIndex = @IndexParm
Run Code Online (Sandbox Code Playgroud)
Isk*_*der 10
2020 年 9 月更新
您可以使用CREATE OR ALTER语句(在 SQL Server 2016 SP1 中添加):
该
CREATE OR ALTER
声明的行为像一个正常CREATE
通过创建数据库对象如果数据库对象不存在和作品像一个正常的声明ALTER
语句,如果数据库对象已经存在。
小智 6
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[spGetRailItems]') AND type in (N'P', N'PC'))
BEGIN
execute ('
CREATE PROCEDURE [dbo].[spGetRailItems]
AS
BEGIN
Declare @isLiftedBagsEnable bit=1;
select @isLiftedBagsEnable=cast(DataValu as bit) from setups where scope =''Rail Setting'' and dataName = ''isLiftedBagsEnable'';
IF @isLiftedBagsEnable=1
BEGIN
IF EXISTS (SELECT * FROM ITEMCONFIG)
BEGIN
SELECT [Item],[Desc] FROM ProcData WHERE Item IN (SELECT Item FROM ItemConfig) ORDER BY [Desc]
END
ELSE
BEGIN
SELECT [Item],[Desc] FROM ProcData ORDER BY [Desc]
END
END
ELSE
BEGIN
SELECT [Item],[Desc] FROM ProcData ORDER BY [Desc]
END
END
')
END
exec spGetRailItems;
Run Code Online (Sandbox Code Playgroud)
以防万一,如果您使用的是 SQL Server 2016,那么有一个较短的版本来检查 proc 是否存在,然后删除并重新创建它
USE [DATABASENAME]
GO
DROP PROCEDURE IF EXISTS <proc name>
GO
CREATE PROCEDURE <proc name>
AS
-- your script here
END
GO
GRANT EXECUTE ON <proc name> TO <username>
Run Code Online (Sandbox Code Playgroud)
来源:https : //blogs.msdn.microsoft.com/sqlserverstorageengine/2015/11/03/drop-if-exists-new-thing-in-sql-server-2016/
归档时间: |
|
查看次数: |
44752 次 |
最近记录: |