I have about 300 databases, (most) with a table, [File], and a column [Location] that holds a UNC path to a file. While migrating SANs, some needed files may not have been copied.
This issue materializes when a web GUI attempts to open a file from the table that doesn't exist. I've been trying to put together some PowerShell to iterate over the locations and run Test-Path, since that seems like the most direct way to perform a check.
I'm running into problems in two places:
I also need to check if the file exists in the old location, so I perform the REPLACE on [Location] to get the old SAN name in my query, but can't seem to parse the output correctly.
I would like to Copy-Item directly from what passes the test, but again, can't seem to parse the output correctly.
What am I missing? It's really the last two lines I can't figure out.
Code is below, and hacked together from an example HERE:
$MS='Microsoft.SQLServer'
@('.SMO') |
foreach-object {
if ([System.Reflection.Assembly]::LoadWithPartialName("$MS$_") -eq $null)
{"missing SMO component $MS$_"}
}
set-psdebug -strict
$ErrorActionPreference = "stop" #
$My="$MS.Management.Smo" #
@("Instance1","Instance2", "Instance3") |
foreach-object {new-object ("$My.Server") $_ } |
Where-Object {$_.ServerType -ne $null} |
Foreach-object {$_.Databases -match "DataPattern[0-9]"} |
Foreach-object {
$Db=$_
$_.ExecuteWithResults(‘IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS AS c WHERE TABLE_SCHEMA = ''schema'' AND TABLE_NAME = ''File'' AND COLUMN_NAME = ''Location'') SELECT [Location], REPLACE(Location, ''Computer'', ''Old-Computer'') [OldLocation] FROM [schema].[File]’).Tables[0]}|
ForEach-Object {if(!(Test-Path -Path $_ ) -And (Test-Path -Path $_ -eq True)) {
Copy-Item $_ $_ -ErrorAction Continue } }
Thanks
EDIT:
Ended up getting it to work with the below two lines of code, but it's incredibly slow if I select anything more than the top 50 lines from each table. Any tips on speeding this up?
ForEach-Object {if(!(Test-Path -Path $_.Location ) -And (Test-Path -Path $_.OldLocation -eq True)) {
Copy-Item $_.OldLocation $_.Location -ErrorAction Continue } }
Best Answer
PowerShell offers the ability to do things in many different ways, so this is just the method I would do in solving the problem at hand, based on the information provided.
SMO offers the ability to check the table class to more efficiently find the database in question that contain the table and column specified; instead of trying to use INFORMATION schema views that some folks have a case against ever using them.
I would break this up into sections that will make it more easy to debug. I am assuming you are not worried what UNC path is tied to which server, just making sure the UNC path exist and the file has been moved. So I would first pull all the UNC paths from any database I find the table and column exist.
Now in regards to changing the path to the old location I would do something like this when I am iterating through the
$uncPaths
variable: