ALTER INDEX failed because of QUOTED_IDENTIFIER when running from sp_msForEachTable
Quoted identifier settings are stored against each stored procedure, and sp_MSforeachtable
has it defined as OFF
. However, you can work around this - by setting it to ON
before it executes the re-index:
create table dbo.T (
ID int not null,
constraint PK_T PRIMARY KEY (ID)
)
go
create view dbo.V ( ID)
with schemabinding
as
select ID from dbo.T
go
create unique clustered index IX_V on dbo.V(ID)
go
ALTER INDEX ALL ON dbo.V REBUILD --Fine
go
exec sp_MSforeachtable 'ALTER INDEX ALL ON ? REBUILD' --Errors
go
exec sp_MSforeachtable 'SET QUOTED_IDENTIFIER ON;
ALTER INDEX ALL ON ? REBUILD' --Fine
SET QUOTED_IDENTIFIER
:
When a stored procedure is created, the
SET QUOTED_IDENTIFIER
andSET ANSI_NULLS
settings are captured and used for subsequent invocations of that stored procedure.
And, of course, insert the usual caveats about sp_MSforeachtable
being undocumented, and so you can't rely on any of its behaviour being stable.
For DBCC DBREINDEX
- all bets are off. DBCC
lives in its own little, very customized code world. But, of course, it shouldn't be relied on for future work either:
This feature will be removed in a future version of Microsoft SQL Server. Do not use this feature in new development work, and modify applications that currently use this feature as soon as possible. Use
ALTER INDEX
instead.
You need the SET QUOTED_IDENTIFIER ON
in the sp_msForEachTable
as well, because sp_msForEachTable
does not have the right setting.
EXECUTE sp_msForEachTable 'SET QUOTED_IDENTIFIER ON; ALTER INDEX ALL ON ? REBUILD;'
Do not use sp_msforeachtable. It has been documented to miss object. You would be much better off iterating through a list of tables using sys.tables.
DECLARE @id INT ,
@table NVARCHAR(256) ,
@reindex NVARCHAR(4000)
SELECT @id = MIN(object_id)
FROM sys.tables
WHILE @id IS NOT NULL
BEGIN
SELECT @table = QUOTENAME(s.name) + '.' + QUOTENAME(t.name)
FROM sys.tables t
INNER JOIN sys.schemas s ON t.schema_id = s.schema_id
WHERE t.object_id = @id
SELECT @reindex = 'SET QUOTED IDENTIFIER ON; ALTER INDEX ALL ON '
+ @table + ' REBUILD;'
PRINT @reindex --prints the reindex command
--EXEC @reindex --uncomment to actually reindex
SELECT @id = MIN(object_id)
FROM sys.tables
WHERE object_id > @id
END
For example:
CREATE PROCEDURE dbo.sp_ForEachTable @query varchar(8000) AS
--todo