76

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

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

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

4

15 回答 15

108

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

如果路径在Properties=> Database Settings=>处显式设置,Database default locations则 SQL 服务器将其存储在Software\Microsoft\MSSQLServer\MSSQLServerin DefaultDataDefaultLogvalues 中。

但是,如果未明确设置这些参数,SQL Server 将使用主数据库的数据和日志路径。

Bellow 是涵盖这两种情况的脚本。这是 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 获得相同的结果。Bellow 是 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')
于 2012-10-06T05:21:03.770 回答
57

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

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

SELECT
  SERVERPROPERTY('instancedefaultdatapath') AS [DefaultFile],
  SERVERPROPERTY('instancedefaultlogpath') AS [DefaultLog]
于 2013-05-21T23:46:02.537 回答
33

我在 SQL Server 帮助中的 Create Database 语句文档中偶然发现了这个解决方案:

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
于 2009-12-10T18:48:22.073 回答
27

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

select physical_name fromsys.database_files;

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

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

于 2009-12-10T18:40:41.757 回答
18

从 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上的评论,并经过测试。)

于 2013-10-23T15:43:12.397 回答
8

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'
于 2009-12-10T18:51:25.450 回答
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

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

于 2013-05-15T11:44:06.610 回答
2

从 GUI:打开您的服务器属性,转到Database Settings,然后查看Database default locations

请注意,您可以将数据库文件放在您喜欢的任何地方,尽管将它们保留在默认目录中似乎更简洁。

于 2009-12-10T18:38:28.657 回答
1

小挑剔:没有数据文件夹,只有一个默认数据文件夹。

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

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

如果有一个命名实例,MSSQL.1 就会变成类似于 MSSQL10.INSTANCENAME 的东西。

于 2009-12-10T18:42:59.897 回答
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'
于 2012-09-11T11:56:26.110 回答
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
于 2012-09-12T21:17:21.340 回答
0

我会做一个备份恢复只是因为它更容易并且支持版本控制。尤其需要对参考数据进行版本控制,以便了解它何时开始生效。分离连接不会给你这种能力。此外,通过备份,您可以继续提供更新的副本,而无需关闭数据库。

于 2014-02-07T14:54:07.483 回答
0

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

但就个人而言,我可能会:

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

ps:20gb不算大,2015年也是。不过都是相对的。

于 2016-06-29T04:23:12.233 回答
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 脚本

于 2016-11-29T02:54:02.803 回答
-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'
于 2013-08-02T13:10:51.203 回答