Sql server 在IF部分内创建过程

Sql server 在IF部分内创建过程,sql-server,tsql,Sql Server,Tsql,我需要一些关于简单SQL代码的帮助: DECLARE @procExists int SET @procExists = (SELECT COUNT(*) FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_SCHEMA = 'dbo' AND ROUTINE_NAME = 'Table_Exists' AND ROUTINE_TYPE = 'PROCEDURE') IF NOT @procExists > 0 BEGIN -- test

我需要一些关于简单SQL代码的帮助:

DECLARE @procExists int
SET @procExists = (SELECT COUNT(*) FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_SCHEMA = 'dbo' AND ROUTINE_NAME = 'Table_Exists' AND ROUTINE_TYPE = 'PROCEDURE')
IF NOT @procExists > 0 
BEGIN
    -- test query
    -- SELECT 'Something' = @procExists;

    -- error throwing code
    -- CREATE PROCEDURE Table_Exists
    --     @schemaName varchar(50),
    --     @tableName varchar(50)
    -- AS
    --     RETURN (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = @schemaName AND TABLE_NAME = @tableName)
END
上面的简单代码:
-声明一个int变量
-检查过程dbo.Table_是否存在
-如果不存在,则创建它

我的问题是此错误信息:

Msg 156, Level 15, State 1, Line 9
Incorrect syntax near the keyword 'PROCEDURE'.
Msg 137, Level 15, State 2, Line 13
Must declare the scalar variable "@schemaName".
我不知道为什么,但是..
-当我单独执行“CREATE PROCEDURE”body时,它会工作
-当我执行不包括“创建过程”主体的整个IF部分时,简单查询工作
-当我执行包含“创建过程”主体的整个IF节时,抛出错误

我错过了什么?

来自:

CREATE PROCEDURE语句不能在单个批处理中与其他Transact-SQL语句组合


因此,除非您能够通过动态查询来实现它,否则您试图做的是不可能的。

创建过程必须在它自己的批处理中

因此,动态SQL是一种方法:

IF OBJECT_ID('Table_Exists') IS NULL
BEGIN
    EXEC ('CREATE PROCEDURE Table_Exists
         @schemaName varchar(50),
         @tableName varchar(50)
     AS
         RETURN (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = @schemaName AND TABLE_NAME = @tableName)
')
END
还是先放下

IF OBJECT_ID('Table_Exists') IS NOT NULL
  DROP PROC Table_Exists
GO
CREATE PROCEDURE Table_Exists
         @schemaName varchar(50),
         @tableName varchar(50)
     AS
         RETURN (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = @schemaName AND TABLE_NAME = @tableName)
GO

请注意使用OBJECT_ID查看进程是否存在。

您可以使用
将NOEXEC设置为ON
来执行此操作。这将指示SQL Server忽略所有SQL代码,直到达到
SET NOEXEC OFF

IF EXISTS (SELECT *
          FROM INFORMATION_SCHEMA.ROUTINES
          WHERE ROUTINE_TYPE = 'PROCEDURE'
          AND ROUTINE_SCHEMA = 'dbo'
          AND ROUTINE_NAME = 'HelloWorld')
BEGIN
    SET NOEXEC ON
END
GO

CREATE PROCEDURE dbo.HelloWorld
AS
    PRINT 'Hello world'
GO

SET NOEXEC OFF
GO

嗯。。我应该选择使用对象ID检查还是通过信息模式检查?我在某个地方读到过,使用信息模式更好。@dygi:我总是使用对象ID,但这取决于你。在其他RDBMS中,您可以使用
CREATE或REPLACE
,或者
CREATE(如果不存在的话)
,所以不要再担心“可移植性”了。此修改是否正确且安全:OBJECT_ID(db_name()+N'.dbo.Table_Exists',N'P')@dygi:yes,但您不能使用
CREATE PROC db_name()+'.dbo.Table_Exists
,因此您必须已经处于正确的数据库上下文中。您不能在动态SQL中使用CREATE PROC…明白。非常感谢。这是干净的。我喜欢它。
if OBJECT_ID('PROC1') IS NULL  
   EXEC('CREATE PROCEDURE DBO.PROC1 AS SELECT 1')

GO

ALTER PROCEDURE DBO.PROC1(@PARAM1 INT, @PARAM2 INT)

AS