Wie finde ich das Datenverzeichnis für eine SQL Server-Instanz?


72

Wir haben einige riesige Datenbanken (20 GB +), die hauptsächlich statische Suchdaten enthalten. Da unsere Anwendung Verknüpfungen für Tabellen in diesen Datenbanken ausführt, müssen sie Teil des lokalen SQL Servers jedes Entwicklers sein (dh sie können nicht auf einem zentralen, gemeinsam genutzten Datenbankserver gehostet werden).

Wir planen, einen kanonischen Satz der tatsächlichen SQL Server-Datenbankdateien (* .mdf und * .ldf) zu kopieren und an die lokale Datenbank jedes Entwicklers anzuhängen.

Wie können Sie das Datenverzeichnis der lokalen SQL Server-Instanz am besten ermitteln, damit wir die Dateien an den richtigen Ort kopieren können? Dies erfolgt über einen automatisierten Prozess, daher muss ich ihn in einem Build-Skript finden und verwenden können.

Antworten:


104

Dies hängt davon ab, ob der Standardpfad für Daten- und Protokolldateien festgelegt ist oder nicht.

Wenn der Pfad explizit auf Properties=> Database Settings=> festgelegt Database default locationsist, speichert SQL Server ihn unter Software\Microsoft\MSSQLServer\MSSQLServerin DefaultDataund DefaultLogWerten.

Wenn diese Parameter jedoch nicht explizit festgelegt werden, verwendet SQL Server die Daten- und Protokollpfade der Masterdatenbank.

Unten ist das Skript, das beide Fälle abdeckt. Dies ist eine vereinfachte Version der Abfrage, die SQL Management Studio ausführt.

Beachten Sie auch, dass ich xp_instance_regreadanstelle von verwende xp_regread, damit dieses Skript für jede Instanz, Standard oder benannt, funktioniert.

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

Mit SMO können Sie das gleiche Ergebnis erzielen. Unten ist ein C # -Beispiel, Sie können jedoch jede andere .NET-Sprache oder PowerShell verwenden.

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;
}

In SQL Server 2012 und höher ist dies viel einfacher, vorausgesetzt, Sie haben Standardpfade festgelegt (was wahrscheinlich immer richtig ist):

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

Erfordert dies nicht die Installation eines anderen Pakets - SMO SDK?
BSalita

1
@BSalita - Wenn Sie SQL Server installiert haben, haben Sie SMO bereits installiert. Sie müssen nur auf Assemblys verweisen C:\Program Files\Microsoft SQL Server\110\SDK\Assemblies, z. B. Microsoft.SqlServer.Smo.dllund Microsoft.SqlServer.ConnectionInfo.dll. Wenn Sie jedoch eine Verbindung von einem Computer herstellen, auf dem kein SQL Server installiert ist, müssen Sie SMO installieren. Suchen Sie nach "Microsoft SQL Server 2012 Feature Pack", um ein eigenständiges SMO-Installationsprogramm zu finden.
Alex Aza

Vielen Dank, dass Sie das C # -Beispiel aufgenommen haben - das war unglaublich hilfreich.
TrailJon

2
Es funktioniert, aber ich erhalte eine Fehlermeldung in den Ergebnissen. 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

Der Versuch, dies für SQL 2005 zu identifizieren, wo die letzte Lösung nicht funktioniert. Nachdem Database default locationsich die GESAMTE Registrierung nach einem von Ihnen erwähnten Schlüsselwort durchsucht habe , kann ich es jedoch nirgendwo finden - nicht für SQL2005, SQL2008 oder SQL2012. Ich habe das gesamte HKEY_LOCAL_MACHINEnach diesem Schlüsselwort sowie nach den tatsächlichen Pfaden selbst durchsucht . Keine Spur für jede Version. Beim Versuch über TSQL erhalte ich den gleichen Fehler wie bei @DKroot. Ich denke, ich muss die Verzeichnisse der Master-Datenbankdateien betrügen und verwenden.
Jerry Dodge

47

Obwohl dies ein sehr alter Thread ist, habe ich das Gefühl, dass ich eine einfache Lösung beitragen muss. Jedes Mal, wenn Sie wissen, wo sich in Management Studio ein Parameter befindet, auf den Sie für ein automatisiertes Skript zugreifen möchten, können Sie am einfachsten einen schnellen Profiler-Trace auf einem eigenständigen Testsystem ausführen und erfassen, was Management Studio im Backend tut .

Angenommen, Sie möchten die Standarddaten und Protokollspeicherorte finden, können Sie in diesem Fall Folgendes tun:

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


33

Ich bin in der Dokumentation zur Anweisung "Datenbank erstellen" in der Hilfe für SQL Server auf diese Lösung gestoßen:

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
Wow, überraschend viele Upvotes für die falsche Antwort. Diese Abfrage zeigt den Pfad der Stammdatenbankdatendatei und nicht den Standarddatendateipfad. Der Standardpfad für Datendateien kann mit dem Dateipfad master.mdf identisch sein oder nicht. Diese 'Lösung' funktioniert nicht, wenn Sie Benutzerdatenbanken getrennt von Systemdatenbanken speichern, was in großen Produktionsumgebungen nicht ungewöhnlich ist.
Alex Aza

@AlexAza Das ist viel mehr Code als ich wollte, was vielleicht nur mein eigenes Problem ist. :-) Was ist mit dieser Antwort?
Aaron Jensen

Schneller Kommentar - Klopfen Sie den Wert für SUBSTRING Starting_Position auf 0, um den vollständigen sauberen Pfad ohne das erste Zeichen des Dateinamens master.mdf zu erhalten.
Mojo

Wir verwenden diese Lösung, weil wir die Registrierung nicht öffnen möchten, um die Antwort zu erfahren. Wir haben jedoch eine Datenbank an der Stelle erstellt, an der andere erstellt werden sollen, und wir suchen nach diesen Datenbankinformationen anstelle von "master". 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
Foxontherock

1
@AlexAza Ich stimme zu, es ist eine schlampige Lösung, aber für ältere Versionen von SQL Server scheinen andere Lösungen nicht zu funktionieren, wie z. B. die Registrierung. Daher die Kommentare zu Ihrer Antwort. Das Lesen aus der Registrierung scheint auch fast ein Hack zu sein.
Jerry Dodge

27

Für die aktuelle Datenbank können Sie einfach verwenden:

select physical_name fromsys.database_files;

Verwenden Sie sys.master_files, um eine andere Datenbank anzugeben, z. B. 'Model'

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


3
+1. Beachten Sie, dass dies im Kontext der Datenbank ausgeführt werden muss, deren Dateien Sie möchten. (Ich habe einige Zeit erfolglos nach einem Weg gesucht, mich ihm anzuschließen sysdatabases).
EM0

@ EM0 nicht wahr. Sie können von überall abfragen sys.master_filesund beitreten sys.databases. select * from sys.master_files f join sys.databases d on d.database_id = f.database_id
Pim


8

Verschiedene Komponenten von SQL Server (Daten, Protokolle, SSAS, SSIS usw.) haben ein Standardverzeichnis. Die Einstellung hierfür finden Sie in der Registrierung. Lesen Sie hier mehr:

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

Wenn Sie also eine Datenbank nur CREATE DATABASE MyDatabaseNamemit erstellen, wird diese unter dem in einer der obigen Einstellungen angegebenen Pfad erstellt.

Wenn der Administrator / Installer den Standardpfad geändert hat, wird der Standardpfad für die Instanz in der Registrierung unter gespeichert

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

Wenn Sie den Namen der Instanz kennen, können Sie die Registrierung abfragen. Dieses Beispiel ist SQL 2008-spezifisch. Lassen Sie mich wissen, ob Sie auch den SQL2005-Pfad benötigen.

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

Jede Datenbank kann erstellt werden, indem die Servereinstellung an einem eigenen Speicherort überschrieben wird, wenn Sie die CREATE DATABASE DBNameAnweisung mit den entsprechenden Parametern ausgeben . Sie können dies herausfinden, indem Sie sp_helpdb ausführen

exec sp_helpdb 'DBName'

Dies hilft nicht, da die Datenbank, die ich abfragen würde, noch nicht vorhanden ist. Gibt es eine äquivalente gespeicherte Prozedur für Instanzen (im Gegensatz zu Datenbanken)?
Aaron Jensen

1
Es tut mir leid, aber diese Lösung ist nicht korrekt. Diese Registrierungsabfrage wurde nullin erster Linie für mich zurückgegeben. Ich wechselte xp_regreadzu xp_instance_regreadund den Registrierungspfad festgelegt Software\Microsoft\MSSQLServer\SetupAbfrage Arbeit auf jeder SQL - Server - Instanz trotz der Version zu machen. Der Speicherort, den die Abfrage zurückgibt, befindet sich jedoch nicht einmal in der Nähe meines Standardspeicherorts für Daten- oder Protokolldateien. Wie kommt es, dass nur ein Wert für Daten- und Protokolldateien zurückgegeben wird? Sie sind in meiner Umgebung auf unterschiedliche Werte eingestellt. Es ist nicht ungewöhnlich, dass sich Daten und Protokolldateien auf verschiedenen Datenträgern befinden.
Alex Aza

Durch Lesen von erhalten Sie HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\[INSTANCENAME]\SetupZugriff auf das Instanzverzeichnis, jedoch nicht auf die Standardverzeichnisse der Daten- / Protokolldatei. Es enthält SQLDataRootjedoch nicht das Unterverzeichnis, \Datadas der tatsächliche Speicherort ist.
Jerry Dodge

6

Einfach halten:

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

Dadurch werden alle Datenbanken mit zugehörigen Dateien zurückgegeben


2

Über die GUI: Öffnen Sie Ihre Servereigenschaften, gehen Sie zu Datenbankeinstellungen und sehen Sie sich die Standardspeicherorte der Datenbank an .

Beachten Sie, dass Sie Ihre Datenbankdateien beliebig ablegen können, obwohl es sauberer erscheint, sie im Standardverzeichnis zu belassen.


0

Kleiner Nitpick: Es gibt keinen Datenordner, nur einen Standarddatenordner .

Wie auch immer, um es zu finden, vorausgesetzt, Sie möchten für die erste Standardinstanz installieren:

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

Wenn es eine benannte Instanz gibt, wird MSSQL.1 zu MSSQL10.INSTANCENAME.


Dies setzt voraus, dass ich den Namen der SQL Server-Instanz kenne (z. B. MSSQL.1, MSSQL.2, MSSQL._N_). Wie erhalte ich diesen Instanznamen?
Aaron Jensen

Bei Standardinstanzen ist es nicht der Name, sondern nur die Nummer. Welche Instanz installiert werden soll, liegt bei Ihnen! Um herauszufinden, welche Instanzen installiert sind, schauen Sie unter HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Microsoft SQL Server \ Instanznamen \ SQL
Stu

Ich muss meine Datenbanken an dieselbe Instanz anhängen, an der sich die anderen Anwendungsinstanzen befinden. Im Wesentlichen müsste ich den Namen der benutzerfreundlichen Instanz (der in SQL Server Enterprise Manager angezeigt wird und auf allen Computern gleich ist) in diesen internen "numerischen" Bezeichner konvertieren.
Aaron Jensen

Suchen Sie also in Instanznamen, suchen Sie den Instanznamen, suchen Sie den Bezeichner (dh den Wert), gehen Sie zurück und suchen Sie den entsprechenden Schlüssel.
Stu

0

Mithilfe des folgenden T-SQL können Sie Standarddaten- und Protokollspeicherorte für die aktuelle SQL Server-Instanz ermitteln:

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'

Hat für eine benannte Instanz nicht funktioniert. Für eine Standardinstanz wurde nur der Protokollspeicherort angegeben.
Oliver

0

Hier ist ein vollständiges Skript, das die Antwort "Splattered Bits" erweitert:

@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

Ich hätte eine Backup-Wiederherstellung durchgeführt, nur weil es einfacher ist und die Versionierung unterstützt. Insbesondere Referenzdaten müssen versioniert werden, um zu wissen, wann sie wirksam werden. Ein Dettach-Anhang gibt Ihnen diese Fähigkeit nicht. Auch bei Sicherungen können Sie weiterhin aktualisierte Kopien bereitstellen, ohne die Datenbank herunterfahren zu müssen.


0

Alex 'Antwort ist die richtige, aber für die Nachwelt gibt es noch eine andere Option: Erstellen Sie eine neue leere Datenbank. Wenn Sie CREATE DATABASE verwenden, ohne ein Zielverzeichnis anzugeben, erhalten Sie ... die Standarddaten- / Protokollverzeichnisse. Einfach.

Persönlich würde ich aber wahrscheinlich auch:

  • Stellen Sie die Datenbank auf dem PC des Entwicklers wieder her, anstatt sie zu kopieren / anzuhängen (Backups können komprimiert, auf einem UNC verfügbar gemacht werden) oder
  • Verwenden Sie einen Verbindungsserver, um dies zu vermeiden (hängt davon ab, wie viele Daten über den Join übertragen werden).

ps: 20GB sind auch 2015 nicht riesig. Aber es ist alles relativ.


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

Geben Sie hier die Bildbeschreibung ein

Sie können ein detailliertes SQL-Skript herunterladen , um das Datenverzeichnis für eine SQL Server-Instanz zu finden


-1

Sie erhalten den Standardspeicherort, wenn Benutzerdatenbank durch diese Abfrage:

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'

funktioniert nicht, wenn sich die Master-Datenbank an einem anderen Speicherort als dem Standardspeicherort befindet (wenn beispielsweise der Standardspeicherort nach dem
Erstellen des
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.