По материалам статьи Neil Boyle на swynk.com:
"For Each Table" Stored Procedure
Перевод Александра Гладченко
Микрософт предлагает для использования с SQL Server очень
удобную системную хранимую процедуру по имени
sp_msForEachTable. Эта SP предназначена для того, чтобы
позволить администратору базы данных исполнять многие простые
операции над таблицами с помощью всего одной команды.
В то
время как sp_msForEachTable прекрасно работает в большинстве
случаев, существует всё же одна проблема: если Вы попытаетесь
обслуживать множество владельцев объектов в базе данных,
используя синтаксис [владелец].[объект]. Это ещё не было бы
большой проблемой, если бы не то, что многие команды (включая
'sp_recompile' и все команды 'DBCC') не могут иметь дело с
владельцами; они могут иметь дело только с простым, "старым"
именем таблицы.
Учитывая, что многие администраторы баз
данных избегают применение множественных владельцев в базе
данных (просто, потому, что это лишняя администраторская
головная боль) я решил написать версию стандартной процедуры,
которая обходится без включения в предложение запроса имени
владельца объекта, и привожу полный текст этой процедуры в
статье. Написанная мной процедура является, в основном, прямой
копией существующей SP (все подтверждения авторских прав MS),
только с одной поправкой - я удалил ссылки на владельцев
объектов так, что новая процедура будет работать только для
таблиц, принадлежащих текущему пользователю. Поскольку объекты
наиболее часто принадлежат DBO, а Вы являетесь администратором
базы данных, это не должно вызвать проблемы.
Я
переименовал сценарий и включил двойной символ подчеркивания в
его имя. 'sp_' позволяет мне размещать её в базе данных master
и обращаться из контекста любой другой базы, а второй символ
подчеркивания позволяет мне легко отличить мой собственный код
от стандартного кода MS.
Вот полный код новой SP:
drop proc sp__foreachtable
go
create proc sp__foreachtable
/*** Built from the Microsoft original
sp__msForEachTable
**** Use at your own risk
***/
@command1 nvarchar(2000), @replacechar nchar(1) =
N'?',
@command2 nvarchar(2000) =
null,
@command3 nvarchar(2000) =
null,
@whereand nvarchar(2000) =
null,
@precommand nvarchar(2000) =
null,
@postcommand nvarchar(2000) = null
as
/* This proc returns one or more rows for
each table (optionally,
matching @where), with
each table defaulting to its own result set
*/
/* @precommand and @postcommand may be used
to force a single
result set via a temp table.
*/
/* Preprocessor won't replace within quotes so
have to use str(). */
declare @mscat
nvarchar(12)
select @mscat =
ltrim(str(convert(int, 0x0002)))
if (@precommand is not
null)
exec(@precommand)
/* Create the select */
exec(N'declare hCForEach cursor global for
select
(object_name(id))
from
dbo.sysobjects o ' + N'
where
OBJECTPROPERTY(o.id,
N''IsUserTable'') = 1 ' + N'
and
o.category
& ' + @mscat + N' = 0 ' + @whereand)
declare @retval int
select
@retval = @@error
if (@retval =
0)
exec
@retval = sp_MSforeach_worker @command1, @replacechar,
@command2, @command3
if (@retval = 0 and @postcommand is not
null)
exec(@postcommand)
return @retval
Примеры Использования
sp__foreachtable 'dbcc showcontig(?)' /*** SQL 2000 only
***/
sp__foreachtable "dbcc
dbreindex(?)"
sp__foreachtable 'sp_recompile ?'
Ограничения использования
Есть ещё множество возможностей для усовершенствования этой
процедуры. Предлагаемый Вам сценарий не обрабатывает имена
таблиц, которые можно использовать, а также команды, которые
ожидают, что им будет передан object_id, а не имя таблицы -
именно поэтому пример с DBCC SHOWCONTIG подходит для
использования только в SQL 2000.
Примечание к работе ряда хранимых процедур "ForEach"
Ряд хранимых процедур 'ForEach' включает sp_msForEachTable
(представленную выше), sp_msForEachDB - которая работает на
уровне базы данных, и sp_msForEachWorker - которая является
утилитой, называемой "other two".
Когда Вы выполняете
команду, используя sp_msForEachTable или sp_msForEachDB,
хранимая процедура использует методы динамического SQL, чтобы
копировать вашу команду для каждой таблицы или объекта. Эти
команды сохранены в курсоре по имени 'hcForEach'. Как только
курсор будет построен, вызывается sp_msForEachWorker, которая
выбирает и выполняет команды из курсора одну за другой. Если
Вы знакомы с динамическим SQL, то можете рассмотреть эти SP,
чтобы увидеть что они будут делать.
Дополнительная литература
sp__ForEachTable способна к более сложной работе чем
простые примеры, показанные в этой статье. Поскольку она в
основном построена на основе аналога SP от Микрософт
(sp_msForEachTable), Вы можете читать о её расширенных
возможностях в Books Online для получения дополнительной
информации. Эта SP была проверена на SQL 7 и SQL 2000.