Вопрос

У нас есть несколько огромный базы данных (20 ГБ+), которые в основном содержат статические данные поиска.Поскольку наше приложение выполняет соединения с таблицами в этих базах данных, они должны быть частью локального SQL-сервера каждого разработчика (т.они не могут размещаться на центральном общем сервере базы данных).

Мы планируем скопировать канонический набор реальных файлов базы данных SQL Server (*.mdf и *.ldf) и прикрепить их к локальной базе данных каждого разработчика.

Как лучше всего узнать каталог данных локального экземпляра SQL Server, чтобы мы могли скопировать файлы в нужное место?Это будет сделано посредством автоматизированного процесса, поэтому я должен иметь возможность найти и использовать его из сценария сборки.

Это было полезно?

Решение

Это зависит от того, установлен ли путь по умолчанию для файлов данных и журналов или нет.

Если путь указан явно в Properties => Database Settings => Database default locations затем SQL-сервер сохраняет его по адресу Software\Microsoft\MSSQLServer\MSSQLServer в DefaultData и DefaultLog ценности.

Однако, если эти параметры не заданы явно, SQL-сервер использует пути к данным и журналам главной базы данных.

Ниже приведен сценарий, охватывающий оба случая.Это упрощенная версия запроса, выполняемого SQL Management Studio.

Также обратите внимание, что я использую xp_instance_regread вместо xp_regread, поэтому этот скрипт будет работать для любого экземпляра, по умолчанию или с именем.

declare @DefaultData nvarchar(512)
exec master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer', N'DefaultData', @DefaultData output

declare @DefaultLog nvarchar(512)
exec master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer', N'DefaultLog', @DefaultLog output

declare @DefaultBackup nvarchar(512)
exec master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer', N'BackupDirectory', @DefaultBackup output

declare @MasterData nvarchar(512)
exec master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer\Parameters', N'SqlArg0', @MasterData output
select @MasterData=substring(@MasterData, 3, 255)
select @MasterData=substring(@MasterData, 1, len(@MasterData) - charindex('\', reverse(@MasterData)))

declare @MasterLog nvarchar(512)
exec master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer\Parameters', N'SqlArg2', @MasterLog output
select @MasterLog=substring(@MasterLog, 3, 255)
select @MasterLog=substring(@MasterLog, 1, len(@MasterLog) - charindex('\', reverse(@MasterLog)))

select 
    isnull(@DefaultData, @MasterData) DefaultData, 
    isnull(@DefaultLog, @MasterLog) DefaultLog,
    isnull(@DefaultBackup, @MasterLog) DefaultBackup

Вы можете добиться того же результата, используя SMO.Ниже приведен пример C#, но вы можете использовать любой другой язык .NET или PowerShell.

using (var connection = new SqlConnection("Data Source=.;Integrated Security=SSPI"))
{
    var serverConnection = new ServerConnection(connection);
    var server = new Server(serverConnection);
    var defaultDataPath = string.IsNullOrEmpty(server.Settings.DefaultFile) ? server.MasterDBPath : server.Settings.DefaultFile;
    var defaultLogPath = string.IsNullOrEmpty(server.Settings.DefaultLog) ? server.MasterDBLogPath : server.Settings.DefaultLog;
}

В SQL Server 2012 и более поздних версиях это намного проще, если предположить, что у вас установлены пути по умолчанию (что, вероятно, всегда правильно):

select 
    InstanceDefaultDataPath = serverproperty('InstanceDefaultDataPath'),
    InstanceDefaultLogPath = serverproperty('InstanceDefaultLogPath')

Другие советы

Несмотря на то, что это очень старая тема, я чувствую, что мне нужно предложить простое решение.Каждый раз, когда вы знаете, где в Management Studio находится параметр, к которому вы хотите получить доступ для любого типа автоматизированного сценария, самый простой способ — запустить быструю трассировку профилировщика в автономной тестовой системе и отследить, что Management Studio делает на серверной части. .

В этом случае, если вы заинтересованы в поиске местоположений данных и журналов по умолчанию, вы можете сделать следующее:

ВЫБИРАТЬ
SERVERPROPERTY('instancedefaultdatapath') AS [DefaultFile],
SERVERPROPERTY('instancedefaultlogpath') AS [DefaultLog]

Я наткнулся на это решение в документации по оператору Create Database в справке по SQL Server:

SELECT SUBSTRING(physical_name, 1, CHARINDEX(N'master.mdf', LOWER(physical_name)) - 1)
                  FROM master.sys.master_files
                  WHERE database_id = 1 AND file_id = 1

Для текущей базы данных вы можете просто использовать:

select physical_name fromsys.database_files;

чтобы указать другую базу данных, например.«Модель», используйте sys.master_files

select physical_name from sys.master_files where database_id = DB_ID(N'Model');

Начиная с Sql Server 2012, вы можете использовать следующий запрос:

SELECT SERVERPROPERTY('INSTANCEDEFAULTDATAPATH') as [Default_data_path], SERVERPROPERTY('INSTANCEDEFAULTLOGPATH') as [Default_log_path];

(Это было взято из комментария на http://technet.microsoft.com/en-us/library/ms174396.aspx, и протестировано.)

Различные компоненты SQL Server (данные, журналы, SSAS, SSIS и т. д.) имеют каталог по умолчанию.Эту настройку можно найти в реестре.Подробнее читайте здесь:

http://technet.microsoft.com/en-us/library/ms143547%28SQL.90%29.aspx

Итак, если вы создали базу данных, используя только CREATE DATABASE MyDatabaseName он будет создан по пути, указанному в одной из настроек выше.

Теперь, если администратор/установщик изменил путь по умолчанию, путь по умолчанию для экземпляра сохраняется в реестре по адресу

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\[INSTANCENAME]\Setup

Если вы знаете имя экземпляра, вы можете запросить реестр.Этот пример относится только к SQL 2008 — дайте мне знать, если вам также нужен путь SQL2005.

DECLARE @regvalue varchar(100)

EXEC master.dbo.xp_regread @rootkey='HKEY_LOCAL_MACHINE',
        @key='SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL10.MSSQLServer\Setup',
        @value_name='SQLDataRoot',
        @value=@regvalue OUTPUT,
        @output = 'no_output'

SELECT @regvalue as DataAndLogFilePath

Каждая база данных может быть создана с переопределением настроек сервера в своем собственном месте при запуске CREATE DATABASE DBName оператор с соответствующими параметрами.Вы можете узнать это, выполнив sp_helpdb

exec sp_helpdb 'DBName'

Если говорить просто:

use master
select DB.name, F.physical_name from sys.databases DB join sys.master_files F on DB.database_id=F.database_id

это вернет все базы данных со связанными файлами

Из графического интерфейса:откройте свойства сервера, перейдите в Настройки базы данных, и посмотреть Расположение базы данных по умолчанию.

Обратите внимание, что вы можете переместить файлы базы данных куда угодно, хотя кажется удобнее хранить их в каталоге по умолчанию.

Вы можете найти расположение данных и журналов по умолчанию для текущего экземпляра SQL Server, используя следующий T-SQL:

DECLARE @defaultDataLocation nvarchar(4000)
DECLARE @defaultLogLocation nvarchar(4000)

EXEC master.dbo.xp_instance_regread
    N'HKEY_LOCAL_MACHINE',
    N'Software\Microsoft\MSSQLServer\MSSQLServer',
    N'DefaultData', 
    @defaultDataLocation OUTPUT

EXEC master.dbo.xp_instance_regread
    N'HKEY_LOCAL_MACHINE',
    N'Software\Microsoft\MSSQLServer\MSSQLServer',
    N'DefaultLog', 
    @defaultLogLocation OUTPUT

SELECT @defaultDataLocation AS 'Default Data Location',
       @defaultLogLocation AS 'Default Log Location'

Маленькая придирка:папки с данными нет, есть только по умолчанию папка данных.

В любом случае, чтобы найти его, предполагая, что вы хотите установить первый экземпляр по умолчанию:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL.1\Setup\SQLDataRoot

Если есть именованный экземпляр, MSSQL.1 становится чем-то вроде MSSQL10.INSTANCENAME.

Расширяя ответ «разбрызганные биты», вот полный скрипт, который это делает:

@ECHO off
SETLOCAL ENABLEDELAYEDEXPANSION

SET _baseDirQuery=SELECT SUBSTRING(physical_name, 1, CHARINDEX(N'master.mdf', LOWER(physical_name)) - 1) ^
 FROM master.sys.master_files WHERE database_id = 1 AND file_id = 1;
ECHO.
SQLCMD.EXE -b -E -S localhost -d master -Q "%_baseDirQuery%" -W >data_dir.tmp
IF ERRORLEVEL 1 ECHO Error with automatically determining SQL data directory by querying your server&ECHO using Windows authentication.
CALL :getBaseDir data_dir.tmp _baseDir

IF "%_baseDir:~-1%"=="\" SET "_baseDir=%_baseDir:~0,-1%"
DEL /Q data_dir.tmp
echo DataDir: %_baseDir%

GOTO :END
::---------------------------------------------
:: Functions 
::---------------------------------------------

:simplePrompt 1-question 2-Return-var 3-default-Val
SET input=%~3
IF "%~3" NEQ "" (
  :askAgain
  SET /p "input=%~1 [%~3]:"
  IF "!input!" EQU "" (
    GOTO :askAgain
  ) 
) else (
  SET /p "input=%~1 [null]: "
)   
SET "%~2=%input%"
EXIT /B 0

:getBaseDir fileName var
FOR /F "tokens=*" %%i IN (%~1) DO (
  SET "_line=%%i"
  IF "!_line:~0,2!" == "c:" (
    SET "_baseDir=!_line!"
    EXIT /B 0
  )
)
EXIT /B 1

:END
PAUSE

я бы сделал восстановление из резервной копии просто потому, что это проще и поддерживает управление версиями.Справочные данные особенно нуждаются в версионировании, чтобы знать, когда они начали действовать.Отсоединение не даст вам такой возможности.Кроме того, с помощью резервных копий вы можете продолжать предоставлять обновленные копии без необходимости выключать базу данных.

Ответ Алекса правильный вариант, но для потомков есть еще один вариант:создайте новую пустую базу данных.Если вы используете CREATE DATABASE без указания целевого каталога, вы получите...каталоги данных/журналов по умолчанию.Легкий.

Однако лично я бы, вероятно, либо:

  • ВОССТАНОВИТЕ базу данных на ПК разработчика, а не копируйте/прикрепляйте ее (резервные копии можно сжимать и размещать в формате UNC) или
  • Используйте связанный сервер, чтобы вообще этого не делать (зависит от того, какой объем данных передается через соединение).

пс:20 ГБ — это не так уж и много даже в 2015 году.Но это все относительно.

SELECT DISTINCT dbo.GetDirectoryPath(filename) AS InstanceDataPaths
FROM sys.sysaltfiles WHERE filename like '%.mdf' and filename not like '%\MSSQL\Binn\%'

SELECT DISTINCT dbo.GetDirectoryPath(filename) AS InstanceLogPaths
FROM sys.sysaltfiles WHERE filename like '%.ldf' and filename not like '%\MSSQL\Binn\%'

enter image description here

Подробный сценарий SQL можно загрузить с сайта как найти каталог данных для экземпляра SQL Server

Вы получите местоположение по умолчанию, если пользовательская база данных по этому запросу:

declare @DataFileName nVarchar(500)

declare @LogFileName   nVarchar(500)


set @DataFileName = (select top 1 RTRIM(LTRIM(name)) FROM master.sys.master_files where database_id >4 AND file_id = 1)+'.mdf'
set @LogFileName =   (select top 1 RTRIM(LTRIM(name)) FROM master.sys.master_files where database_id >4 AND file_id = 2)+'.ldf'

select  
( SELECT top 1 SUBSTRING(physical_name, 1, CHARINDEX(@DataFileName, LOWER(physical_name)) - 1) 
FROM master.sys.master_files
WHERE database_id >4 AND file_id = 1) as 'Data File'
,

(SELECT top 1 SUBSTRING(physical_name, 1, CHARINDEX(@LogFileName, LOWER(physical_name)) - 1)
FROM master.sys.master_files
WHERE database_id >4 AND file_id = 2)  as 'Log File'
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top