我正在尝试从存储过程中创建一个视图,并且很难看到来自非常类似方法的两个相反的结果。
示例1
CREATE PROCEDURE cv AS
GO
DECLARE @sql nvarchar(MAX)
SET @sql = 'CREATE VIEW test AS SELECT * FROM someOtherTable'
exec (@sql)
虽然此示例在第一次创建过程后创建视图,但在以后使用以下步骤执行过程时,它不会重新创建视图:
EXEC cv
示例2
CREATE PROCEDURE cv
@table SYSNAME
AS
DECLARE @sql nvarchar(MAX)
SET @sql = 'CREATE VIEW '+ @table +' AS SELECT * FROM someOtherTable'
这个过程在第一次创建过程时不创建视图,但每次调用后都会创建视图:
EXEC @sql;
为什么会这样?我认为这真的令人困惑,没有意义或是这样吗?
答案 0 :(得分:3)
第1次陈述
CREATE PROCEDURE cv AS
GO --<-- This GO here terminates the batch
DECLARE @sql nvarchar(MAX)
SET @sql = 'CREATE VIEW test AS SELECT * FROM someOtherTable'
exec (@sql)
GO
批处理终结器创建过程并立即执行以下语句。因此,您可以创建一个为您创建视图的过程。
事实上,这两个批次是两个陈述。
- BATCH 1
CREATE PROCEDURE cv AS
GO
- BATCH 2
DECLARE @sql nvarchar(MAX)
SET @sql = 'CREATE VIEW test AS SELECT * FROM someOtherTable'
exec (@sql)
批处理1创建一个内部没有任何内容的过程,但它为您创建一个过程对象,根本没有功能/定义。
单独执行关键字GO
后的语句并为您创建视图。
我的建议
在创建对象之前,请务必检查对象是否存在。我会写这样的程序..
CREATE PROCEDURE cv
AS
BEGIN
SET NOCOUNT ON;
IF OBJECT_ID ('test', 'V') IS NOT NULL
BEGIN
DROP VIEW test
END
DECLARE @sql nvarchar(MAX)
SET @sql = 'CREATE VIEW test AS SELECT * FROM someOtherTable'
exec (@sql)
END
答案 1 :(得分:0)
在示例1中 - 您正在创建一个带有硬编码测试名称的视图。在proc的后续运行中,由于视图已经存在,SQL Server将抛出一个错误,因为您正在尝试创建一个与已存在的视图同名的视图。
在示例2中,您将视图的名称作为参数传递。这将始终创建一个新视图,除非您传入的@table值对应于现有视图。
只是想知道 - 为什么要使用存储过程创建视图?这不是您通常在SQL中执行的操作。
答案 2 :(得分:0)
您需要更改
EXEC @sql
致EXEC (sql)
EXEC可用于运行存储过程,而不是动态sql
例如
declare @dd varchar(100)='Select ''A'''
exec (@dd) ->will work fine
exec @dd -> Error
答案 3 :(得分:0)
创建视图语句不能与存储过程一起使用
答案 4 :(得分:0)
EXEC ('CREATE VIEW ViewName AS SELECT * FROM OPENQUERY(Yourservername,''EXECUTE [databasename].[dbo].[sp_name] ''''' +Parameter + ''''''')')