How do I switch off SCHEMABINDING
for a view without recreating it?
5 Answers
Yes. It's good that you use SCHEMABINDING (we do always) and sometimes you have to remove it to change a dependent object. Just ALTER the view
ALTER VIEW myView
--Remove this WITH SCHEMABINDING
AS
SELECT ...
GO
-
so did I, but sometimes other objects (functions, views) depend on this one. So it will be good to mark /unmark this flag for a time :). So it is impossible in the current version of db, yes?– garikMar 28, 2011 at 16:43
-
@garik: correct, I have the same problem. Run ALTER on each dependent object... At any point in time SQL Server will enforce the rules: you can't "switch off" because this would lead to inconsistency– gbnMar 28, 2011 at 16:45
After looking around for hours, I created 2 stored proc for this. Hope this helps someone
CREATE PROCEDURE ViewRemoveSchemaBinding
@ViewName VARCHAR(MAX)
AS
BEGIN
DECLARE @PositionShemaBinding INT
DECLARE @Command NVARCHAR(MAX)
SELECT @Command = OBJECT_DEFINITION(OBJECT_ID(@ViewName));
SET @PositionShemaBinding = CHARINDEX('WITH SCHEMABINDING', @Command)
IF NOT @PositionShemaBinding = 0 BEGIN
-- WITH SCHEMA BINDING IS PRESENT... Let's remove it !
SET @Command = STUFF(@Command, CHARINDEX('WITH SCHEMABINDING', @Command), LEN('WITH SCHEMABINDING'), '');
SET @Command = REPLACE(@Command, 'CREATE VIEW', 'ALTER VIEW');
EXECUTE sp_executesql @Command
END
END
And to put the SCHEMABINDING :
CREATE PROCEDURE ViewAddSchemaBinding
@ViewName VARCHAR(MAX)
AS
BEGIN
DECLARE @PositionShemaBinding INT
DECLARE @Command NVARCHAR(MAX)
DECLARE @ObjectName VARCHAR(MAX)
SELECT @Command = OBJECT_DEFINITION(OBJECT_ID(@ViewName)),
@ObjectName = OBJECT_NAME(OBJECT_ID(@ViewName));
SET @PositionShemaBinding = PATINDEX('%WITH SCHEMABINDING%', @Command)
IF @PositionShemaBinding = 0 BEGIN
-- WITH SCHEMA BINDING IS NOT PRESENT... Let's add it !
SET @Command = REPLACE(@Command, 'CREATE VIEW', 'ALTER VIEW');
-- IF OBJECT NAME IS INTO BRAKETS, We need to handle it
IF NOT CHARINDEX('[' + @ObjectName + ']', @Command) = 0 BEGIN
SET @ObjectName = '[' + @ObjectName + ']'
END
SET @Command = STUFF(@Command, CHARINDEX(@ObjectName, @Command), LEN(@ObjectName), @ObjectName + ' WITH SCHEMABINDING ');
EXECUTE sp_executesql @Command
END
END
It is provided "as is"...
Won't ALTER VIEW allow for you to get this done? When you create a view you would do:
CREATE VIEW
WITH SCHEMABINDING
AS
SELECT stmt
GO
so, lose the WITH clause:
ALTER VIEW viewname
AS
SELECT stmt
GO
-
1"Won't ALTER VIEW allow for you to get this done?" - it requires you to re-supply the definition of the
VIEW
which is a big hassle - ideally we'd be able to run justALTER VIEW WITH ( SCHEMABINDING = ON|OFF );
without re-supplying theSELECT...
part.– DaiAug 10, 2022 at 17:57
This version of ViewRemoveSchemaBinding works even if the view has been renamed since it was created. (The problem is that if the view has been renamed, OBJECT_DEFINITION() will still return a definition using the old name.)
CREATE PROCEDURE [dbo].[ViewRemoveSchemaBinding]
@ViewName VARCHAR(MAX)
AS
BEGIN
DECLARE @PositionShemaBinding INT
DECLARE @Command NVARCHAR(MAX)
SELECT @Command = OBJECT_DEFINITION(OBJECT_ID(@ViewName));
SET @PositionShemaBinding = CHARINDEX('WITH SCHEMABINDING', @Command)
IF NOT @PositionShemaBinding = 0 BEGIN
SET @Command = 'ALTER VIEW ' + @ViewName + ' ' + RIGHT(@Command, LEN(@Command) - @PositionShemaBinding + 1);
EXECUTE sp_executesql @Command
END
END
It seems that after running this the renaming issue goes away, and so ViewAddSchemaBinding doesn't need to be altered....
-
1This doesn't work, as the command still contains 'WITH SCHEMABINDING' - to fix it, change the usage of
RIGHT
to:RIGHT(@Command, LEN(@Command) - (@PositionShemaBinding + LEN('WITH SCHEMABINDING')))
Jan 23, 2019 at 10:45
You might want to do something like..
@Command = REPLACE(@Command,'WITH SCHEMABINDING','-- WITH SCHEMABINDING')
This would allow you to scan the --WITH SCHEMABINDING
to reinstate the schemabinding after the object was altered.