я использую sp_msforeachdb
чтобы перечислить все базы данных на моем сервере.
Я знаю это не поддерживается, но мне интересно, почему в нем не перечислены все установленные мной базы данных.
Вот как я его запускаю:
set run="C:\Program Files\Microsoft SQL Server\100\Tools\Binn\SQLCMD.EXE" -S .\SQL2008 -E -h -1 -Q
%run% "exec sp_msforeachdb 'select ''?'''"
Вывод:
master
tempdb
model
msdb
balance166
Базы данных, которые показывает SSMS:
master
tempdb
model
msdb
balance166
BOON205
KAB205
Обе BOON0205
и KAB205
были восстановлены с помощью таких команд:
%run% "..."
где "..."
это утверждение в одной строке:
RESTORE DATABASE [BOON205] FROM DISK = N'C:\Data\Backup\Balance205.bak'
WITH REPLACE,
STATS = 10,
MOVE N'Balance166' to N'C:\Data\Balance205.mdf',
MOVE N'Balance166_log' to N'C:\Data\Balance205_log.ldf';
Восстановление, очевидно, работает: я могу нормально подключиться к этим базам данных.
Но sp_msforeachdb
не перечисляет их.
Зачем?
С чего мне начать узнавать?
редактировать: Окружающая среда
sys.databases
в порядке:
C:\bin>%sqlrun% -Q "select name from sys.databases"
name
-----------------------------------------------------------------------------
master
tempdb
model
msdb
balance166
Balance205
KAB205
BOON205
(8 rows affected)
has_dbaccess
нормально, но status
наверное нет. Нужно это проверить:
C:\bin>%sqlrun% -Q "select cast(name as varchar(10)), status, cast(status as varbinary(8)), DATABASEPROPERTY(name, 'issingleuser') as issingleuser, has_dbaccess(name) as has_dbaccess from master.dbo.sysdatabases"
status issingleuser has_dbaccess
---------- ----------- ---------- ------------ ------------
master 65544 0x00010008 0 1
tempdb 65544 0x00010008 0 1
model 65536 0x00010000 0 1
msdb 65544 0x00010008 0 1
balance166 65536 0x00010000 0 1
Balance205 1073807361 0x40010001 0 1
KAB205 1073807361 0x40010001 0 1
BOON205 1073807361 0x40010001 0 1
Это не статус, как DATABASEPROPERTYEX('master', 'Status')
возвращается ONLINE
для всех.
Со списком найденных кодов состояния Вот и определение sp_msforeachdb, Я сделал это так, что исключает status
как проблема:
8 0x00000008 - 'trunc. log on chkpt'
65536 0x00010000 - 'online'
65544 0x00010008 - 65536 + 8
1073741824 0x40000000 - 'invalid login'
1073807361 0x40010001 - 1073741824 + 65536 + 8
Таким образом, последние 4 базы данных из списка имеют «неверный логин».
Пора заняться безопасностью и правами ...
- Джерун
Решено! В 0x4000000
бит состояния базы данных - это AutoClose установка БД.
AutoClose
это плохо, не только потому, что сбивает с толку ms_foreachdb, но и потому, что часто снижает вашу производительность. Хорошие новости: он в «списке убийств».
sp_helpdb может анализировать статусы в удобочитаемой форме и показывает, что sp_msforeachdb исходный код интерпретирует AutoClose
пометить неправильно как InvalidLogin
:-)
Это то, что sp_helpdb
показано (прокрутите вправо, чтобы увидеть различия между Balance166 и Balance205):
Balance166 Status=ONLINE, Updateability=READ_WRITE, UserAccess=MULTI_USER, Recovery=FULL, Version=655, Collation=SQL_Latin1_General_CP1_CI_AS, SQLSortOrder=52, IsAutoCreateStatistics, IsAutoUpdateStatistics
Balance205 Status=ONLINE, Updateability=READ_WRITE, UserAccess=MULTI_USER, Recovery=FULL, Version=655, Collation=SQL_Latin1_General_CP1_CI_AS, SQLSortOrder=52, IsAutoClose, IsAutoCreateStatistics, IsAutoUpdateStatistics
Отключить AutoClose очень просто:
USE [master]
GO
ALTER DATABASE [Balance205] SET AUTO_CLOSE OFF WITH NO_WAIT
GO
и приводит к этим настройкам:
name status Xstatus DBStatus issingleuser has_dbaccess
---------- ------- ---------- ---------- ------------ ------------
Balance166 65536 0x00010000 ONLINE 0 1
Balance205 65536 0x00010000 ONLINE 0 1
- Джерун
ms_foreachdb не работает так же хорошо в SQL Server 2005 или новее, но если вы скопируете логику из этой хранимой процедуры и измените тип курсора на INSENSITIVE, эта недокументированная хранимая процедура будет работать правильно. Однако лучше всего будет использовать свой собственный код для проверки в будущем.
SQL Server Management Studio выполняет запрос к представлению каталога sys.databases. Все базы данных перечислены в этом DMV. Хранимая процедура sp_msforeachdb имеет логику, которая вызывает функцию has_dbaccess () для анализа своего списка баз данных. Очевидно, он не хочет пытаться запустить команду для базы данных, к которой у вас нет доступа. Есть ли у вас доступ ко всем рассматриваемым базам данных с учетной записью, использованной для выполнения запроса?