Yes, I am trying to do a version of log-shipping that doesn’t require linking any servers and allows them to be in different domains. I also know I am crazy.
Now that we have that out of the way, let me show you some of the stuff I am doing! Loading a table from multiple file locations using Powershell. It will go and read what is in the directories and load them into a table for me (Oh my goodness, I knew Powershell was cool, but it took me so long to figure this out, that I was super proud with how fast it loaded).
First, the housekeeping. Create two tables in a DBA Database:
CREATE TABLE [dbo].[LogshippingFile](
[FileName] [varchar](500) NULL,
[FileLocation] [varchar](1000) NULL,
[FileType] [char](1) NULL,
[Origin] [varchar](50) NULL,
[ForDatabase] [varchar](50) NULL,
[CreatedDate] [datetime2](7) NULL,
[Applied] [bit] NOT NULL
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[LogshippingFile] ADD CONSTRAINT [DF_LogshippingFiles_Applied] DEFAULT ((0)) FOR [Applied]
CREATE TABLE [dbo].[Config](
[Origin] [varchar](50) NULL,
[FileLocation] [varchar](500) NULL,
[Type] [char](1) NULL
) ON [PRIMARY]
In the Config table, I am going to put the common name for the database I am restoring so the rows will look like this:
Origin | FileLocation | Type |
Batman | J:\FullBackups\Batman | B |
Batman | J:\LogBackups\Batman | L |
Superman | J:\FullBackups\Superman | B |
Superman | J:\LogBackups\Superman | L |
Yay! Now we can get to the fun stuff. This is how I set up the Powershell:
# Credentials for connection to SQL Server.
$username = 'Batgirl'
$password = '!Pennyworth54'
#Connecting to the SQL Server and Query to get FileLocation and Origin from the Config table.
$DS = Invoke-Sqlcmd -ServerInstance "BatCave01" -Database "DBAStuff" -Username $username -Password $password -Query "SELECT FileLocation, Origin FROM Config" -As DataSet
#Magic that puts my two columns into variables
$data = $DS.Tables[0].Rows
$data
ForEach ($Row in $data) {
$FileLocation = $Row.FileLocation
$Origin = $Row.Origin
#Build my insert statement so Powershell knows what to expect.
#gets all the filenames and loads them into the table.
$sqlstatement=@'
INSERT INTO LogshippingFile
(
FileName,
FileLocation,
FileType,
Origin,
ForDatabase
)
VALUES (
'{0}',
'{1}',
'{2}',
'{3}',
'{4}'
)
'@
Get-ChildItem -Recurse $FileLocation |
select Name,FullName,
@{
Label='FileType'
Expression={($FileLocation.Substring(10,1))}}, @{
Label='Origin'
Expression={($Origin)}}, @{
Label='ForDatabase'
Expression={'Gryphon_'+($Origin)}} |
# @{Label="Length";Expression={$_.Length / 1024KB -as [int] }} |
ForEach-Object {
$SQL = $sqlstatement -f $_.name,$_.FullName, $_.FileType, $_.Origin, $_.ForDatabase #, $_.Length
Invoke-sqlcmd -Username $username -Password $password -Query $SQL -ServerInstance “BatCave01” -database “DBAStuff” -Querytimeout 0
}
}
Now we have all this data in the table, what do we do with it? Guess you will have to tune in again to this same Bat channel.
The song for this post is Matt Nathanson’s Kiss Quick