【问题标题】:create several views in same batch in SQL在 SQL 中在同一批次中创建多个视图
【发布时间】:2017-12-14 17:35:49
【问题描述】:

我尝试运行一个为特定数据库的每个表创建视图的脚本。 我找到了这个链接: How to create view for all tables in database?

显然,为了工作,我需要添加“GO”语句和回车。所以这就是我所做的

DECLARE @SQL NVARCHAR(MAX)
SET @SQL = ''

SELECT
    @SQL = @SQL+
    N'CREATE VIEW [v2_' + t.name + N'] AS SELECT ' + 
        STUFF(
            (SELECT N',' + c.name
               FROM
                  sys.columns AS c
               WHERE 
                 c.OBJECT_ID = t.OBJECT_ID
               ORDER BY
                 column_id
               FOR XML PATH(''), TYPE).value('.',N'nvarchar(max)')
        ,1,1,N'')
        + N' FROM [' + t.name + N'] [\r\n]go[\r\n]'

FROM
    sys.tables AS t
WHERE
    t.schema_id ='1'

SET @SQL = REPLACE(@SQL,'[\r\n]',CHAR(13)+CHAR(10))
PRINT @SQL

EXECUTE (@SQL)

所以打印结果是我所期望的:

CREATE VIEW ***** AS SELECT Parent_Path,id,a2ea,userLabel,DATE,HEURE,REF_EQT,COMMANDE_REF,LOG FROM ***** 
go
CREATE VIEW ***** AS SELECT AlarmIdentifier,Class,Category,Time,ObjectOfReference,AlarmText,DATE,HEURE,REF_EQT,SS_EQT,Carte_EQT,COMMANDE_REF,LOG FROM ***** 
go
CREATE VIEW ***** AS SELECT CELL,MCC,MNC,LAC,CID,BSC,CO,EA,RO,NCS,DATE,HEURE,REF_EQT,SS_EQT,Carte_EQT,COMMANDE_REF,LOG FROM ***** 
go
CREATE VIEW ***** AS SELECT RNC,RNCID,R1,R2,GLCNID,RNCCODEC,TB,DATE,HEURE,REF_EQT,SS_EQT,Carte_EQT,COMMANDE_REF,LOG FROM ***** 
go
CREATE VIEW ***** AS SELECT MGG,MG,RESTRICTED,DEFAULT,MISC,MGP,WF,DATE,HEURE,REF_EQT,SS_EQT,Carte_EQT,COMMANDE_REF,LOG FROM [NRGGP] 
go
CREATE VIEW ***** AS SELECT SNT,SNTV,SNTP,DIP,DEV,DEVP,SNTINL,EQLEV,PROT,SDIP,SUBSNT,DEFPST,EXTP,MG,DATE,HEURE,REF_EQT,COMMANDE_REF,LOG FROM *****
go
CREATE VIEW ***** AS SELECT RefreshLog_Id,Date,Etat,DateTransfert,Transfert FROM ***** 
go

但 exec 行返回:

消息 156,级别 15,状态 1,程序 *****,第 3 行 [批处理开始第 0 行]
关键字“CREATE”附近的语法不正确。

消息 111,级别 15,状态 1,程序 *****,第 3 行 [批处理开始第 0 行]
“CREATE VIEW”必须是查询批处理中的第一条语句。

消息 111,级别 15,状态 1,程序 *****,第 5 行 [批处理开始第 0 行]
“CREATE VIEW”必须是查询批处理中的第一条语句。

消息 111,级别 15,状态 1,过程 *****,第 7 行 [批处理开始行 0]

我应该创建一个架构吗?我的问题有什么解决办法吗?

非常感谢

【问题讨论】:

  • 这是一个光标可以真正帮助您的地方。这将使遍历所有表并一次只执行一个CREATE VIEW 变得更容易,而无需使用回车等跳过箍。此外,如果您总是包含每个,为什么不直接使用SELECT * FROM blah场有什么办法吗?最后,为什么不直接使用DECLARE @GO NVARCHAR(MAX) = CHAR(13)+CHAR(10)+'GO'+CHAR(13)+CHAR(10);,然后将@GO 附加到每个语句的末尾?
  • 另外,您的名称可能太长。尝试SELECT length, COUNT(*) FROM (SELECT LEN(name) length FROM sys.tables WHERE schema_id = 1) name_lengths GROUP BY length ORDER BY length; 看看您是否有任何表名已经达到最大名称长度? (截至 2008 年为 128 个,此后为 256 个。)
  • @MatBailie :非常感谢您的建议,首先,我认为问题不在于长度。关于“Go”的好主意;)我会尝试使用光标,我不太了解它们,但我会检查如何在 Google 上使用它们;)
  • go 不是 T-SQL 命令。这是一个客户端工具命令,它指示客户端工具将一大块文本拆分成单独的批次以提交给SQL Server。在 SQL Server 中运行代码后,就不再涉及客户端工具了。
  • 感谢您的信息,但我找到了解决方案:)

标签: sql tsql view create-view


【解决方案1】:

使用 cursor 和 EXECUTE sp_executesql 似乎可以工作

DECLARE @SQL NVARCHAR(MAX)
       , @table_id INT
SET @SQL = ''

DECLARE CUR CURSOR LOCAL FAST_FORWARD FOR
SELECT t.object_id FROM sys.tables AS t
WHERE t.schema_id ='1'

OPEN CUR

FETCH NEXT FROM cur INTO @table_id
WHILE @@FETCH_STATUS = 0
BEGIN

    SELECT @SQL = N'CREATE VIEW [v2_' + t.name + N'] AS SELECT ' + 
            STUFF(
                (SELECT N',' + c.name
                   FROM
                      sys.columns AS c
                   WHERE 
                     c.OBJECT_ID = t.OBJECT_ID
                   ORDER BY
                     column_id
                   FOR XML PATH(''), TYPE).value('.',N'nvarchar(max)')
            ,1,1,N'')
            + N' FROM [' + t.name + N'];'
    FROM
        sys.tables AS t
    WHERE t.object_id = @table_id 

    PRINT @SQL
    --EXECUTE sp_executesql @SQL
    FETCH NEXT FROM cur INTO @table_id
END

CLOSE CUR

DEALLOCATE CUR

【讨论】:

  • 我已经尝试过使用分号 (;) 但它也不起作用。我会用光标试试:)
【解决方案2】:

好的,所以最后我按照你们的建议做了,我创建了一个光标,它可以工作。谢谢。

DECLARE @TableName as NVARCHAR(50)
DECLARE @TableCursor as CURSOR

SET @TableCursor = CURSOR FOR
SELECT TABLE_NAME 
FROM INFORMATION_SCHEMA.TABLES 
WHERE TABLE_TYPE='BASE TABLE' and TABLE_SCHEMA = 'dbo';

OPEN @TableCursor;

FETCH NEXT FROM @TableCursor INTO @TableName;

While @@FETCH_STATUS = 0

BEGIN
    EXEC ('create view '+ @TableName+'_V2 
    as select * from ' +@TableName +';')
    FETCH NEXT FROM @TableCursor INTO @TableName;
END

CLOSE @TableCursor
DEALLOCATE @TableCursor 

【讨论】:

  • 小心选择 *,如果您在表格中间添加一列,您的视图可能会返回错误的列
  • 查看同义词,它们可能比使用带有 select * 的视图更好。 link
【解决方案3】:

你应该使用这样的语法:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE VIEW [schema].[viewname] AS
SELECT * FROM schema.table

GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE VIEW [schema].[viewname] AS
SELECT * FROM schema.table

GO

例如:

SELECT 
'SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE VIEW ' + TABLE_SCHEMA + '.' + TABLE_NAME + ' AS 
SELECT * FROM ' + TABLE_SCHEMA + '.' + TABLE_NAME + ' 

GO 
'
FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE'

不要忘记将结果输出为文本格式(在 SQL server Mgmt studio 中为 CTRL + T。),因为它会保留回车。

对于这种情况,您可以生成一个脚本来检查 SQL Server 如何处理您的脚本。 只需右键单击您的数据库、任务、生成脚本并跟随助手。它会在 SQL Server 等待它时向您输出一个文件。

【讨论】:

    猜你喜欢
    • 2020-03-14
    • 1970-01-01
    • 2013-06-23
    • 1970-01-01
    • 2012-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多