Need script to delete the old backup file from storage blob , the script need to run from managed instance - azure-sql-database

Can anyone help me to get the script to remove the backup file older than 45 days from storage Blob container.
Actually i want to run the script in Managed instance ( PAAS) through SQL server agent job.
Please help me on this.

According this post.
I think you can modifier the PS script. Change $FromDate = ((Get-Date).AddDays(-6)).Date to $FromDate = ((Get-Date).AddDays(-45)).Date . The script is as follows:
#PowerShell Script to delete System Databases .bak files from Azure Block Blob
#-eq = equals
#-ne = not equals
#-lt = less than
#-gt = greater than
#-le = less than or equals
#-ge = greater than or equals
#Set All Variables
$YesterdayDate = ((Get-Date).AddDays(-1)).Date #Get Yesterday date
$FromDate = ((Get-Date).AddDays(-45)).Date #Get 6 Days back date from Today
$BlobType = "Pageblob"
$bacs = Get-ChildItem $location -Filter *.bak
$container="dwhdatabasesbackup"
$StorageAccountName="analytics"
$StorageAccountKey="xxxxxx"
$context = New-AzureStorageContext -StorageAccountName $StorageAccountName -StorageAccountKey $StorageAccountKey
$filelist = Get-AzureStorageBlob -Container $container -Context $context
#Foreach Loop With a Condition $_.LastModified.Date -eq $YesterdayDate to make Sure there was a File Uploaded Yesterday
foreach ($filein$filelist | Where-Object {$_.LastModified.Date -eq $YesterdayDate -and $_.BlobType -eq $BlobType -and ($_.Name -like "*.bak")})
{
$Yesterdayfile = $file.Name
if ($Yesterdayfile -ne $null)
{
$FileFullLength = $Yesterdayfile.Length
$FileNameWithoutDatePart = $Yesterdayfile.SubString(0, $FileFullLength-30)
Write-Output ("File Name Without Date Part: " +$FileNameWithoutDatePart)
#Foreach Loop With a Condition $_.LastModified.Date -lt $FromDate to Remove Files those are 5 Days Old
foreach ($filein$filelist | Where-Object {$_.LastModified.Date -lt $FromDate -and $_.BlobType -eq $BlobType -and ($_.Name -like "$FileNameWithoutDatePart*.bak")})
{
$removefile = $file.Name
$RemoveFileFullLength = $removefile.Length
$ModifiedDate = $file.LastModified.Date
if (($removefile -ne $null) -and ($RemoveFileFullLength -eq $FileFullLength))
{
Write-Output ("Remove File Name: ("+$removefile +") as Modified Date: ("+ $ModifiedDate +") of File is Older Than Date: ("+ $FromDate + ")")
}
}
}
}

Related

Extract values into variables from filename in Powershell

I have a Powershell script to read .sql files from a specific folder and run them against a database depending on the name of the filename.
The filenames are always the same: myDatabase.script.SomeRandomCharacters.csv
There can be many files which is why the script has a foreach loop.
[CmdletBinding()]
param (
[parameter(Mandatory = $true)][ValidateSet('dev')][String]$serverName,
[parameter(Mandatory = $true)][String]$databaseName,
)
$dir = Split-Path $MyInvocation.MyCommand.Path
$scripts = Get-ChildItem $dir | Where-Object { $_.Extension -eq ".sql" } | Where-Object { $_.Name -like "$databaseName*" }
foreach ($s in $scripts) {
$script = $s.FullName
Invoke-Sqlcmd -ServerInstance $serverName -Database $databaseName -InputFile $script
}
The issue here is that if I would have 2 databases "myDatabase" and "myDatabase2", running the script with the former input would run the latter as well since the Where-Object filtering uses an asterisk.
I can't figure out how to modify the script so that I get the absolute value of whatever is before the first fullstop in the filename. What I would also what to do is to validate the value between the first and second fullstops, in the example filename it is script.
Any help is appreciated!
Use the database names to construct a regex pattern that will match either:
param(
[Parameter(Mandatory = $true)][ValidateSet('dev')][String]$ServerName,
[Parameter(Mandatory = $true)][String[]]$DatabaseNames,
)
# Construct alternation pattern like `db1|db2|db3`
$dbNamesEscaped = #($DatabaseNames |ForEach-Object {
[regex]::Escape($_)
}) -join '|'
# Construct pattern with `^` (start-of-string anchor)
$dbNamePattern = '^{0}' -f $dbNamesEscaped
# Fetch scripts associated with either of the database names
$scripts = Get-ChildItem $dir | Where-Object { $_.Extension -eq ".sql" -and $_.Name -match $dbNamePattern }
# ...
You can use the StartsWith function to fix your filter:
$scripts = Get-ChildItem $dir | Where-Object { $_.Extension -eq ".sql" } | Where-Object { $_.Name.StartsWith("$($databaseName).") }

PowerShell code to script out all SQL Server Agent jobs into a single file

I was trying to script out all the SQL Server Agent jobs for category 'Data Warehouse' into a single file
I was able to do it using PowerShell, where every single job creates a single file.
But I need one file for all the SQL Server Agent jobs under category ID = 100 (or Category : = 'Data Warehouse')
Code I'm currently using:
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.Smo') | Out-Null
$serverInstance = "APAAUHC7DB01VD"
$server = New-Object ('Microsoft.SqlServer.Management.Smo.Server') $serverInstance
$jobs = $server.JobServer.Jobs
#$jobs = $server.JobServer.Jobs | where-object {$_.category -eq "100"}
if ($jobs -ne $null)
{
$serverInstance = $serverInstance.Replace("\", "-")
ForEach ( $job in $jobs )
{
$FileName = "C:\SQLBackup\SQLJobs\" + $serverInstance + "_" + $job.Name + ".sql"
$job.Script() | Out-File -filepath $FileName
}
}
Give $FileName a single file name for the whole set. Then you can leave out the whole foreach block:
$FileName = "C:\SQLBackup\SQLJobs\whatever.sql"
$jobs | %{ $_.Script() } | Out-File -filepath $FileName

Remove permissions on a sharepoint sitecollection

So I have a list of sitecollections and with them everyone who have access to the sitecollections. A ; separated csv file, formated like /sites1/sites;AD\User1.
We need to make a cleanup on ~400 sites where we want to remove users beloning to a certain company or being in a certain AD.
I have this information so thats not a problem.
Is there a way to make a powershellscript to remove theese users on theese site collection, in the other output we don't have any list of where they have permission only that they have it somewhere on the site.
I would also need the output format in a good way so we can restore them in a case it would be needed?
Can this be done?
We used below to get the list of users:
$ver = $host | select version
if($Ver.version.major -gt 1) {$Host.Runspace.ThreadOptions = "ReuseThread"}
if(!(Get-PSSnapin Microsoft.SharePoint.PowerShell -ea 0))
{
Add-PSSnapin Microsoft.SharePoint.PowerShell
}
$pathSave = "D:\Script\Output.csv"
$pathRead = "D:\Script\\sites.txt"
write-output = "======================================================================="
[System.Collections.ArrayList]$objectCollection = #();
[System.Collections.ArrayList]$allUsersArray = #();
foreach($line in Get-Content $pathRead)
{
$site = Get-SPSite($line)
$sitecntr = 0;
#write-output " ";
write-output $site.Url;
$allusers = $site.RootWeb.AllUsers;
foreach ($user in $allusers)
{
if (!$user.IsDomainGroup)
{
$sitecntr++;
$outstring = $site.Url + ";" + $user.UserLogin + ";" + $user.Email
$a = $allUsersArray.Add($outstring);
}
}
$outString = "Totalt: " + $sitecntr
if ($sitecntr -ne 0) {
write-output $outstring;
write-output " ";
}
$site.Dispose();
}
write-output ""
write-output "Exporting to csv..."
Out-File -FilePath $pathSave -InputObject $allUsersArray
write-output "Finished! "
write-output ""
This script will ensure reader permissions to the specified user across the site collection.
**Keep in mind:** This is not the right way to deal with permissions issues!
$site = Get-SPSite -Identity "http://mysite/"
$user = Get-SPUser -Identity "mydomain\myuser" -Web $site.RootWeb
$assignment = New-Object Microsoft.SharePoint.SPRoleAssignment($user)
$role = $site.RootWeb.RoleDefinitions[[Microsoft.SharePoint.SPRoleType]::Reader]
$assignment.RoleDefinitionBindings.Add($role);
foreach ($web in $site.AllWebs) {
if ($web.HasUniquePerm) {
$web.RoleAssignments.Add($assignment)
}
}
Note: You need to be Site Collection Admin to use this script.

How to check if SQL Server 2008 R2 database exists using power shell

I have a script for a database which works perfectly, however I ran into a problem where I need an if statement which checks if the database specified by user already exists. If it does, then the script should create a backup of it, if it does not exist, then the script should show an error.
Here is my script
#Loads Assembly
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") | Out-Null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SmoExtended") | Out-Null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.ConnectionInfo") | Out-
Null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SmoEnum") | Out-Null
$server = New-Object ("Microsoft.SqlServer.Management.Smo.Server") "(local)"
$bkdir = "C:\DBbackups" #We define the folder path as a variable
$database = Read-Host "Please Specify Database Name"
$dbs = $server.Databases
#To Backup one Database specify exact name
#To backup multiple database which starts with same name use "*"
foreach ($db in $dbs)
{
if($db.Name -like $database)
{
$dbname = $db.Name
$dt = get-date -format yyyyMMddHHmmss #We use this to create a file name based on the timestamp
$dbBackup = new-object ("Microsoft.SqlServer.Management.Smo.Backup")
$dbBackup.Action = "Database"
$dbBackup.Database = $dbname
$dbBackup.Devices.AddDevice($bkdir + "\" + $dbname + "_db_" + $dt + ".bak", "File")
$dbBackup.SqlBackup($server)
write-host "Database backup is successful for"$dbname
write-host "."
write-host "New Backup file is"$dbname"_db_"$dt".bak"
}
}
write-host "New Backup Location is" $bkdir
This is what i have modified to
foreach ($db in $dbs)
{
if($db.Name -like $database)
{
$dbname = $db.Name
$dt = get-date -format yyyyMMddHHmmss #We use this to create a file name based on the timestamp
$dbBackup = new-object ("Microsoft.SqlServer.Management.Smo.Backup")
$dbBackup.Action = "Database"
$dbBackup.Database = $dbname
$dbBackup.Devices.AddDevice($bkdir + "\" + $dbname + "_db_" + $dt + ".bak", "File")
$dbBackup.SqlBackup($server)
write-host "Database backup is successful for"$dbname `n
write-host "New Backup file is"$dbname"_db_"$dt".bak" `n
}
else {
write-host "invalid"
}
}
Try adding an else to the if ($db.Name -like $database) block if ($db.Name -like $database) { # do current backup stuff }
else { write-output "Database doesn't exist" }

Database relocation, Detach/attach database, MS-SQL-Server-Management-Studio(2012)

In the next week we want to relocate our database from one server to another one.
On http://msdn.microsoft.com/en-us/library/ms187858%28v=sql.110%29.aspx
I read about detaching the database from the old location and attach it to the new location.
The problem is, that I don't have access to the file system of the server, I don't even know where exactly the server is physically located^^
Is there a way to relocate a database from one Server to another without the need to access the file system of the old Server?
You could use the Import/Export tool in SQL Server to copy the data directly which will create a new database in the destination location. The good thing about this is the new DB will work as you might expect since it is created from scratch on the target server, but that also means that you might have old, deprecated syntax in your stored procs or functions or whatever which won't work unless you lower the compatibility level (although that shouldn't be hard). also be aware of any possible collation conflicts (your old server might have SQL_Latin1_General_CP1_CI_AS and the new one might be Latin1_General_CI_AS which can cause equality operations to fail amongst other things).
In addition, if you have a big database then it'll take a long time, but I can't think of any other method off the of of my head which doesn't require some level of access to the file system as you'd still need to get to the file system to take a copy of a backup, or if using a UNC path for the backup the source server would need to be able to write to that location and you'd need to be able to access it afterwards. If anyone else can think of one I'd be interested because it would be a useful bit of knowledge to have tucked away.
Edit:
Should also have mentioned the use of Powershell and SMO - it's not really any different to using the Import/Export wizard but it does allow you to fine tune things. The following is a PS script I have been using to create a copy of a DB (schema only) on a different server to the original but with certain facets missing (NCIs, FKs Indeitites etc) as the copy was destined to be read-only. You could easily extend it to copy the data as well.
param (
[string]$sourceServerName = $(throw "Source server name is required."),
[string]$destServerName = $(throw "Destination server is required."),
[string]$sourceDBName = $(throw "Source database name is required."),
[string]$destDBName = $(throw "Destination database name is required"),
[string]$schema = "dbo"
)
# Add an error trap so that at the end of the script we can see if we recorded any non-fatal errors and if so then throw
# an error and return 1 so that the SQL job recognises there's been an error.
trap
{
write-output $_
exit 1
}
# Append year to destination DB name if it isn't already on the end.
$year = (Get-Date).AddYears(-6).Year
if (-Not $destDBName.EndsWith($year)) {
$destDBName+=$year
}
# Load assemblies.
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.ConnectionInfo") | out-null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") | out-null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SmoExtended") | out-null
# Set up source connection.
$sourceSrvConn = new-object Microsoft.SqlServer.Management.Common.ServerConnection
$sourceSrvConn.ServerInstance = $sourceServerName
$sourceSrvConn.LoginSecure = $false
$sourceSrvConn.Login = "MyLogin"
$sourceSrvConn.Password = "xxx"
# Set up destination connection.
$destSrvConn = new-object Microsoft.SqlServer.Management.Common.ServerConnection
$destSrvConn.ServerInstance = $destServerName
$destSrvConn.LoginSecure = $false
$destSrvConn.Login = "MyLogin"
$destSrvConn.Password = "xxx"
$sourceSrv = New-Object Microsoft.SqlServer.Management.SMO.Server($sourceSrvConn)
$sourceDb = New-Object ("Microsoft.SqlServer.Management.SMO.Database")
$destSrv = New-Object Microsoft.SqlServer.Management.SMO.Server($destSrvConn)
$destDb = New-Object ("Microsoft.SqlServer.Management.SMO.Database")
$tbl = New-Object ("Microsoft.SqlServer.Management.SMO.Table")
$scripter = New-Object Microsoft.SqlServer.Management.SMO.Scripter($sourceSrvConn)
# Get the database objects
$sourceDb = $sourceSrv.Databases[$sourceDbName]
$destDb = $destSrv.Databases[$destDbName]
# Test to see databases exist. Not as easy to test for servers - if you got those wrong then this will fail and throw an error
# so it's down to the user to check their values carefully.
if ($sourceDb -eq $null) {throw "Database '" + $sourceDbName + "' does not exist on server '" + $sourceServerName + "'"}
if ($destDb -eq $null) {throw "Database '" + $destDbName + "' does not exist on server '" + $destServerName + "'"}
# Get source objects.
$tbl = $sourceDb.tables | Where-object { $_.schema -eq $schema -and -not $_.IsSystemObject }
$storedProcs = $sourceDb.StoredProcedures | Where-object { $_.schema -eq $schema -and -not $_.IsSystemObject }
$views = $sourceDb.Views | Where-object { $_.schema -eq $schema -and -not $_.IsSystemObject }
$udfs = $sourceDb.UserDefinedFunctions | Where-object { $_.schema -eq $schema -and -not $_.IsSystemObject }
$catalogs = $sourceDb.FullTextCatalogs
$udtts = $sourceDb.UserDefinedTableTypes | Where-object { $_.schema -eq $schema -and -not $_.IsSystemObject }
$assemblies = $sourceDb.Assemblies | Where-object { -not $_.IsSystemObject }
# Set scripter options to ensure only schema is scripted
$scripter.Options.ScriptSchema = $true;
$scripter.Options.ScriptData = $false;
#Exclude GOs after every line
$scripter.Options.NoCommandTerminator = $false;
$scripter.Options.ToFileOnly = $false
$scripter.Options.AllowSystemObjects = $false
$scripter.Options.Permissions = $true
$scripter.Options.DriForeignKeys = $false
$scripter.Options.SchemaQualify = $true
$scripter.Options.AnsiFile = $true
$scripter.Options.Indexes = $false
$scripter.Options.DriIndexes = $false
$scripter.Options.DriClustered = $true
$scripter.Options.DriNonClustered = $false
$scripter.Options.NonClusteredIndexes = $false
$scripter.Options.ClusteredIndexes = $true
$scripter.Options.FullTextIndexes = $true
$scripter.Options.NoIdentities = $true
$scripter.Options.DriPrimaryKey = $true
$scripter.Options.EnforceScriptingOptions = $true
$pattern = "(\b" + $sourceDBName + "\b)"
$errors = 0
function CopyObjectsToDestination($objects) {
foreach ($o in $objects) {
if ($o -ne $null) {
try {
$script = $scripter.Script($o)
$script = $script -replace $pattern, $destDBName
$destDb.ExecuteNonQuery($script)
} catch {
#Make sure any errors are logged by the SQL job.
$ex = $_.Exception
$message = $o.Name + " " + (Get-Date)
$message += "`r`n"
#$message += $ex.message
$ex = $ex.InnerException
while ($ex.InnerException) {
$message += "`n$ex.InnerException.message"
$ex = $ex.InnerException
}
#Write-Error $o.Name
Write-Error $message # Write to caller. SQL Agent will display this (or at least some of it) in the job step history.
# Need to use Set-Variable or changes to the variable will only be in scope within the function and we want to persist this.
if ($errors -eq 0) {
Set-Variable -Name errors -Scope 1 -Value 1
}
}
}
}
}
# Output the scripts
CopyObjectsToDestination $assemblies
CopyObjectsToDestination $tbl
CopyObjectsToDestination $udfs
CopyObjectsToDestination $views
CopyObjectsToDestination $storedProcs
CopyObjectsToDestination $catalogs
CopyObjectsToDestination $udtts
# Disconnect from databases cleanly.
$sourceSrv.ConnectionContext.Disconnect()
$destSrv.ConnectionContext.Disconnect()
# Did we encounter any non-fatal errors along the way (SQL errors and suchlike)? If yes then throw an exception which tells the
# user to check the log files.
if ($errors -eq 1) {
throw "Errors encountered - see log file for details"
}