如何找到SQL Server实例的数据目录?


72

我们有一些大型数据库(20GB +),其中大多数包含静态查找数据。因为我们的应用程序对这些数据库中的表执行联接,所以它们必须是每个开发人员本地SQL Server的一部分(即它们不能托管在中央共享数据库服务器上)。

我们计划复制一组规范的实际SQL Server数据库文件(* .mdf和* .ldf),并将它们附加到每个开发人员的本地数据库中。

找出本地SQL Server实例的数据目录的最佳方法是什么,以便我们可以将文件复制到正确的位置?这将通过自动化过程完成,因此我必须能够从构建脚本中找到并使用它。

Answers:


104

这取决于是否为数据和日志文件设置了默认路径。

如果该路径在Properties=> Database Settings=>处显式设置,Database default locations则SQL Server将其存储Software\Microsoft\MSSQLServer\MSSQLServerDefaultDataDefaultLogvalue中。

但是,如果未明确设置这些参数,则SQL Server将使用master数据库的Data和Log路径。

贝娄是涵盖这两种情况的脚本。这是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')

这是否不需要安装另一个软件包-SMO SDK?
BSalita

1
@BSalita-如果您已经安装了SQL Server,而不是已经安装了SMO。您只需要引用来自的程序集C:\Program Files\Microsoft SQL Server\110\SDK\Assemblies,例如Microsoft.SqlServer.Smo.dllMicrosoft.SqlServer.ConnectionInfo.dll。但是,如果从未安装SQL Server的计算机进行连接,则需要安装SMO。查找“ Microsoft SQL Server 2012功能包”以查找独立的SMO安装程序。
亚历克斯·阿扎

感谢您提供C#示例-这非常有用。
TrailJon 2015年

2
它可以工作,但是结果中出现错误信息。 RegQueryValueEx() returned error 2, 'The system cannot find the file specified.' Msg 22001, Level 1, State 1 RegQueryValueEx() returned error 2, 'The system cannot find the file specified.' Msg 22001, Level 1, State 1
DKroot

试图为SQL 2005识别此问题,而最后一个解决方案不起作用。但是,在ENTIRE注册表中搜索您提到的任何关键字(例如)后Database default locations,我在任何地方都找不到它-不适用于SQL2005,SQL2008或SQL2012。我在整个HKEY_LOCAL_MACHINE关键字中以及实际路径本身中进行了搜索。对于任何版本,都不是跟踪。并尝试通过TSQL,我得到与@DKroot相同的错误。猜猜我将不得不作弊并使用master数据库文件的目录。
杰里·道奇

48

即使这是一个非常老的线程,我仍需要提供一个简单的解决方案。每当您知道要在任何类型的自动化脚本中访问的参数在Management Studio中的位置时,最简单的方法是在独立的测试系统上运行快速探查器跟踪并捕获Management Studio在后端执行的操作。

在这种情况下,假设您有兴趣查找默认数据和日志位置,则可以执行以下操作:

SELECT
     SERVERPROPERTY('instancedefaultdatapath')AS [DefaultFile],
     SERVERPROPERTY('instancedefaultlogpath')AS [DefaultLog]


33

我在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

41
哇,令人惊讶的是,很多人为错误的答案表示支持。该查询将显示主数据库数据文件的路径,而不是默认数据文件的路径。默认数据文件路径可能与master.mdf文件路径相同,也可能不同。如果将用户数据库与系统数据库分开存储,则此“解决方案”将不起作用,这在大型生产环境中并不罕见。
亚历克斯·阿扎

@AlexAza这比我想要的要多得多的代码,这可能只是我自己的问题。:-)这个答案呢?
亚伦·詹森

快速注释-将SUBSTRING starting_position值减小到0,以获得完整的干净路径,而无需master.mdf文件名的第一个字符。
mojo

我们之所以使用该解决方案,是因为我们不想打开注册表来知道答案。但是,我们在希望创建其他数据库的地方创建了一个数据库,我们正在寻找该数据库信息而不是“主数据库”。 SELECT physical_name FROM sys.master_files mf inner JOIN sys.databases d ON d.database_id = mf.database_id AND d.name = 'our-template-database' AND TYPE = 0
foxont​​herock 2014年

1
@AlexAza我同意,这是一个草率的解决方案,但是对于旧版本的SQL Server,其他解决方案似乎无效,例如注册表。因此,您对答案的评论。从注册表中读取几乎也似乎是一种黑客。
杰里·道奇

27

对于当前数据库,您可以使用:

select physical_name fromsys.database_files;

要指定另一个数据库,例如“模型”,请使用sys.master_files

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


3
+1。值得一提的是,这需要在想要其文件的DB上下文中运行。(我花了一些时间徒劳无功地寻找加入的方法sysdatabases)。
EM0 2012年

@ EM0不正确。您可以从任何地方查询sys.master_files和加入sys.databasesselect * from sys.master_files f join sys.databases d on d.database_id = f.database_id
pim


8

SQL Server的各种组件(数据,日志,SSAS,SSIS等)具有默认目录。可以在注册表中找到此设置。在这里阅读更多:

http://technet.microsoft.com/zh-cn/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'

这没有帮助,因为我要查询的数据库尚不存在。实例(而不是数据库)是否有等效的存储过程?
亚伦·詹森,2009年

1
抱歉,此解决方案不正确。此注册表查询null首先为我返回。我改变了xp_regreadxp_instance_regread固定的注册表路径Software\Microsoft\MSSQLServer\Setup,使每个SQL Server实例的查询工作,尽管版本。但是,查询返回的位置甚至与我的默认数据或日志文件位置都不接近。另外,它为什么只为数据和日志文件返回一个值?在我的环境中,它们设置为不同的值。将数据和日志文件存储在不同的磁盘上并不少见。
亚历克斯·阿扎

从中读取可以HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\[INSTANCENAME]\Setup访问实例目录,但不能访问实际的数据/日志文件默认目录。它具有SQLDataRoot,但是不包括\Data实际位置的子目录。
杰里·道奇

6

保持简单:

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

这将返回所有带有关联文件的数据库


2

在GUI中:打开服务器属性,转到“数据库设置”,然后查看“数据库默认位置”

请注意,您可以将数据库文件放置在任意位置,尽管将它们保留在默认目录中看起来更干净。


0

小nitpick:没有数据文件夹,只有默认数据文件夹。

无论如何,假设您要为第一个默认实例进行安装,请找到它:

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

如果存在命名实例,则MSSQL.1类似于MSSQL10.INSTANCENAME。


这要求我知道SQL Server实例名称(例如MSSQL.1,MSSQL.2,MSSQL._N_)。如何获得该实例名称?
亚伦詹森,2009年

对于默认实例,它不是名称,而是数字。哪个实例要安装由您决定!要找出安装了哪些实例,请查看HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Microsoft SQL Server \ Instance Names \ SQL
Stu

我需要将数据库附加到其他应用程序实例所在的实例中。本质上,我需要将友好的实例名称(在SQL Server企业管理器中显示的实例名称,在所有计算机上都相同)转换为此内部的“数字”标识符。
亚伦·詹森,2009年

因此,在“实例名称”中查找,找到实例名称,查找标识符(即值),然后返回并查找适当的键。
Stu

0

您可以使用以下T-SQL查找当前SQL Server实例的默认数据和日志位置:

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'

不适用于命名实例。对于默认实例,仅给出日志位置。
奥利弗·

0

扩展“飞溅的位”答案,这是一个完整的脚本,可以完成此操作:

@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

0

我会做一个备份还原,只是因为它更容易并且支持版本控制。尤其需要对参考数据进行版本控制,以便知道何时开始生效。独立的附件不会给您这种能力。同样,通过备份,您可以继续提供更新的副本,而不必关闭数据库。


0

亚历克斯的答案是正确的,但对于后代,这是另一种选择:创建一个新的空数据库。如果您在不指定目标目录的情况下使用CREATE DATABASE,则会得到...默认数据/日志目录。简单。

但是我个人可能会:

  • 将数据库还原到开发人员的PC,而不是复制/附加(备份可以压缩,在UNC上公开)或
  • 首先使用链接服务器避免这样做(取决于通过连接传递的数据量)

ps:即使在2015年,20GB的存储空间也不算太大。但这都是相对的。


0
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\%'

在此处输入图片说明

您可以从如何查找SQL Server实例的数据目录中下载详细的SQL脚本。


-1

如果用户数据库通过此查询将获得默认位置:

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'

如果master数据库所在的位置与默认位置不同(例如,默认位置在创建master之后更改了),则无法正常工作
Allanrbo 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.