71

CREATE OR REPLACE VIEW doesn't seem to work in SQL Server. So how do I port CREATE OR REPLACE VIEW to work on SQL Server?

This is what I'm trying to do:

CREATE OR REPLACE VIEW data_VVVV AS 
SELECT 
    VCV.xxxx,
        VCV.yyyy AS yyyy,
        VCV.zzzz AS zzzz
FROM 
TABLE_A
;

Any ideas?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Alexander Kalian
  • 1,059
  • 2
  • 9
  • 17
  • 10
    **TL;DR**: The syntax you are looking for is `CREATE OR ALTER VIEW ...` – ˈvɔlə Nov 20 '19 at 15:14
  • Looks like Wolle's comment should be the best answer, unless there's some problem with it that I haven't experienced. – Tony Guinta Oct 13 '20 at 16:48
  • 1
    Looks like this is locked for new answers, but as @WoIIe mentioned CREATE OR ALTER is you best choice since ~SQL2016 SP1. For earlier versions the complexity in the other answers has more value. https://support.microsoft.com/en-us/topic/kb3190548-update-introduces-create-or-alter-transact-sql-statement-in-sql-server-2016-fd0596f3-9098-329c-a7a5-2e18f29ad1d4 – Karl Kieninger Mar 08 '21 at 20:18

8 Answers8

89

Borrowing from @Khan's answer, I would do:

IF OBJECT_ID('dbo.test_abc_def', 'V') IS NOT NULL
    DROP VIEW dbo.test_abc_def
GO

CREATE VIEW dbo.test_abc_def AS
SELECT 
    VCV.xxxx
    ,VCV.yyyy AS yyyy
    ,VCV.zzzz AS zzzz
FROM TABLE_A

MSDN Reference

JaKXz
  • 1,665
  • 1
  • 14
  • 34
  • 2
    In Oracle, "create or replace" is atomic, so there is no downtime and you can update the view without problems even while an application wants to query the view. – Kim Sullivan Jul 23 '15 at 14:01
  • 18
    `DROP` and a following `CREATE` will drop meta data, such as granted rights. In a SQL Server where you are not the SA, this might be quite bad... – Shnugo Apr 13 '16 at 14:48
68

SQL Server 2016 Answer

With SQL Server 2016 you can now do (MSDN Source):

DROP VIEW IF EXISTS dbo.MyView

Or alternatively (MSDN Source):

CREATE OR ALTER VIEW dbo.MyView
Muhammad Rehan Saeed
  • 35,627
  • 39
  • 202
  • 311
58

Here is another method, where you don't have to duplicate the contents of the view:

IF (NOT EXISTS (SELECT 1 FROM sys.views WHERE name = 'data_VVV'))
BEGIN
    EXECUTE('CREATE VIEW data_VVVV as SELECT 1 as t');
END;

GO

ALTER VIEW data_VVVV AS 
    SELECT VCV.xxxx, VCV.yyyy AS yyyy, VCV.zzzz AS zzzz FROM TABLE_A ;

The first checks for the existence of the view (there are other ways to do this). If it doesn't exist, then create it with something simple and dumb. If it does, then just move on to the alter view statement.

Gordon Linoff
  • 1,242,037
  • 58
  • 646
  • 786
  • 3
    This doesn't seem to work. SQL Server is complaining that CREATE VIEW must be the first line in a batch of statements. The answer below that first drops the view works. – Bob Dizzle Feb 05 '15 at 20:59
  • 1
    This answer worked for me if I put `GO` statements before the `IF` and before the `ALTER VIEW` – Seafish Apr 30 '18 at 18:09
  • 3
    I've been using this approach for views/procs for years. It also maintains any special security that has been assigned to them. DROP loses that. – Isaac May 16 '19 at 17:25
  • I would change first line to `IF OBJECT_ID('dbo.data_VVVV') IS NULL` - this is shorter, simpler to read. However the logic in this answer is the right one, imo - because @Khan's answer duplicates the full view content - bad for maintenance, and @JaKXz's answer drops the view - meaning you will lose all permission settings that were assigned to it, as @Isaac said. This answer by @Gordon Linoff retains the view without duplicating the view logic and can be made simpler still with my suggestion. – youcantryreachingme Aug 21 '19 at 23:47
  • 2
    What if a view with the same name exists in a different schema? To cover that scenario maybe instead of `SELECT 1 FROM sys.views WHERE name = 'data_VVV'` use `SELECT 1 FROM INFORMATION_SCHEMA.VIEWS WHERE table_name = 'data_VVV' AND table_schema = 'dbo'` – Steve Jun 25 '20 at 22:18
  • 1
    @Steve . . . The scope of the view includes the schema, so you would want to include the schema name as well. The question didn't include a schema -- and schemas would be handled differently in Oracle -- but your point is well-taken. – Gordon Linoff Jun 26 '20 at 01:56
15

Edit: Although this question has been marked as a duplicate, it has still been getting attention. The answer provided by @JaKXz is correct and should be the accepted answer.


You'll need to check for the existence of the view. Then do a CREATE VIEW or ALTER VIEW depending on the result.

IF OBJECT_ID('dbo.data_VVVV') IS NULL
BEGIN
    CREATE VIEW dbo.data_VVVV
    AS
    SELECT VCV.xxxx, VCV.yyyy AS yyyy, VCV.zzzz AS zzzz FROM TABLE_A VCV
END
ELSE
    ALTER VIEW dbo.data_VVVV
    AS
    SELECT VCV.xxxx, VCV.yyyy AS yyyy, VCV.zzzz AS zzzz FROM TABLE_A VCV
BEGIN
END
Khan
  • 17,904
  • 5
  • 47
  • 59
  • 2
    This causes you to repeat your select statement so you really double the amount of code you have to think about. JaKXz answer below is a better approch – JustEngland Jun 03 '15 at 19:21
  • 56
    This does not work in SQL Server. `Create View` must be first in the batch and when trying to put it inside `IF`, I get `Incorrect syntax near the keyword 'VIEW'.` – trailmax Feb 24 '16 at 11:04
  • 2
    You have to wrap the CREATE statement into EXEC('your create statement'). Otherwise it won't work in IF. – Jurijs Kastanovs Jun 16 '16 at 12:29
  • 5
    Can anyone offer an answer as to why CREATE VIEW has to be the only statement in the batch but CREATE TABLE is allowed? – Stuart Oct 07 '16 at 14:25
  • 8
    Nowadays, you can just use `CREATE OR ALTER VIEW` in **SQL Server 2016+** – ˈvɔlə Nov 20 '19 at 15:15
9

The accepted solution has an issue with the need to maintain the same statement twice, it isnt very efficient (although it works). In theory Gordon Linoff's solution would be the go, except it does not work in MSSQL because create view must be the first line in a batch.

The drop/create does not answer the question as posed. The following does the job as per the original question.

if not exists (select * from sysobjects where name='TABLE_A' and xtype='V')
exec ('create view SELECT 
VCV.xxxx,
    VCV.yyyy AS yyyy,
    VCV.zzzz AS zzzz
FROM TABLE_A')
statler
  • 1,322
  • 2
  • 15
  • 24
  • That works correctly and explanation helped why I got error messages when trying to use accepted answer approach. – trailmax Feb 24 '16 at 10:58
  • 1
    Even better might be to create (in case of non-existance) a VIEW with just a `SELECT 1 AS Dummy` and let the "real" VIEW definition follow after a `GO` with `ALTER` ... – Shnugo Apr 13 '16 at 14:45
3

How about something like this, comments should explain:

--DJ - 2015-07-15 Example for view CREATE or REPLACE

--Replace with schema and view names
DECLARE @viewName NVARCHAR(30)= 'T';
DECLARE @schemaName NVARCHAR(30)= 'dbo';

--Leave this section as-is
BEGIN TRY
    DECLARE @view AS NVARCHAR(100) = '
CREATE VIEW ' + @schemaName + '.' + @viewName + ' AS SELECT '''' AS [1]';
    EXEC sp_executesql
        @view;
END TRY
BEGIN CATCH
    PRINT 'View already exists';
END CATCH;
GO

--Put full select statement here after modifying the view & schema name appropriately
ALTER VIEW [dbo].[T]
AS
    SELECT  '' AS [2];
GO


--Verify results with select statement against the view
SELECT  *
FROM    [T];

Cheers -DJ

0

Altering a view could be accomplished by dropping the view and recreating it. Use the following to drop and recreate your view.

IF EXISTS
(SELECT NAME FROM SYS.VIEWS WHERE NAME = 'dbo.test_abc_def')
DROP VIEW dbo.test_abc_def) go

CREATE VIEW dbo.test_abc_def AS
SELECT 
    VCV.xxxx, 
    VCV.yyyy AS yyyy
    ,VCV.zzzz AS zzzz
FROM TABLE_A
pix
  • 1,264
  • 19
  • 32
Bright
  • 31
  • 3
-2
IF NOT EXISTS(select * FROM sys.views where name = 'data_VVVV ')
    BEGIN
        CREATE VIEW data_VVVV AS 
        SELECT VCV.xxxx, VCV.yyyy AS yyyy, VCV.zzzz AS zzzz FROM TABLE_A VCV
    END
ELSE
    BEGIN
        ALTER VIEW data_VVVV AS 
        SELECT VCV.xxxx, VCV.yyyy AS yyyy, VCV.zzzz AS zzzz FROM TABLE_A VCV
    END
Giannis Paraskevopoulos
  • 18,261
  • 1
  • 49
  • 69
  • 1
    Also, the VCV alias is not set anywhere. – mr.Reband Aug 30 '13 at 14:12
  • Does not work in SQL Server. Copy and paste that query into SSMS, hit the Execute (or Parse) button and tell me what you get. – clamum Jun 29 '17 at 21:09
  • @clamum Can you please tell me what happens in your case? In my SSMS it works. Unless of course you are trying exactly what i have written, cause in that case if you do not have a table named `TABLE_A` then you will get an error. – Giannis Paraskevopoulos Jul 03 '17 at 12:55
  • @GiannisParaskevopoulos No, I took what you have written and pasted it into SSMS 2008 R2 and substituted your "data_VVVV" for a view that exists in my database and "xxxx/yyyy/zzzz" for fields belonging to that view. Running the "Parse" on this query gives me: Msg 156, Level 15, State 1, Line 3 Incorrect syntax near the keyword 'VIEW'. Msg 156, Level 15, State 1, Line 8 Incorrect syntax near the keyword 'VIEW'. FYI it has that red squiggly line underneath the "CREATE VIEW" and "ALTER VIEW" lines. – clamum Jul 11 '17 at 21:14
  • @clamum could you possibly paste your modified version here? – Giannis Paraskevopoulos Jul 11 '17 at 21:18