我有一个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
...
如何添加检查存储过程是否存在,如果存储过程不存在则创建它,如果存储过程存在则修改它?
您可以在任何能够运行查询的地方运行过程代码。
复制AS后面的所有内容:
BEGIN
DECLARE @myvar INT
SELECT *
FROM mytable
WHERE @myvar ...
END
这段代码所做的事情与存储的proc完全相同,但是没有存储在数据库端。
这很像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+中,您可以这样做
创建或修改过程dbo。MyProc
这里有一个方法和一些使用它的理由。编辑存储的proc并不是很漂亮,但是有利有弊……
更新:您还可以将整个调用包装在一个TRANSACTION中。在单个事务中包含多个存储过程,这些存储过程可以全部提交或全部回滚。在事务中封装的另一个优点是,只要其他SQL连接不使用READ UNCOMMITTED事务隔离级别,存储过程就始终存在!
1)避免将变更作为流程决策。我们的过程总是IF存在,然后创建。如果您执行相同的模式,假设新的PROC是所需的PROC,那么满足alters就有点困难,因为您将拥有If EXISTS ALTER ELSE CREATE。
2)你必须把CREATE/ALTER作为批处理中的第一个调用,这样你就不能在动态SQL之外的事务中包装一系列过程更新。基本上,如果您想运行整个过程更新堆栈或在不恢复DB备份的情况下将它们全部回滚,这是一种在单个批处理中完成所有工作的方法。
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
我想知道!为什么我不写整个查询像这样
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本身是照顾什么是已经存在的,这是我总是做我的客户端!
我知道你想“修改一个存在的过程,创建一个不存在的过程”,但我相信这样更简单:
删除该过程(如果它已经存在),然后
重新创建它。
是这样的:
IF OBJECT_ID('MyProcedure', 'P') IS NOT NULL
DROP PROCEDURE MyProcedure
GO
CREATE PROCEDURE MyProcedure AS
BEGIN
/* ..... */
END
GO
第二个参数告诉OBJECT_ID只查找object_type = 'P'的对象,这些对象是存储过程:
AF = Aggregate function (CLR)
C = CHECK constraint
D = DEFAULT (constraint or stand-alone)
F = FOREIGN KEY constraint
FN = SQL scalar function
FS = Assembly (CLR) scalar-function
FT = Assembly (CLR) table-valued function
IF = SQL inline table-valued function
IT = Internal table
P = SQL Stored Procedure
PC = Assembly (CLR) stored-procedure
PG = Plan guide
PK = PRIMARY KEY constraint
R = Rule (old-style, stand-alone)
RF = Replication-filter-procedure
S = System base table
SN = Synonym
SO = Sequence object
TF = SQL table-valued-function
TR = Trigger
你可以通过以下途径获得完整的选项列表:
SELECT name
FROM master..spt_values
WHERE type = 'O9T'