如何使用sp_MSforeachtable为每个表添加索引?它不断出错。
EXEC sp_MSforeachtable @precommand = 'declare @idx as char;',
@command1 = '
set @idx = ''idx_'' + ? + ''_modified_on'';
print @idx;
IF EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N''[dbo].[?]'') AND name = N''@idx'')
DROP INDEX [@idx] ON [dbo].[?]
CREATE NONCLUSTERED INDEX [@idx] ON [dbo].[?]
(
[modified_on] ASC
) ON [PRIMARY]
'
一个这样的错误:
Msg 137, Level 15, State 1, Line 2
Must declare the scalar variable "@idx".
我尝试将声明放在命令中,但随后出现此错误:
Msg 4104, Level 16, State 1, Line 3
The multi-part identifier "dbo.DIAG_contractAuditHistory" could not be bound.
以下是使用测试SQL修复语法错误的更新尝试,但它仍然提供了奇怪的错误。我最终用存储过程解决了这个问题并为每个表调用了存储过程。
EXEC sp_MSforeachtable @command1 = '
declare @idx as varchar(256);
set @idx = ''idx_'' + SUBSTRING(''?'', 8, len(''?'')-8) + ''_modified_on'';
print @idx;
IF EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N''?'') AND name = @idx )
DROP INDEX [@idx] ON ?
IF EXISTS (select * from sys.columns where object_id = OBJECT_ID(N''?'') and name = ''modified_on'')
CREATE NONCLUSTERED INDEX [@idx] ON ?
(
[modified_on] ASC
) ON [PRIMARY]
'
declare @cat as char;
set @cat='dog';
print @cat;
EXEC sp_MSforeachtable 'print ''idx_'' + SUBSTRING(''?'', 8, len(''?'')-8) + ''_modified_on'';'
EXEC sp_MSforeachtable 'print ''?'''
print substring('[dbo].[merchantNotes]', 8, (len('[dbo].[merchantNotes]')-9))
select * from sys.columns where object_id = OBJECT_ID(N'[dbo].[banks]') and name = 'modified_on'
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'contractPaymentHistory') AND name = 'idx_contractPaymentHistory_modified_on'
这适用于大约二十几个表,然后它会出现奇怪的错误,如
Ms 1934,Level 16,State 1,Line 9 CREATE INDEX失败,因为以下SET选项具有不正确的设置:'QUOTED_IDENTIFIER'。验证SET选项是否正确,以便与计算列和/或筛选索引和/或查询通知和/或XML数据类型方法和/或空间索引操作的索引视图和/或索引一起使用。
所以我最终使用了不同的策略并创建了一个存储过程来创建索引:How do I create an index inside a stored procedure?
答案 0 :(得分:2)
我之前从未尝试过使用@precommand
,但是如果您将该部分添加到@command1
中,它应该有用。
第二个问题与你如何使用?
有关,它实际上已经包含了dbo架构。将部分OBJECT_ID(N''[dbo].[?]'')
替换为OBJECT_ID("?")
,同样适用于CREATE
和DROP INDEX
声明。
修改强>
此代码应该有效。
EXEC sp_MSforeachtable
'
declare @idx as char;
set @idx = ''idx_'' + "?" + ''_modified_on'';
IF EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID("?") AND name = N''@idx'')
DROP INDEX [@idx] ON ?
CREATE NONCLUSTERED INDEX [@idx] ON ?
(
[modified_on] ASC
) ON [PRIMARY]
'
答案 1 :(得分:1)
您可以在命令中声明idx。您还有其他语法错误。表决。您的错误与declare语句无关。这是因为您使用?
错误。 sp_msforeachtable
会做一个简单的替换。因此,对于您的使用,您需要引用它(或者更确切地说,不要取消引用外部字符串。
请参阅我对your other question的回答,了解为何仍然无效。
这是一个徒手修正的版本:
EXEC sp_MSforeachtable
@command1 = '
declare @idx nvarchar(1000);
declare @tbl nvarchar(1000);
set @tbl = replace(''?'', ''[dbo].'', '''');
set @tbl = left(@tbl, len(@tbl) - 1);
set @idx = ''idx_'' + @tbl + ''_modified_on'';
print @idx;
IF EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N''?'') AND name = N''@idx'')
DROP INDEX [@idx] ON ?;
declare @sql nvarchar(1000);
set @sql = ''
CREATE NONCLUSTERED INDEX ['' + @idx + ''] ON ?
(
[modified_on] ASC
) ON [PRIMARY]'';
exec sp_executesql @sql;
';
我应该质疑你为什么要这样做。仅对该字段编制索引并不像您可能那么好。阅读covering indexes。