SQL:无法在块内创建SP

时间:2016-10-19 23:09:24

标签: sql-server tsql stored-procedures scripting

如果表尚不存在,我试图运行一些SQL查询,具体来说:

  1. 创建表格。
  2. 添加一些数据。
  3. 创建存储过程以访问数据。
  4. 步骤1和2工作正常,但是当我尝试执行第三部分时,我收到错误。这是我的代码(不需要仔细阅读 - 这里作为参考,跳到下面的问题区域):

    USE [MyDB]
    GO
    
    
    IF NOT EXISTS (SELECT * FROM sysobjects WHERE name='fooTable' and xtype='U')
        BEGIN
            CREATE TABLE fooTable
            (
                ID INT NOT NULL IDENTITY(1,1),
                SomeNumber INT NOT NULL, 
                SomeOtherTable_ID INT NOT NULL, 
                PRIMARY KEY (ID),
                FOREIGN KEY (SomeOtherTable_ID) REFERENCES SomeOtherTable(SomeOtherTable_ID)
            );
    
            INSERT INTO fooTable (SomeNumber, SomeOtherTable_ID)
            VALUES (5, 1), (10, 1), (25, 1), (50, 1), (100, 1), (500, 1)
    
            CREATE PROCEDURE myProcedureName
            AS
            SELECT SomeNumber from [fooTable]
        END 
    

    相关的故障线是第三个,它在if语句的外部工作正常:

    CREATE PROCEDURE myProcedureName
    AS
    SELECT SomeNumber from [fooTable]
    

    但如果我尝试在if块中运行它,SELECT会用以下内容加下划线红色:

      

    SELECT附近的语法不正确。期待外在。

    如何在if块中运行存储过程?如果它是相关的,这是在使用T-SQL的SQL Server中。

3 个答案:

答案 0 :(得分:5)

存储过程,触发器,函数和其他几种对象类型需要在它们自己的批处理中。通过将IF语句包装在CREATE中,可以在EXEC(N'....')块内实现此目的:

IF (OBJECT_ID(N'dbo.footTable') IS NULL)
BEGIN
   CREATE TABLE dbo.[fooTable]
   (
      ID INT NOT NULL IDENTITY(1, 1)
           CONSTRAINT [PK_fooTable] PRIMARY KEY,
      SomeNumber INT NOT NULL, 
      SomeOtherTable_ID INT NOT NULL
           CONSTRAINT [FK_fooTable_SomeOtherTable] FOREIGN KEY
           REFERENCES dbo.SomeOtherTable(SomeOtherTable_ID)
   );

   INSERT INTO dbo.fooTable (SomeNumber, SomeOtherTable_ID)
   VALUES (5, 1), (10, 1), (25, 1), (50, 1), (100, 1), (500, 1);

   EXEC(N'
        CREATE PROCEDURE dbo.myProcedureName
        AS
        SELECT SomeNumber FROM [fooTable];
   ');
END;

注意:

  • 请确保在包含动态SQL的字符串文字中包含大写 - N前缀(作为最佳做法 - 是的,没有它经常有效,但让它始终有效)。

  • 请勿使用已弃用的兼容性视图,例如sysobjects。从SQL Server 2005的发布开始,正确的系统目录视图位于sys模式中。在这种情况下,它将是sys.objects

  • 您应该对对象进行架构限定:dbo.fooTable而不仅仅是fooTable

  • 您应该命名您的约束:PK,FK等

答案 1 :(得分:1)

CREATE PROCEDURE需要在自己的块中。将其移出并执行以下操作:

CREATE TABLE `grid` (
  `id` int(10) unsigned NOT NULL,
  `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `customers_id` int(10) unsigned NOT NULL,
  `x` int(11) NOT NULL,
  `y` int(11) NOT NULL,
  `seen` timestamp NULL DEFAULT NULL
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

答案 2 :(得分:0)

我喜欢以下习语:

if object_id('dbo.yourProc') is not null --object exists
   set noexec on;
go
create procedure dbo.yourProc as
begin
   select 'not implemented' as [message]
end
go
set noexec off;
go
alter procedure dbo.yourProc as
begin
   «actual definition here»
end
go

我喜欢这个是保留程序中已存在的任何权限并且是幂等的。