SQL Server эквивалентно Oracle CREATE OR REPLACE VIEW


115

В Oracle я могу воссоздать представление с помощью одного оператора, как показано здесь:

CREATE OR REPLACE VIEW MY_VIEW AS
SELECT SOME_FIELD
FROM SOME_TABLE
WHERE SOME_CONDITIONS

Как следует из синтаксиса, это отбросит старое представление и воссоздает его с любым определением, которое я дал.

Есть ли эквивалент в MSSQL (SQL Server 2005 или новее), который будет делать то же самое?

Ответы:


103

Приведенные выше решения, хотя они и выполнят свою работу, делают это с риском потери пользовательских разрешений. Я предпочитаю создавать или заменять представления или хранимые процедуры следующим образом.

IF NOT EXISTS (SELECT * FROM sys.views WHERE object_id = OBJECT_ID(N'[dbo].[vw_myView]'))
    EXEC sp_executesql N'CREATE VIEW [dbo].[vw_myView] AS SELECT ''This is a code stub which will be replaced by an Alter Statement'' as [code_stub]'
GO

ALTER VIEW [dbo].[vw_myView]
AS
SELECT 'This is a code which should be replaced by the real code for your view' as [real_code]
GO

2
Раньше я был человеком "Отбросить", а затем "Добавить". Но сейчас я склоняюсь к этому типу решения (добавить, если нет, то переделать).
granadaCoder

Лучше изменить вид, чем бросить и воссоздать его. Что, если у вас есть много настроек безопасности существующих пользователей для представления, вам придется воссоздать все их заново. Это мой подход к этому вопросу.
jonas

Ваши CREATE и ALTER делают разные вещи .... почему? (Один динамический, другой нет, и у них разные сообщения.)
Джей Салливан,

Мне кажется непонятным, как ваш оператор CREATE VIEW включает «замену оператором Alter» - что это означает? Мне также непонятно, какой код на самом деле нужно здесь заменить и как. Я, должно быть, один из немногих, кого смутил твой ответ.
Кайл Джуле,

2
Для SQL Server 2016 SP1 + см. Ответ lad2025.
MBWise

45

Вы можете использовать IF EXISTS, чтобы проверить, существует ли представление, и удалить его, если он существует.

ЕСЛИ СУЩЕСТВУЕТ (ВЫБЕРИТЕ ИМЯ ТАБЛИЦЫ ИЗ INFORMATION_SCHEMA.VIEWS
        ГДЕ TABLE_NAME = 'MyView')
    УДАЛИТЬ ПРОСМОТР MyView
ИДТИ

СОЗДАТЬ ПРОСМОТР MyView
ТАК КАК 
     ....
ИДТИ

13
Проблема заключается в том, что вы теряете все разрешения, которые могли существовать для объекта, который был удален.
Саймон

37

Для справки SQL Server 2016 SP1+вы можете использовать CREATE OR ALTER VIEWсинтаксис.

MSDN СОЗДАТЬ ПРОСМОТР :

CREATE [ OR ALTER ] VIEW [ schema_name . ] view_name [ (column [ ,...n ] ) ]   
[ WITH <view_attribute> [ ,...n ] ]   
AS select_statement   
[ WITH CHECK OPTION ]   
[ ; ]

ИЛИ ИЗМЕНИТЬ

Условно изменяет представление, только если оно уже существует.

db <> демо скрипта


Это синтаксис. Вы не можете использовать одновременно ключевые слова CREATE и ALTER, как в ORACLE. при такой попытке вы получите следующие ошибки. - Неправильный синтаксис рядом с ключевым словом "ИЛИ". - «CREATE / ALTER PROCEDURE» должен быть первым оператором в пакете запроса.
Div

3
@DivTiwari, очевидно, это верно в SQL 2016. По-видимому, SQL Server потребовалось всего 11 лет, чтобы догнать эту функцию оракула :)
JosephStyons

1
@JosephStyons Действительно, вы правы! Не понимаю, как они так долго упускали такую ​​важную особенность.
Div

@DivTiwari Это был выбор разработчиков: СОЗДАТЬ ИЛИ ИЗМЕНИТЬ Лучше поздно, чем никогда :)
Лукаш Шозда

14

Я использую:

IF OBJECT_ID('[dbo].[myView]') IS NOT NULL
DROP VIEW [dbo].[myView]
GO
CREATE VIEW [dbo].[myView]
AS

...

Недавно я добавил несколько служебных процедур для такого рода вещей:

CREATE PROCEDURE dbo.DropView
@ASchema VARCHAR(100),
@AView VARCHAR(100)
AS
BEGIN
  DECLARE @sql VARCHAR(1000);
  IF OBJECT_ID('[' + @ASchema + '].[' + @AView + ']') IS NOT NULL
  BEGIN
    SET @sql  = 'DROP VIEW ' + '[' + @ASchema + '].[' + @AView + '] ';
    EXEC(@sql);
  END 
END

Итак, теперь я пишу

EXEC dbo.DropView 'mySchema', 'myView'
GO
CREATE View myView
...
GO

Я думаю, это делает мои скрипты изменений более читабельными


7

Обычно я использую что-то вроде этого:

if exists (select * from dbo.sysobjects
  where id = object_id(N'dbo.MyView') and
  OBJECTPROPERTY(id, N'IsView') = 1)
drop view dbo.MyView
go
create view dbo.MyView [...]


3

У меня он отлично работает на SQL Server 2017:

USE MSSQLTipsDemo 
GO
CREATE OR ALTER PROC CreateOrAlterDemo
AS
BEGIN
SELECT TOP 10 * FROM [dbo].[CountryInfoNew]
END
GO

https://www.mssqltips.com/sqlservertip/4640/new-create-or-alter-statement-in-


Спасибо, это здорово. Я вижу, что этот синтаксис был введен в SQL 2016. Когда я писал вопрос, это было еще в SQL 2005.
JosephStyons

2

Вы можете использовать ALTER для обновления представления, но это отличается от команды Oracle, поскольку она работает, только если представление уже существует. Вероятно, лучше с ответом DaveK, поскольку он всегда будет работать.


1
Хотя ALTER сохраняет существующие разрешения (и сохраняет старую версию, если в новой версии есть синтаксические ошибки и т. Д.). Таким образом, использование IF NOT EXISTS ... для создания заглушки, а затем ALTER для его замены / оригинала может быть лучше для сохранения разрешений и зависимостей.
Кристен

1

В SQL Server 2016 (или новее) вы можете использовать это:

CREATE OR ALTER VIEW VW_NAMEOFVIEW AS ...

В более старых версиях SQL-сервера вы должны использовать что-то вроде

DECLARE @script NVARCHAR(MAX) = N'VIEW [dbo].[VW_NAMEOFVIEW] AS ...';

IF NOT EXISTS(SELECT * FROM sys.views WHERE name = 'VW_NAMEOFVIEW')
-- IF OBJECT_ID('[dbo].[VW_NAMEOFVIEW]') IS NOT NULL
BEGIN EXEC('CREATE ' + @script) END
ELSE
BEGIN EXEC('ALTER ' + @script) END

Или, если в представлении нет зависимостей, вы можете просто отбросить его и воссоздать:

IF EXISTS(SELECT * FROM sys.views WHERE name = 'VW_NAMEOFVIEW')
-- IF OBJECT_ID('[dbo].[VW_NAMEOFVIEW]') IS NOT NULL
BEGIN 
   DROP VIEW [VW_NAMEOFVIEW];
END

CREATE VIEW [VW_NAMEOFVIEW] AS ...

1
Я использую SQL Server 2016 (или новее) и не могу использовать CREATE OR REPLACE VIEWсинтаксис. Правильный синтаксис CREATE OR ALTER VIEW. Как получается, что все говорят, что это есть CREATE OR REPLACEво всех других ТАКИХ
ветках, которые

@Wolle, CREATE OR REPLACE - это синтаксис в Oracle (см. Вопрос)
Евгений Личенок,
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.