diff --git a/MySQL/MySQL - Blocked Processes query.sql b/MySQL/MySQL - Blocked Processes query.sql
new file mode 100644
index 0000000..bccd16c
--- /dev/null
+++ b/MySQL/MySQL - Blocked Processes query.sql
@@ -0,0 +1,30 @@
+SELECT p1.id waiting_thread,
+ p1.user waiting_user,
+ p1.host waiting_host,
+ it1.trx_query waiting_query,
+ ilw.requesting_engine_transaction_id waiting_transaction,
+ ilw.blocking_engine_lock_id blocking_lock,
+ il.lock_mode blocking_mode,
+ il.lock_type blocking_type,
+ ilw.blocking_engine_transaction_id blocking_transaction,
+ CASE it.trx_state
+ WHEN 'LOCK WAIT'
+ THEN it.trx_state
+ ELSE p.state end blocker_state,
+ concat(il.object_schema,'.', il.object_name) as locked_table,
+ it.trx_mysql_thread_id blocker_thread,
+ p.user blocker_user,
+ p.host blocker_host,
+ p.info blocker_query
+FROM performance_schema.data_lock_waits ilw
+ JOIN performance_schema.data_locks il
+ ON ilw.blocking_engine_lock_id = il.engine_lock_id
+ AND ilw.blocking_engine_transaction_id = il.engine_transaction_id
+ JOIN information_schema.innodb_trx it
+ ON ilw.blocking_engine_transaction_id = it.trx_id
+ join information_schema.processlist p
+ ON it.trx_mysql_thread_id = p.id
+ join information_schema.innodb_trx it1
+ ON ilw.requesting_engine_transaction_id = it1.trx_id
+ join information_schema.processlist p1
+ ON it1.trx_mysql_thread_id = p1.id
\ No newline at end of file
diff --git a/MySQL/MySQL - Monitoring queries.sql b/MySQL/MySQL - Monitoring queries.sql
new file mode 100644
index 0000000..61cc78c
--- /dev/null
+++ b/MySQL/MySQL - Monitoring queries.sql
@@ -0,0 +1,111 @@
+/* Increase the length of text returned in queries from default 64k */
+SET @sys.statement_truncate_len := 1024 ;
+
+/* Current queries and connections */
+SELECT *
+FROM INFORMATION_SCHEMA.PROCESSLIST
+-- where command <> 'Sleep'
+ORDER BY TIME DESC;
+
+
+-- CALL mysql.rds_kill(8675352);
+
+
+/* MySQL version and Aurora version */
+select @@version, @@aurora_version;
+
+set transaction isolation level read uncommitted;
+
+/* Blocked queries - similar to sp_whoisactive */
+SELECT p1.id waiting_thread,
+ p1.user waiting_user,
+ p1.host waiting_host,
+ it1.trx_query waiting_query,
+ ilw.requesting_engine_transaction_id waiting_transaction,
+ ilw.blocking_engine_lock_id blocking_lock,
+ il.lock_mode blocking_mode,
+ il.lock_type blocking_type,
+ ilw.blocking_engine_transaction_id blocking_transaction,
+ CASE it.trx_state
+ WHEN 'LOCK WAIT'
+ THEN it.trx_state
+ ELSE p.state end blocker_state,
+ concat(il.object_schema,'.', il.object_name) as locked_table,
+ it.trx_mysql_thread_id blocker_thread,
+ p.user blocker_user,
+ p.host blocker_host,
+ p.info blocker_query
+FROM performance_schema.data_lock_waits ilw
+ JOIN performance_schema.data_locks il
+ ON ilw.blocking_engine_lock_id = il.engine_lock_id
+ AND ilw.blocking_engine_transaction_id = il.engine_transaction_id
+ JOIN information_schema.innodb_trx it
+ ON ilw.blocking_engine_transaction_id = it.trx_id
+ join information_schema.processlist p
+ ON it.trx_mysql_thread_id = p.id
+ join information_schema.innodb_trx it1
+ ON ilw.requesting_engine_transaction_id = it1.trx_id
+ join information_schema.processlist p1
+ ON it1.trx_mysql_thread_id = p1.id;
+
+
+/* More information on the below queries can be found here: https://github.com/mysql/mysql-sys/tree/master/views/p_s */
+
+/* Sessions without system sessions */
+SELECT *
+FROM sys.session
+ORDER BY time DESC;
+
+/* Table locks */
+SELECT *
+FROM sys.schema_table_lock_waits;
+
+/* Queries with Errors */
+SELECT *
+FROM sys.statements_with_errors_or_warnings
+WHERE last_seen > '2024-02-01'
+ and exec_count > 100
+ORDER BY error_pct DESC LIMIT 10;
+
+/* Slow queries */
+SELECT *
+FROM sys.statements_with_runtimes_in_95th_percentile;
+
+/* Execution times for types of statements/users */
+SELECT *
+FROM sys.user_summary_by_statement_type;
+
+
+/* Find tables with most table scans */
+SELECT *
+FROM sys.schema_tables_with_full_table_scans
+LIMIT 10;
+
+/* Wait Types - Average */
+SELECT *
+FROM sys.wait_classes_global_by_avg_latency
+WHERE event_class != 'idle';
+
+/* Wait Types - Global */
+SELECT *
+FROM sys.wait_classes_global_by_latency;
+
+/* Query Analyzer view - ordered by Total_Latency */
+SELECT *
+FROM sys.statement_analysis
+LIMIT 10;
+
+/* Indexes - Redundant Indexes */
+SELECT *
+FROM sys.schema_redundant_indexes;
+
+/* Indexes - Unused Indexes */
+SELECT *
+FROM sys.schema_unused_indexes;
+
+
+/* Find text in Stored Procedures */
+SELECT *
+FROM information_schema.routines
+WHERE routine_definition LIKE '%BOM_BATCH_CONTROL%'
+LIMIT 10;
\ No newline at end of file
diff --git a/PowerShell/Backup and Restore DBs for DAG.ps1 b/PowerShell/Backup and Restore DBs for DAG.ps1
new file mode 100644
index 0000000..0430f79
--- /dev/null
+++ b/PowerShell/Backup and Restore DBs for DAG.ps1
@@ -0,0 +1,32 @@
+cls
+
+$FromSQLlistener = 'AGXSQLOP1LS.ad.pquadnt.com'
+$FromAvailabilityGroup = 'AGXSQLOP'
+$backupPath = '\\ad.pquadnt.com\pc-sqlbackup\backups\Migration\'
+$ToSQLListener = 'AGXEcommLS.ad.pquadnt.com'
+
+
+$databases = Get-DbaAgDatabase -SqlInstance $FromSQLlistener -AvailabilityGroup $FromAvailabilityGroup
+
+foreach ($db in $databases){
+ $DBName = $db.Name
+ $DBBackupPath = $backupPath + $DBName
+ $DestinationDataDir = 'S:\DB_DATA\' + $DBName
+ $DestinationLogDir = 'S:\DB_LOGS\' + $DBName
+
+ $DBName
+
+ if ($DBName -ne 'AG_TEST' -and $DBName -ne 'Archive'){
+ Backup-DbaDatabase -SqlInstance $FromSQLlistener -Database $DBName -Path $DBBackupPath -Checksum -CompressBackup -BuildPath -FileCount 4 -BufferCount 20 -MaxTransferSize 1048576
+
+ ##Backup-DbaDatabase -SqlInstance $FromSQLlistener -Database $DBName -Type Log -Path $DBBackupPath -Checksum -CompressBackup -BuildPath
+ }
+
+ if ($DBName -ne 'AG_TEST'){
+ Backup-DbaDatabase -SqlInstance $FromSQLlistener -Database $DBName -Type Log -Path $DBBackupPath -Checksum -CompressBackup -BuildPath
+
+ Restore-DbaDatabase -SqlInstance $ToSQLListener -DatabaseName $DBName -Path $DBBackupPath -DestinationDataDirectory $DestinationDataDir -DestinationLogDirectory $DestinationLogDir -WithReplace -NoRecovery -BufferCount 20 -MaxTransferSize 1048576
+
+ Invoke-DbaQuery -SqlInstance $ToSQLListener -Query "ALTER DATABASE [$DBName] SET HADR AVAILABILITY GROUP = [AGXDistributed]"
+ }
+}
\ No newline at end of file
diff --git a/PowerShell/Create CNames.ps1 b/PowerShell/Create CNames.ps1
new file mode 100644
index 0000000..fc23932
--- /dev/null
+++ b/PowerShell/Create CNames.ps1
@@ -0,0 +1,27 @@
+cls
+
+
+$DBConnection = "dev2sqlop01.ad.pquadnt.com"
+
+$dsCNAMES = Invoke-Sqlcmd -Query "SELECT [Dev3 Server] AS DevServer, [Dev3 CName] AS DevCName FROM DAN_TEST.dbo.PC_CNames WHERE [Dev3 Server] <> ''" -ServerInstance $DBConnection
+
+foreach ($rowCName in $dsCNAMES){
+ $ServerName = $rowCName.DevServer
+ $CName = $rowCName.DevCName
+
+
+ $change1 = New-Object Amazon.Route53.Model.Change
+ $change1.Action = "CREATE"
+ $change1.ResourceRecordSet = New-Object Amazon.Route53.Model.ResourceRecordSet
+ $change1.ResourceRecordSet.Type = "CNAME"
+ $change1.ResourceRecordSet.TTL = 300
+ $change1.ResourceRecordSet.Name = "$CName"
+ $change1.ResourceRecordSet.ResourceRecords.Add(@{Value="$ServerName"})
+
+ $params = @{
+ HostedZoneId=""
+ ChangeBatch_Change=$change1
+ }
+
+ Edit-R53ResourceRecordSet @params
+}
diff --git a/PowerShell/Deploy from SQLPROJ.ps1 b/PowerShell/Deploy from SQLPROJ.ps1
new file mode 100644
index 0000000..b8c637d
--- /dev/null
+++ b/PowerShell/Deploy from SQLPROJ.ps1
@@ -0,0 +1,21 @@
+cls
+
+## These are connection variables to SQL Server installed on my laptop, but can be any SQL Server instance
+$TargetConnection = "Data Source=localhost;Integrated Security=True"
+$TargetDB = "AdventureWorks2017"
+
+## Local Repo path
+$RepoPath = "C:\Working\GitHub\POC-DB-CICD\POC-DB-CICD\POC-DB-CICD.sqlproj"
+
+## Path to place the DACPAC file
+$OutPath = 'C:\Working\GitHub\'
+
+
+## This part build a DACPAC, comparing the .sqlproj to the destination server in the TargetConnection and TargetDB variables
+$msbuild = "C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe"
+$collectionOfArgs = @("$RepoPath", '/target:Build', "/p:TargetConnectionString=""$TargetConnection""", "/p:TargetDatabase=$TargetDB", "/p:OutDir=$OutPath")
+& $msbuild $collectionOfArgs
+
+
+## This publishes the changes in the dacpac to the server
+Publish-DbaDacPackage -SqlInstance localhost -Database AdventureWorks2017 -Path C:\Working\GitHub\POC-DB-CICD.dacpac -OutputPath $OutPath
\ No newline at end of file
diff --git a/PowerShell/Generate Backup Scripts.ps1 b/PowerShell/Generate Backup Scripts.ps1
new file mode 100644
index 0000000..aac650e
--- /dev/null
+++ b/PowerShell/Generate Backup Scripts.ps1
@@ -0,0 +1,102 @@
+cls
+Set-DbatoolsInsecureConnection -SessionOnly
+
+##$Servers = @('FE4SQL21.proflowers.com','FE4SQL22.proflowers.com','FE4SQL23.proflowers.com','BE4SQL23.proflowers.com','RPT3SQL25.proflowers.com')
+$Servers = @('WMS4SQL31.proflowers.com')
+
+foreach ($Server in $Servers){
+ $FromServer = $Server
+ $FromServer
+
+ $AvailabilityGroups = Get-DbaAvailabilityGroup -SqlInstance $FromServer
+
+ foreach ($AG in $AvailabilityGroups){
+ if ($AG.ComputerName -eq $AG.PrimaryReplica){
+ foreach($DB in $AG.AvailabilityDatabases){
+ $DBName = $DB.name
+ $DBName
+ $DestDataPath = $ToDataPath + $DBName
+ $DestLogPath = $ToLogPath + $DBName
+ $Bak = $BackupDirectory + "$ClusterName" + '$' + $AG.AvailabilityGroup + '\' + $DBName + '\'
+
+ $Query = ";WITH cteLatestFullBackup AS
+ (
+ SELECT bs.database_name AS DBName, MAX(bs.backup_set_id) AS backup_set_id
+ FROM msdb.dbo.backupset bs
+ WHERE bs.database_name = '$DBName'
+ AND bs.type = 'D'
+ AND bs.is_copy_only = 0
+ GROUP BY bs.database_name
+ ),
+ cteFilePaths AS
+ (
+ SELECT
+ CASE
+ WHEN bf.file_type = 'D' THEN
+ ' MOVE N''' + bf.logical_name + ''' TO N''' + 'S:\DB_DATA\' + lfb.DBName + '\' + FName.FName + ''''
+ ELSE
+ ' MOVE N''' + bf.logical_name + ''' TO N''' + 'S:\DB_LOGS\' + lfb.DBName + '\' + FName.FName + ''''
+ END AS MoveCommand
+ FROM msdb.dbo.backupfile bf
+ INNER JOIN cteLatestFullBackup lfb
+ ON lfb.backup_set_id = bf.backup_set_id
+ CROSS APPLY
+ (VALUES(SUBSTRING(bf.physical_name, LEN(bf.physical_name) - CHARINDEX('\',Reverse(bf.physical_name))+2, LEN(bf.physical_name)))) AS FName (FName)
+ ),cteConcatFileMoves AS
+ (
+ SELECT STUFF(
+ (SELECT ', ' + cfp.MoveCommand
+ FROM cteFilePaths cfp
+ FOR XML PATH('')
+ ),1,1,'') AS MovePath
+ ),cteBackupChain AS
+ (
+
+ SELECT 0 AS backup_set_id, ' EXECUTE AS LOGIN = ''sa'';' AS CommandSet
+ UNION ALL
+ SELECT b.backup_set_id
+ ,'RESTORE DATABASE ' + lfb.DBName + ' FROM ' +
+ STUFF(
+ (SELECT ', DISK = ''' + mf.physical_device_name + ''''
+ FROM msdb.dbo.backupmediafamily mf
+ WHERE mf.media_set_id = b.media_set_id
+ ORDER BY mf.family_sequence_number ASC
+ FOR XML PATH('')
+ ),1,1,'')
+ + ' WITH REPLACE, ' + 'FILE = ' + CONVERT(VARCHAR(10), b.position) + ', ' + cfm.MovePath + ', STATS=5, NORECOVERY;' AS CommandSet
+ FROM msdb.dbo.backupset b
+ INNER JOIN msdb.dbo.backupmediafamily mf ON b.media_set_id = mf.media_set_id
+ CROSS JOIN cteConcatFileMoves cfm
+ INNER JOIN cteLatestFullBackup lfb
+ ON lfb.backup_set_id = b.backup_set_id
+ UNION ALL
+ SELECT b.backup_set_id
+ ,'RESTORE LOG ' + lfb.DBName + ' FROM ' +
+ STUFF(
+ (SELECT ', DISK = ''' + mf.physical_device_name + ''''
+ FROM msdb.dbo.backupmediafamily mf
+ WHERE mf.media_set_id = b.media_set_id
+ ORDER BY mf.family_sequence_number ASC
+ FOR XML PATH('')
+ ),1,1,'')
+ + ' WITH ' + 'FILE = ' + CONVERT(VARCHAR(10), b.position) + ', STATS=5,NORECOVERY;'
+ FROM msdb.dbo.backupset b
+ INNER JOIN msdb.dbo.backupmediafamily mf ON b.media_set_id = mf.media_set_id
+ CROSS JOIN cteLatestFullBackup lfb
+ WHERE b.database_name = '$DBName'
+ AND b.backup_set_id >= lfb.backup_set_id
+ AND b.backup_set_id < 999999999
+ AND b.type = 'L'
+ )
+ SELECT bc.CommandSet
+ FROM cteBackupChain bc
+ ORDER BY bc.backup_set_id;"
+
+ ##$Query
+ $RestoreCmds = Invoke-Sqlcmd -ServerInstance $FromServer -QueryTimeout 0 -Query $Query
+ $RestoreCmdsNoHdr = ($RestoreCmds | Format-Table -HideTableHeaders| Out-String -Width 5000).trim()
+ $RestoreCmdsNoHdr | Out-File "S:\Install\$DBname.sql" -Encoding utf8 -Width 5000
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/PowerShell/Get EBS Snapshots.ps1 b/PowerShell/Get EBS Snapshots.ps1
new file mode 100644
index 0000000..d1313ef
--- /dev/null
+++ b/PowerShell/Get EBS Snapshots.ps1
@@ -0,0 +1,34 @@
+cls
+
+
+
+
+
+$output = @()
+# Get all snapshots
+$snapshots = Get-EC2Snapshot -Region us-east-1 ##| Where-Object { $_.Instances.Tags.Value -eq 'db-prod' }
+
+foreach ($snapshot in $snapshots){
+ $snapshotId = $snapshot.snapshotId
+ $snapshotName = ($snapshot.Tags | Where-Object { $_.Key -eq 'Name' }).Value
+ $snapshotSizeGB = $snapshot.VolumeSize
+ $snapshotDate = $snapshot.StartTime
+ $snapshotDesc = $snapshot.Description
+
+ ##$snapshot
+ $object = New-Object PSObject -Property @{
+ "snapshotId" = $snapshotId
+ "snapshotName" = $snapshotName
+ "snapshotSizeGB" = $snapshotSizeGB
+ "snapshotDate" = $snapshotDate
+ "snapshotDesc" = $snapshotDesc
+
+ }
+
+ $output += $object
+}
+
+
+$output | Export-Csv -Path "C:\Temp\PC_Prod_EBS_Snapshots2.csv" -NoTypeInformation
+
+Write-Output "CSV file 'PC_Prod_EBS_Snapshots.csv' has been exported."
\ No newline at end of file
diff --git a/PowerShell/Get EC2 Volumes.ps1 b/PowerShell/Get EC2 Volumes.ps1
new file mode 100644
index 0000000..260817d
--- /dev/null
+++ b/PowerShell/Get EC2 Volumes.ps1
@@ -0,0 +1,43 @@
+
+cls
+
+
+
+
+$output = @()
+
+$stoppedInstances = Get-EC2Instance -Region us-east-1 | Where-Object { $_.Instances.State.Name -eq 'stopped'} ## -and $_.Instances.Tags.Value -eq 'db-prod' }
+
+# Loop through stopped instances to find attached volumes
+foreach ($instance in $stoppedInstances) {
+ $instanceId = $instance.Instances.InstanceId
+ ##$instanceId
+ $instanceName = ($instance.Instances.Tags | Where-Object { $_.Key -eq 'Name' }).Value
+
+ $volumes = Get-EC2Volume -Region us-east-1 | Where-Object { $_.Attachments.InstanceId -eq $instanceId }
+ # Output information about each volume
+ foreach ($volume in $volumes) {
+ $volumeId = $volume.VolumeId
+ $sizeGB = $volume.Size
+ $state = $volume.State
+ $type = $volume.VolumeType
+ $attachment = $volume.Attachments | Where-Object { $_.InstanceId -eq $instanceId }
+ $deleteOnTermination = $attachment.DeleteOnTermination
+
+ $object = New-Object PSObject -Property @{
+ "InstanceName" = $instanceName
+ "InstanceId" = $instanceId
+ "VolumeId" = $volumeId
+ "Type" = $type
+ "SizeGB" = $sizeGB
+ "DeleteOnTermination" = $deleteOnTermination
+
+ }
+
+ $output += $object
+ }
+}
+
+$output | Export-Csv -Path "C:\Temp\PC_Prod_EBS_Volumes_with_Instance.csv" -NoTypeInformation
+
+Write-Output "CSV file 'EBS_Volumes_with_Instance.csv' has been exported."
\ No newline at end of file
diff --git a/PowerShell/Get Unattached Volumes.ps1 b/PowerShell/Get Unattached Volumes.ps1
new file mode 100644
index 0000000..abfa51b
--- /dev/null
+++ b/PowerShell/Get Unattached Volumes.ps1
@@ -0,0 +1,28 @@
+cls
+
+
+
+
+$output = @()
+$volumes = Get-EC2Volume -Region us-east-1 -Filter @{'Name'='status'; 'Values'='available'}
+
+ foreach ($volume in $volumes) {
+ $volumeId = $volume.VolumeId
+ $sizeGB = $volume.Size
+ $state = $volume.State
+ $type = $volume.VolumeType
+
+ $object = New-Object PSObject -Property @{
+ "VolumeId" = $volumeId
+ "Type" = $type
+ "SizeGB" = $sizeGB
+
+ }
+
+ $output += $object
+
+}
+
+$output | Export-Csv -Path "C:\Temp\PC_Prod_EBS_Unattached_Volumes.csv" -NoTypeInformation
+
+Write-Output "CSV file 'PC_Prod_EBS_Unattached_Volumes.csv' has been exported."
\ No newline at end of file
diff --git a/PowerShell/PC - GDPR Delete.ps1 b/PowerShell/PC - GDPR Delete.ps1
new file mode 100644
index 0000000..e29bab5
--- /dev/null
+++ b/PowerShell/PC - GDPR Delete.ps1
@@ -0,0 +1,55 @@
+##
+## This script will process GDPR Delete requests by finding the CustomerId and FL_CustomerID as well as any orders by an Email address
+## Developed: 2022-04-18
+##
+
+
+## $EmailToPurgeArray can be a comma delimited list (i.e. "dan@planetart.com","igor@planetart.com")
+$EmailsToPurgeArray = "bribaysara@yahoo.com"
+
+
+
+## MAIN ##
+cls
+##Variables for connections
+$OLTPConnection = "FE4SQL21.proflowers.com"
+$PaymentVaultConnection = "FE4SQL23.proflowers.com"
+
+
+## Loop through each Email in the array
+foreach ($Email in $EmailsToPurgeArray) {
+ Write-Output "Processing $Email"
+ ## Get FL_CustomerID
+ $dsCustomers = Invoke-Sqlcmd -Query "SELECT fc.FL_CustomerID, CustomerID FROM OLTP.dbo.FL_Customer AS fc WHERE fc.email = '$Email'" -ServerInstance "$OLTPConnection" -As DataSet
+
+ $dsCustomers.Count
+ ## check to see if any customers where found, and if so proceed with purge
+ if ($dsCustomers.Count -gt 0) {
+ $FL_CustomerID = $dsCustomers.Tables[0].Rows | %{ echo "$($_['FL_CustomerID'])" }
+ $CustomerId = $dsCustomers.Tables[0].Rows | %{ echo "$($_['CustomerID'])" }
+
+ ## Get list of OrderIDs
+ $dsOrders = Invoke-Sqlcmd -Query "SELECT po.orderID FROM OLTP.dbo.PF_Orders AS po WHERE po.email = '$Email'" -ServerInstance "$OLTPConnection" -As DataSet
+
+ ## Loop through OrderIDs (if they exist) and execute usp_iu_OrderCreditCard procs in Payment Vault
+ if ($dsOrders.Count -gt 0) {
+ $dsOrders.Tables[0] | foreach {
+ $orderID = $_.orderId
+
+ Invoke-Sqlcmd -Query "EXEC PaymentVault.dbo.usp_iu_OrderCreditCard @OrderID = N'$orderID', @CardHolderName = N'GDPR_PURGE',@CreditCardNumber = N'PURGE_GDPR',
+ @CreditCardLastFour = N'GDPR', @CreditCardExpiration = N'12/12',@CreditCardType = NULL,@UserName = N'arief',
+ @FL_CustomerID = NULL, @SaveCard = 0, @PF_OrdersID = NULL, @CryptoDescriptorName = NULL, @CalyxCustomerID = NULL, @EnableCustomerFeed = 0;" `
+ -Database 'PaymentVault' -ServerInstance "$PaymentVaultConnection"
+ }
+ }
+
+ ## Exec usp_del_CustomerByFL_CustomerID proc in PaymentVault
+ Invoke-Sqlcmd -Query "EXEC PaymentVault.dbo.usp_del_CustomerByFL_CustomerID @FL_CustomerID = '$FL_CustomerID'" -Database 'PaymentVault' -ServerInstance "$PaymentVaultConnection"
+
+ ## Exec usp_AccMgmt_PurgeCustomer_GDPR_Data proc in OLTP
+ Invoke-Sqlcmd -Query "EXEC OLTP.dbo.usp_AccMgmt_PurgeCustomer_GDPR_Data @Email = '$Email', @CustomerID = '$CustomerId'" -Database 'OLTP' -ServerInstance "$OLTPConnection"
+ }
+ else {
+ Write-Output " Could not find CustomerId for $Email"
+ }
+}
\ No newline at end of file
diff --git a/PowerShell/PC - Purge Customer PII data for customers deleted in Archive.ps1 b/PowerShell/PC - Purge Customer PII data for customers deleted in Archive.ps1
new file mode 100644
index 0000000..c51b390
--- /dev/null
+++ b/PowerShell/PC - Purge Customer PII data for customers deleted in Archive.ps1
@@ -0,0 +1,16 @@
+
+
+## MAIN ##
+cls
+##Variables for connections
+$OLTPConnection = "fe4sql21"
+$ArchiveConnection = "rpt3sql25"
+
+$dsCustomers = Invoke-Sqlcmd -Query "SELECT pcpar.CustomerID, fc.email FROM Archive.dbo.PC_CustomerPurgeAudit_Repository AS pcpar INNER JOIN oltp.dbo.FL_Customer AS fc ON fc.customerID = pcpar.CustomerID WHERE pcpar.IsDeleted = 1 AND fc.email NOT LIKE '%_GDPR_XXX_OPTOUT%' AND NOT EXISTS (SELECT 1 FROM OLTP.dbo.PF_Orders AS po WHERE po.customerID = pcpar.customerID )" -ServerInstance "$ArchiveConnection" -As DataSet
+
+ foreach ($dsCustomer in $dsCustomers.Tables[0].Rows){
+ $CustomerId = $dsCustomer[0]
+ $Email = $dsCustomer[1]
+
+ Invoke-Sqlcmd -Query "EXEC OLTP.dbo.usp_AccMgmt_PurgeCustomer_GDPR_Data @Email = '$Email', @CustomerID = '$CustomerId', @RequestedBy = 'Archive PII Purge'" -Database 'OLTP' -ServerInstance "$OLTPConnection"
+ }
\ No newline at end of file
diff --git a/PowerShell/Rollback Commerce-Live CNAMEs - Copy.ps1 b/PowerShell/Rollback Commerce-Live CNAMEs - Copy.ps1
new file mode 100644
index 0000000..9be3444
--- /dev/null
+++ b/PowerShell/Rollback Commerce-Live CNAMEs - Copy.ps1
@@ -0,0 +1,28 @@
+cls
+## Copy and paste access key info here
+
+## Update access key info above
+
+
+$NewEndpoint = ""
+$HostedZoneId = "" ## cafepress.io
+$CNAMEArray = @('')
+
+foreach ($CName in $CNAMEArray){
+
+ $change1 = New-Object Amazon.Route53.Model.Change
+ $change1.Action = "UPSERT"
+ $change1.ResourceRecordSet = New-Object Amazon.Route53.Model.ResourceRecordSet
+ $change1.ResourceRecordSet.Type = "CNAME"
+ $change1.ResourceRecordSet.TTL = 300
+ $change1.ResourceRecordSet.Name = "$CName"
+ $change1.ResourceRecordSet.ResourceRecords.Add(@{Value="$NewEndpoint"})
+
+ $params = @{
+ HostedZoneId="$HostedZoneId"
+ ChangeBatch_Change=$change1
+ }
+
+ Edit-R53ResourceRecordSet @params
+ $change1.ResourceRecordSet.Name
+}
diff --git a/PowerShell/Rollback Shared-Live CNAMEs - Copy.ps1 b/PowerShell/Rollback Shared-Live CNAMEs - Copy.ps1
new file mode 100644
index 0000000..ef3b657
--- /dev/null
+++ b/PowerShell/Rollback Shared-Live CNAMEs - Copy.ps1
@@ -0,0 +1,29 @@
+cls
+## Copy and paste access key info here
+
+## Update access key info above
+
+
+$NewEndpoint = "" ## !! Update Endpoint here !!
+
+$HostedZoneId = "" ## cafepress.io
+$CNAMEArray = @('')
+
+foreach ($CName in $CNAMEArray){
+
+ $change1 = New-Object Amazon.Route53.Model.Change
+ $change1.Action = "UPSERT"
+ $change1.ResourceRecordSet = New-Object Amazon.Route53.Model.ResourceRecordSet
+ $change1.ResourceRecordSet.Type = "CNAME"
+ $change1.ResourceRecordSet.TTL = 300
+ $change1.ResourceRecordSet.Name = "$CName"
+ $change1.ResourceRecordSet.ResourceRecords.Add(@{Value="$NewEndpoint"})
+
+ $params = @{
+ HostedZoneId="$HostedZoneId"
+ ChangeBatch_Change=$change1
+ }
+
+ Edit-R53ResourceRecordSet @params
+ $change1.ResourceRecordSet.Name
+}
diff --git a/PowerShell/Rolling restore of AG databases.ps1 b/PowerShell/Rolling restore of AG databases.ps1
new file mode 100644
index 0000000..88d30e2
--- /dev/null
+++ b/PowerShell/Rolling restore of AG databases.ps1
@@ -0,0 +1,26 @@
+cls
+## Variables to Change
+$FromServer = ''
+$ToServer = ''
+
+
+## Static variables that don't change
+$ToDataPath = 'S:\DB_DATA\'
+$ToLogPath = 'S:\DB_LOGS\'
+$BackupDirectory = ''
+
+$AvailabilityGroups = Get-DbaAvailabilityGroup -SqlInstance $FromServer
+$Cluster = Get-DbaWsfcCluster -ComputerName $FromServer
+$ClusterName = $Cluster.Name
+
+foreach ($AG in $AvailabilityGroups){
+
+ foreach($DB in $AG.AvailabilityDatabases){
+ $DBName = $DB.name
+ $DestDataPath = $ToDataPath + $DBName
+ $DestLogPath = $ToLogPath + $DBName
+ $Bak = $BackupDirectory + "$ClusterName" + '$' + $AG.AvailabilityGroup + '\' + $DBName + '\'
+
+ Restore-DbaDatabase -SqlInstance $ToServer -DatabaseName $DBName -Path $Bak -DestinationDataDirectory $DestDataPath -DestinationLogDirectory $DestLogPath -MaintenanceSolutionBackup -WithReplace -NoRecovery -WhatIf
+ }
+}
\ No newline at end of file
diff --git a/PowerShell/Update Commerce-Live CNAMEs.ps1 b/PowerShell/Update Commerce-Live CNAMEs.ps1
new file mode 100644
index 0000000..21ba20d
--- /dev/null
+++ b/PowerShell/Update Commerce-Live CNAMEs.ps1
@@ -0,0 +1,35 @@
+cls
+
+
+
+
+$HostedZoneId = "" ## cafepress.io
+$CNAMEArray = @('')
+
+
+
+foreach ($CName in $CNAMEArray){
+
+ $NewEndpoint = Switch($CName){
+ '' {''}
+ '' {''}
+
+ }
+ $CName
+ $NewEndpoint
+ ##$change1 = New-Object Amazon.Route53.Model.Change
+ ##$change1.Action = "UPSERT"
+ ##$change1.ResourceRecordSet = New-Object Amazon.Route53.Model.ResourceRecordSet
+ ##$change1.ResourceRecordSet.Type = "CNAME"
+ ##$change1.ResourceRecordSet.TTL = 300
+ ##$change1.ResourceRecordSet.Name = "$CName"
+ ##$change1.ResourceRecordSet.ResourceRecords.Add(@{Value="$NewEndpoint"})
+ ##
+ ##$params = @{
+ ## HostedZoneId="$HostedZoneId"
+ ## ChangeBatch_Change=$change1
+ ##}
+ ##
+ ## Edit-R53ResourceRecordSet @params
+ ## $change1.ResourceRecordSet.Name
+}
\ No newline at end of file
diff --git a/PowerShell/Update Shared-Live CNAMEs.ps1 b/PowerShell/Update Shared-Live CNAMEs.ps1
new file mode 100644
index 0000000..c1d4ed9
--- /dev/null
+++ b/PowerShell/Update Shared-Live CNAMEs.ps1
@@ -0,0 +1,29 @@
+cls
+## Copy and paste access key info here
+
+## Update access key info above
+
+
+$NewEndpoint = "" ## !! Update Endpoint here !!
+
+$HostedZoneId = "" ## cafepress.io
+$CNAMEArray = @('')
+
+foreach ($CName in $CNAMEArray){
+
+ $change1 = New-Object Amazon.Route53.Model.Change
+ $change1.Action = "UPSERT"
+ $change1.ResourceRecordSet = New-Object Amazon.Route53.Model.ResourceRecordSet
+ $change1.ResourceRecordSet.Type = "CNAME"
+ $change1.ResourceRecordSet.TTL = 300
+ $change1.ResourceRecordSet.Name = "$CName"
+ $change1.ResourceRecordSet.ResourceRecords.Add(@{Value="$NewEndpoint"})
+
+ $params = @{
+ HostedZoneId="$HostedZoneId"
+ ChangeBatch_Change=$change1
+ }
+
+ Edit-R53ResourceRecordSet @params
+ $change1.ResourceRecordSet.Name
+}
\ No newline at end of file
diff --git a/RunBook/Run Book Details.rdl b/RunBook/Run Book Details.rdl
new file mode 100644
index 0000000..aeacb4a
--- /dev/null
+++ b/RunBook/Run Book Details.rdl
@@ -0,0 +1,3343 @@
+
+
+ 0
+
+
+ /Data Sources/THSQL1DataMartDev
+ None
+ 178ac664-42ce-49f6-bcc9-10ddd18977fd
+
+
+
+
+
+ dsDMDev
+ SELECT di.InstanceName
+ ,di.Environment
+ ,di.ServerUse
+ ,RIGHT(di.SQLEdition, LEN(di.SQLEdition) - 21) AS SQLEdition
+ ,di.SQLVersion
+ ,di.Comments
+ ,di.LastRestarted
+ ,di.LastCheckDateTime
+ ,unhealthyDatabase.UnhealthyDatabaseCnt
+ ,alerts.AlertCnt
+ ,failedBackups.BackupCnt
+ ,failedJobs.JobCnt
+ ,ISNULL(failedJobs.SuccessAfterCnt,0) AS SuccessAfterCnt
+ ,MemDmp.MemoryDmpCnt
+ ,CASE
+ WHEN di.Environment = 'Prod' THEN 1
+ WHEN di.Environment = 'Test' THEN 2
+ WHEN di.Environment = 'Dev' THEN 3
+ WHEN di.Environment = 'DR' THEN 4
+ ELSE 5
+ END AS GroupOrder
+FROM Sys_Admin.RunBook.DatabaseInstances di
+ CROSS APPLY
+ (SELECT COUNT(*) AS UnhealthyDatabaseCnt
+ FROM Sys_Admin.RunBook.UnhealthyDatabases ud
+ WHERE ud.CheckDateTime = di.LastCheckDateTime
+ and ud.InstanceName = di.InstanceName
+ ) unhealthyDatabase
+ CROSS APPLY
+ (SELECT COUNT(*) AS AlertCnt
+ FROM Sys_Admin.RunBook.Alerts a
+ WHERE a.CheckDateTime = di.LastCheckDateTime
+ AND a.InstanceName = di.InstanceName
+ ) alerts
+ CROSS APPLY
+ (SELECT COUNT(*) AS BackupCnt
+ FROM Sys_Admin.RunBook.FailedBackups fb
+ WHERE fb.CheckDateTime = di.LastCheckDateTime
+ AND fb.InstanceName = di.InstanceName
+ ) failedBackups
+ CROSS APPLY
+ (SELECT COUNT(*) AS JobCnt
+ ,SUM(CASE WHEN fj.RanSuccessfulAfter = 1 THEN 1 ELSE 0 END) AS SuccessAfterCnt
+ FROM Sys_Admin.RunBook.FailedJobs fj
+ WHERE fj.CheckDateTime = di.LastCheckDateTime
+ AND fj.InstanceName = di.InstanceName
+ ) failedJobs
+ CROSS APPLY
+ (SELECT COUNT(*) AS MemoryDmpCnt
+ FROM Sys_Admin.RunBook.MemoryDumps md
+ WHERE md.CheckDateTime = di.LastCheckDateTime
+ AND md.InstanceName = di.InstanceName
+ ) MemDmp
+WHERE di.IsActive = 1;
+
+
+
+ InstanceName
+ System.String
+
+
+ Environment
+ System.String
+
+
+ ServerUse
+ System.String
+
+
+ LastRestarted
+ System.DateTime
+
+
+ LastCheckDateTime
+ System.DateTime
+
+
+ SQLEdition
+ System.String
+
+
+ SQLVersion
+ System.String
+
+
+ UnhealthyDatabaseCnt
+ System.Int32
+
+
+ Comments
+ System.String
+
+
+ AlertCnt
+ System.Int32
+
+
+ BackupCnt
+ System.Int32
+
+
+ JobCnt
+ System.Int32
+
+
+ MemoryDmpCnt
+ System.Int32
+
+
+ SuccessAfterCnt
+ System.Int32
+
+
+ GroupOrder
+ System.Int32
+
+
+
+
+
+ dsDMDev
+
+select di.InstanceName
+ ,di.Environment
+ ,ud.DatabaseName
+ ,ud.DatabaseState
+ ,CASE
+ WHEN di.Environment = 'Prod' THEN 1
+ WHEN di.Environment = 'Test' THEN 2
+ WHEN di.Environment = 'Dev' THEN 3
+ WHEN di.Environment = 'DR' THEN 4
+ ELSE 5
+ END AS GroupOrder
+from Sys_Admin.RunBook.UnhealthyDatabases ud
+ INNER JOIN Sys_Admin.RunBook.DatabaseInstances di
+ ON di.InstanceName = ud.InstanceName
+ AND di.LastCheckDateTime = ud.CheckDateTime
+
+
+
+ InstanceName
+ System.String
+
+
+ Environment
+ System.String
+
+
+ DatabaseName
+ System.String
+
+
+ DatabaseState
+ System.String
+
+
+ GroupOrder
+ System.Int32
+
+
+
+
+
+ dsDMDev
+
+SELECT di.InstanceName
+ ,di.Environment
+ ,a.AlertName
+ ,a.AlertDateTime
+ ,'Message Id: ' + CAST(a.MessageId as VARCHAR(100)) + ', Severity: ' + CAST(a.Severity AS VARCHAR(100)) AS ErrorNbr
+ ,CASE
+ WHEN di.Environment = 'Prod' THEN 1
+ WHEN di.Environment = 'Test' THEN 2
+ WHEN di.Environment = 'Dev' THEN 3
+ WHEN di.Environment = 'DR' THEN 4
+ ELSE 5
+ END AS GroupOrder
+from Sys_Admin.RunBook.Alerts a
+ INNER JOIN Sys_Admin.RunBook.DatabaseInstances di
+ ON di.InstanceName = a.InstanceName
+ AND di.LastCheckDateTime = a.CheckDateTime
+
+
+
+ InstanceName
+ System.String
+
+
+ Environment
+ System.String
+
+
+ AlertName
+ System.String
+
+
+ AlertDateTime
+ System.DateTime
+
+
+ ErrorNbr
+ System.String
+
+
+ GroupOrder
+ System.Int32
+
+
+
+
+
+ dsDMDev
+
+select di.InstanceName
+ ,di.Environment
+ ,fb.DatabaseName
+ ,fb.LastFullBackup
+ ,fb.LastDiffBackup
+ ,CASE
+ WHEN di.Environment = 'Prod' THEN 1
+ WHEN di.Environment = 'Test' THEN 2
+ WHEN di.Environment = 'Dev' THEN 3
+ WHEN di.Environment = 'DR' THEN 4
+ ELSE 5
+ END AS GroupOrder
+from Sys_Admin.RunBook.FailedBackups fb
+ INNER JOIN Sys_Admin.RunBook.DatabaseInstances di
+ ON di.InstanceName = fb.InstanceName
+ AND di.LastCheckDateTime = fb.CheckDateTime
+
+
+
+ InstanceName
+ System.String
+
+
+ Environment
+ System.String
+
+
+ DatabaseName
+ System.String
+
+
+ LastFullBackup
+ System.DateTime
+
+
+ LastDiffBackup
+ System.DateTime
+
+
+ GroupOrder
+ System.Int32
+
+
+
+
+
+ dsDMDev
+ select di.InstanceName
+ ,di.Environment
+ ,fj.JobName
+ ,fj.RunDateTime
+ ,fj.RanSuccessfulAfter
+ ,CASE
+ WHEN di.Environment = 'Prod' THEN 1
+ WHEN di.Environment = 'Test' THEN 2
+ WHEN di.Environment = 'Dev' THEN 3
+ WHEN di.Environment = 'DR' THEN 4
+ ELSE 5
+ END AS GroupOrder
+from Sys_Admin.RunBook.FailedJobs fj
+ INNER JOIN Sys_Admin.RunBook.DatabaseInstances di
+ ON di.InstanceName = fj.InstanceName
+ AND di.LastCheckDateTime = fj.CheckDateTime
+
+
+
+ InstanceName
+ System.String
+
+
+ Environment
+ System.String
+
+
+ JobName
+ System.String
+
+
+ RunDateTime
+ System.DateTime
+
+
+ RanSuccessfulAfter
+ System.Boolean
+
+
+ GroupOrder
+ System.Int32
+
+
+
+
+
+ dsDMDev
+
+select di.InstanceName
+ ,di.Environment
+ ,md.MemoryDumpDateTime
+ ,CASE
+ WHEN di.Environment = 'Prod' THEN 1
+ WHEN di.Environment = 'Test' THEN 2
+ WHEN di.Environment = 'Dev' THEN 3
+ WHEN di.Environment = 'DR' THEN 4
+ ELSE 5
+ END AS GroupOrder
+from Sys_Admin.RunBook.MemoryDumps md
+ INNER JOIN Sys_Admin.RunBook.DatabaseInstances di
+ ON di.InstanceName = md.InstanceName
+ AND di.LastCheckDateTime = md.CheckDateTime
+
+
+
+ InstanceName
+ System.String
+
+
+ Environment
+ System.String
+
+
+ MemoryDumpDateTime
+ System.DateTime
+
+
+ GroupOrder
+ System.Int32
+
+
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ Run Book
+
+
+
+
+
+
+ Title
+ ReportTitle
+ 0.11333in
+ 0.4in
+ 2.32417in
+
+
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+ 2.69915in
+
+
+ 1.14584in
+
+
+ 1.82291in
+
+
+ 0.85416in
+
+
+ 0.60417in
+
+
+ 0.66667in
+
+
+ 0.5625in
+
+
+ 0.625in
+
+
+
+
+ 0.41667in
+
+
+
+
+ true
+ true
+
+
+
+
+ Instance Name
+
+
+
+
+
+
+ Textbox1
+
+
+ Gainsboro
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ Server Use
+
+
+
+
+
+
+ Textbox3
+
+
+ Gainsboro
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ Last Restarted
+
+
+
+
+
+
+ Textbox15
+
+
+ Gainsboro
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ Unhealthy Databases
+
+
+
+
+
+
+ Textbox17
+
+
+ Gainsboro
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ Alerts
+
+
+
+
+
+
+ Textbox19
+
+
+ Gainsboro
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ Missing Backups
+
+
+
+
+
+
+ Textbox21
+
+
+ Gainsboro
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ Failed Jobs
+
+
+
+
+
+
+ Textbox23
+
+
+ Gainsboro
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ Memory Dumps
+
+
+
+
+
+
+ Textbox25
+
+
+ Gainsboro
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ 0.25in
+
+
+
+
+ true
+ true
+
+
+
+
+ =Fields!InstanceName.Value
+
+
+
+
+
+
+ InstanceName
+ =Fields!SQLEdition.Value & " " & Fields!SQLVersion.Value
+
+
+ =Iif(Fields!Environment.Value="Prod","No Color", "WhiteSmoke")
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ =Fields!ServerUse.Value
+
+
+
+
+
+
+ ServerUse
+
+
+ =Iif(Fields!Environment.Value="Prod","No Color", "WhiteSmoke")
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ =Fields!LastRestarted.Value
+
+
+
+
+
+
+ LastRestarted
+
+
+ =Iif(Fields!Environment.Value="Prod","No Color", "WhiteSmoke")
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ =Fields!UnhealthyDatabaseCnt.Value
+
+
+
+
+
+
+ UnhealthyDatabaseCnt
+
+
+
+ txtUnhealthy
+
+
+
+
+
+ =Iif(Fields!Environment.Value="Prod","No Color", "WhiteSmoke")
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ =Fields!AlertCnt.Value
+
+
+
+
+
+
+ AlertCnt
+
+
+
+ txtAlerts
+
+
+
+
+
+ =Iif(Fields!Environment.Value="Prod","No Color", "WhiteSmoke")
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ =Fields!BackupCnt.Value
+
+
+
+
+
+
+ BackupCnt
+
+
+
+ txtBackups
+
+
+
+
+
+ =Iif(Fields!Environment.Value="Prod","No Color", "WhiteSmoke")
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ =Fields!JobCnt.Value-Fields!SuccessAfterCnt.Value
+
+
+
+
+
+
+ JobCnt
+
+
+
+ txtJobs
+
+
+
+
+
+ =Iif(Fields!Environment.Value="Prod","No Color", "WhiteSmoke")
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ =Fields!MemoryDmpCnt.Value
+
+
+
+
+
+
+ MemoryDmpCnt
+
+
+
+ txtMemory
+
+
+
+
+
+ =Iif(Fields!Environment.Value="Prod","No Color", "WhiteSmoke")
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0.68751in
+
+
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+ Textbox7
+
+
+ Gainsboro
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ After
+
+
+
+
+ =Fields!GroupOrder.Value
+
+
+
+
+ =Fields!GroupOrder.Value
+
+
+
+ 0.68751in
+
+
+ true
+ true
+
+
+
+
+ =Fields!Environment.Value
+
+
+
+
+
+
+ Environment
+
+
+ =Iif(Fields!Environment.Value="Prod","No Color", "WhiteSmoke")
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Instance
+ 0.46944in
+ 0.11333in
+ 0.66667in
+ 9.66791in
+ 1
+
+
+
+
+
+ true
+ true
+
+
+
+
+ =Format(Globals!ExecutionTime,”MMM-dd-yyyy”)
+
+
+
+
+
+
+ Textbox28
+ 6.21875in
+ 0.4in
+ 3.56249in
+ 2
+
+
+ Bottom
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+ 2.69915in
+
+
+ 2.67708in
+
+
+ 1.40625in
+
+
+
+
+ 0.25in
+
+
+
+
+ true
+ true
+
+
+
+
+ Instance Name
+
+
+
+
+
+
+ Textbox29
+
+
+ WhiteSmoke
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ Database Name
+
+
+
+
+
+
+ Textbox31
+
+
+ WhiteSmoke
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ Database State
+
+
+
+
+
+
+ Textbox33
+
+
+ WhiteSmoke
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ 0.25in
+
+
+
+
+ true
+ true
+
+
+
+
+ =Fields!InstanceName.Value
+
+
+
+
+
+
+ InstanceName1
+
+
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ =Fields!DatabaseName.Value
+
+
+
+
+
+
+ DatabaseName
+
+
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ =Fields!DatabaseState.Value
+
+
+
+
+
+
+ DatabaseState
+
+
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0.68751in
+
+
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+ Textbox35
+
+
+ WhiteSmoke
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ After
+
+
+
+
+ =Fields!GroupOrder.Value
+
+
+
+
+ =Fields!GroupOrder.Value
+
+
+
+ 0.68751in
+
+
+ true
+ true
+
+
+
+
+ =Fields!Environment.Value
+
+
+
+
+
+
+ Environment1
+
+
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+
+
+
+
+
+ UnhealthyDB
+ 1.70708in
+ 0.11333in
+ 0.5in
+ 7.46999in
+ 3
+
+
+
+
+
+ true
+ true
+
+
+
+
+ Unhealthy Databases
+
+
+
+
+
+
+ Textbox37
+ 1.45708in
+ 0.11333in
+ 0.25in
+ 3.26167in
+ 4
+ txtUnhealthy
+
+
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+ 2.78125in
+
+
+ 1.57292in
+
+
+ 1.92708in
+
+
+
+
+ 0.25in
+
+
+
+
+ true
+ true
+
+
+
+
+ Alert Name
+
+
+
+
+
+
+ Textbox42
+
+
+ WhiteSmoke
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ Alert Date Time
+
+
+
+
+
+
+ Textbox46
+
+
+ WhiteSmoke
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ Error Nbr
+
+
+
+
+
+
+ Textbox48
+
+
+ WhiteSmoke
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ 0.25in
+
+
+
+
+ true
+ true
+
+
+
+
+ =Fields!AlertName.Value
+
+
+
+
+
+
+ AlertName
+
+
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ =Fields!AlertDateTime.Value
+
+
+
+
+
+
+ AlertDateTime
+
+
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ =Fields!ErrorNbr.Value
+
+
+
+
+
+
+ ErrorNbr
+
+
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0.68751in
+
+
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+ Textbox44
+
+
+ WhiteSmoke
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ 2.69915in
+
+
+ true
+ true
+
+
+
+
+ Instance Name
+
+
+
+
+
+
+ Textbox61
+
+
+ WhiteSmoke
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+
+
+ After
+
+
+
+
+ =Fields!GroupOrder.Value
+
+
+
+
+ =Fields!GroupOrder.Value
+
+
+
+ 0.68751in
+
+
+ true
+ true
+
+
+
+
+ =Fields!Environment.Value
+
+
+
+
+
+
+ Environment2
+
+
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+
+ =Fields!InstanceName.Value
+
+
+
+
+ =Fields!InstanceName.Value
+
+
+
+ 2.69915in
+
+
+ true
+ true
+
+
+
+
+ =Fields!InstanceName.Value
+
+
+
+
+
+
+ InstanceName4
+
+
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Alerts
+ 2.56472in
+ 0.11333in
+ 0.5in
+ 9.66791in
+ 5
+
+
+
+
+
+ true
+ true
+
+
+
+
+ SQL Server Alerts
+
+
+
+
+
+
+ Textbox50
+ 2.32167in
+ 0.11333in
+ 0.25in
+ 3.26167in
+ 6
+ txtAlerts
+
+
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+ 2.40625in
+
+
+ 1.94792in
+
+
+ 2.05207in
+
+
+
+
+ 0.25in
+
+
+
+
+ true
+ true
+
+
+
+
+ Database Name
+
+
+
+
+
+
+ Textbox53
+
+
+ WhiteSmoke
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ Last Full Backup
+
+
+
+
+
+
+ Textbox55
+
+
+ WhiteSmoke
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ Last Diff Backup
+
+
+
+
+
+
+ Textbox59
+
+
+ WhiteSmoke
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ 0.25in
+
+
+
+
+ true
+ true
+
+
+
+
+ =Fields!DatabaseName.Value
+
+
+
+
+
+
+ DatabaseName1
+
+
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ =Fields!LastFullBackup.Value
+
+
+
+
+
+
+ LastFullBackup
+
+
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ =Fields!LastDiffBackup.Value
+
+
+
+
+
+
+ LastDiffBackup
+
+
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0.68751in
+
+
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+ Textbox57
+
+
+ WhiteSmoke
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ 2.69915in
+
+
+ true
+ true
+
+
+
+
+ Instance Name
+
+
+
+
+
+
+ Textbox63
+
+
+ WhiteSmoke
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+
+
+ After
+
+
+
+
+ =Fields!GroupOrder.Value
+
+
+
+
+ =Fields!GroupOrder.Value
+
+
+
+ 0.68751in
+
+
+ true
+ true
+
+
+
+
+ =Fields!Environment.Value
+
+
+
+
+
+
+ Environment3
+
+
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+
+ =Fields!InstanceName.Value
+
+
+
+
+ =Fields!InstanceName.Value
+
+
+
+ 2.69915in
+
+
+ true
+ true
+
+
+
+
+ =Fields!InstanceName.Value
+
+
+
+
+
+
+ InstanceName11
+
+
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Backups
+ 3.49181in
+ 0.11333in
+ 0.5in
+ 9.7929in
+ 7
+
+
+
+
+
+ true
+ true
+
+
+
+
+ No Backups in Last 24 hours
+
+
+
+
+
+
+ 3.24181in
+ 0.11333in
+ 0.25in
+ 3.26167in
+ 8
+ txtBackups
+
+
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+ 3.26042in
+
+
+ 1.80208in
+
+
+ 1.21875in
+
+
+
+
+ 0.41667in
+
+
+
+
+ true
+ true
+
+
+
+
+ Job Name
+
+
+
+
+
+
+ Textbox68
+
+
+ WhiteSmoke
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ Run Date
+
+
+
+
+
+
+ Textbox70
+
+
+ WhiteSmoke
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ Ran Successful After
+
+
+
+
+
+
+ Textbox76
+
+
+ WhiteSmoke
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ 0.25in
+
+
+
+
+ true
+ true
+
+
+
+
+ =Fields!JobName.Value
+
+
+
+
+
+
+ JobName
+
+
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ =Fields!RunDateTime.Value
+
+
+
+
+
+
+ RunDateTime
+
+
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ =Fields!RanSuccessfulAfter.Value
+
+
+
+
+
+
+ RanSuccessfulAfter
+
+
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0.68751in
+
+
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+ Textbox72
+
+
+ WhiteSmoke
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ 2.69915in
+
+
+ true
+ true
+
+
+
+
+ Instance Name
+
+
+
+
+
+
+ Textbox74
+
+
+ WhiteSmoke
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+
+
+ After
+
+
+
+
+ =Fields!GroupOrder.Value
+
+
+
+
+ =Fields!GroupOrder.Value
+
+
+
+ 0.68751in
+
+
+ true
+ true
+
+
+
+
+ =Fields!Environment.Value
+
+
+
+
+
+
+ Environment4
+
+
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+
+ =Fields!InstanceName.Value
+
+
+
+
+ =Fields!InstanceName.Value
+
+
+
+ 2.69915in
+
+
+ true
+ true
+
+
+
+
+ =Fields!InstanceName.Value
+
+
+
+
+
+
+ InstanceName21
+
+
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Jobs
+ 4.48833in
+ 0.11333in
+ 0.66667in
+ 9.66791in
+ 9
+
+
+
+
+
+ true
+ true
+
+
+
+
+ Failed Jobs
+
+
+
+
+
+
+ Textbox78
+ 4.23833in
+ 0.11333in
+ 0.25in
+ 3.26167in
+ 10
+ txtJobs
+
+
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+ 2.69915in
+
+
+ 2.26042in
+
+
+
+
+ 0.25in
+
+
+
+
+ true
+ true
+
+
+
+
+ Instance Name
+
+
+
+
+
+
+ Textbox79
+
+
+ WhiteSmoke
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ Memory Dump Date
+
+
+
+
+
+
+ Textbox81
+
+
+ WhiteSmoke
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ 0.25in
+
+
+
+
+ true
+ true
+
+
+
+
+ =Fields!InstanceName.Value
+
+
+
+
+
+
+ InstanceName2
+
+
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ =Fields!MemoryDumpDateTime.Value
+
+
+
+
+
+
+ MemoryDumpDateTime
+
+
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0.68751in
+
+
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+ Textbox85
+
+
+ WhiteSmoke
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ After
+
+
+
+
+ =Fields!GroupOrder.Value
+
+
+
+
+ =Fields!GroupOrder.Value
+
+
+
+ 0.68751in
+
+
+ true
+ true
+
+
+
+
+ =Fields!Environment.Value
+
+
+
+
+
+
+ Environment5
+
+
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+
+
+
+
+
+ MemoryDumps
+ 5.72792in
+ 0.11333in
+ 0.5in
+ 5.64708in
+ 11
+
+
+
+
+
+ true
+ true
+
+
+
+
+ Memory Dumps
+
+
+
+
+
+
+ Textbox87
+ 5.47792in
+ 0.11333in
+ 0.25in
+ 3.26167in
+ 12
+ txtMemory
+
+
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+ 6.35292in
+
+
+
+
+ 10.65625in
+
+
+ 0.45in
+ true
+ true
+
+
+ true
+ true
+
+
+
+
+ =Globals!ExecutionTime
+
+
+
+
+
+
+ ExecutionTime
+ 0.06944in
+ 0.11333in
+ 0.25in
+ 2in
+
+
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ 0in
+ 8.5in
+ 1in
+ 1in
+ 1in
+ 1in
+
+
+
+
+ Inch
+ http://chdc-cls-dhsql9/ReportServer_DEV
+ 171bb502-1003-4802-9236-98babc1a76e2
+
\ No newline at end of file
diff --git a/RunBook/Run Book.rdl b/RunBook/Run Book.rdl
new file mode 100644
index 0000000..b9357ad
--- /dev/null
+++ b/RunBook/Run Book.rdl
@@ -0,0 +1,1334 @@
+
+
+ 0
+
+
+ /Data Sources/THSQL1DataMartDev
+ None
+ 178ac664-42ce-49f6-bcc9-10ddd18977fd
+
+
+
+
+
+ dsDMDev
+ SELECT di.InstanceName
+ ,di.Environment
+ ,di.ServerUse
+ ,RIGHT(di.SQLEdition, LEN(di.SQLEdition) - 21) AS SQLEdition
+ ,di.SQLVersion
+ ,di.Comments
+ ,di.LastRestarted
+ ,di.LastCheckDateTime
+ ,di.IsCurrentPrimary
+ ,unhealthyDatabase.UnhealthyDatabaseCnt
+ ,alerts.AlertCnt
+ ,failedBackups.BackupCnt
+ ,failedJobs.JobCnt
+ ,ISNULL(failedJobs.SuccessAfterCnt,0) AS SuccessAfterCnt
+ ,MemDmp.MemoryDmpCnt
+ ,CASE
+ WHEN di.Environment = 'Prod' THEN 1
+ WHEN di.Environment = 'Test' THEN 2
+ WHEN di.Environment = 'Dev' THEN 3
+ WHEN di.Environment = 'DR' THEN 4
+ ELSE 5
+ END AS GroupOrder
+FROM Sys_Admin.RunBook.DatabaseInstances di
+ CROSS APPLY
+ (SELECT COUNT(*) AS UnhealthyDatabaseCnt
+ FROM Sys_Admin.RunBook.UnhealthyDatabases ud
+ WHERE ud.CheckDateTime = di.LastCheckDateTime
+ and ud.InstanceName = di.InstanceName
+ ) unhealthyDatabase
+ CROSS APPLY
+ (SELECT COUNT(*) AS AlertCnt
+ FROM Sys_Admin.RunBook.Alerts a
+ WHERE a.CheckDateTime = di.LastCheckDateTime
+ AND a.InstanceName = di.InstanceName
+ ) alerts
+ CROSS APPLY
+ (SELECT COUNT(*) AS BackupCnt
+ FROM Sys_Admin.RunBook.FailedBackups fb
+ WHERE fb.CheckDateTime = di.LastCheckDateTime
+ AND fb.InstanceName = di.InstanceName
+ ) failedBackups
+ CROSS APPLY
+ (SELECT COUNT(*) AS JobCnt
+ ,SUM(CASE WHEN fj.RanSuccessfulAfter = 1 THEN 1 ELSE 0 END) AS SuccessAfterCnt
+ FROM Sys_Admin.RunBook.FailedJobs fj
+ WHERE fj.CheckDateTime = di.LastCheckDateTime
+ AND fj.InstanceName = di.InstanceName
+ ) failedJobs
+ CROSS APPLY
+ (SELECT COUNT(*) AS MemoryDmpCnt
+ FROM Sys_Admin.RunBook.MemoryDumps md
+ WHERE md.CheckDateTime = di.LastCheckDateTime
+ AND md.InstanceName = di.InstanceName
+ ) MemDmp
+WHERE di.IsActive = 1;
+ true
+
+
+
+ InstanceName
+ System.String
+
+
+ Environment
+ System.String
+
+
+ ServerUse
+ System.String
+
+
+ LastRestarted
+ System.DateTime
+
+
+ LastCheckDateTime
+ System.DateTime
+
+
+ SQLEdition
+ System.String
+
+
+ SQLVersion
+ System.String
+
+
+ UnhealthyDatabaseCnt
+ System.Int32
+
+
+ Comments
+ System.String
+
+
+ IsCurrentPrimary
+ System.Boolean
+
+
+ AlertCnt
+ System.Int32
+
+
+ BackupCnt
+ System.Int32
+
+
+ JobCnt
+ System.Int32
+
+
+ MemoryDmpCnt
+ System.Int32
+
+
+ SuccessAfterCnt
+ System.Int32
+
+
+ GroupOrder
+ System.Int32
+
+
+
+
+
+ dsDMDev
+
+select di.InstanceName
+ ,di.Environment
+ ,ud.DatabaseName
+ ,ud.DatabaseState
+ ,CASE
+ WHEN di.Environment = 'Prod' THEN 1
+ WHEN di.Environment = 'Test' THEN 2
+ WHEN di.Environment = 'Dev' THEN 3
+ WHEN di.Environment = 'DR' THEN 4
+ ELSE 5
+ END AS GroupOrder
+from Sys_Admin.RunBook.UnhealthyDatabases ud
+ INNER JOIN Sys_Admin.RunBook.DatabaseInstances di
+ ON di.InstanceName = ud.InstanceName
+ AND di.LastCheckDateTime = ud.CheckDateTime
+
+
+
+ InstanceName
+ System.String
+
+
+ Environment
+ System.String
+
+
+ DatabaseName
+ System.String
+
+
+ DatabaseState
+ System.String
+
+
+ GroupOrder
+ System.Int32
+
+
+
+
+
+ dsDMDev
+
+SELECT di.InstanceName
+ ,di.Environment
+ ,a.AlertName
+ ,a.AlertDateTime
+ ,'Message Id: ' + CAST(a.MessageId as VARCHAR(100)) + ', Severity: ' + CAST(a.Severity AS VARCHAR(100)) AS ErrorNbr
+ ,CASE
+ WHEN di.Environment = 'Prod' THEN 1
+ WHEN di.Environment = 'Test' THEN 2
+ WHEN di.Environment = 'Dev' THEN 3
+ WHEN di.Environment = 'DR' THEN 4
+ ELSE 5
+ END AS GroupOrder
+from Sys_Admin.RunBook.Alerts a
+ INNER JOIN Sys_Admin.RunBook.DatabaseInstances di
+ ON di.InstanceName = a.InstanceName
+ AND di.LastCheckDateTime = a.CheckDateTime
+
+
+
+ InstanceName
+ System.String
+
+
+ Environment
+ System.String
+
+
+ AlertName
+ System.String
+
+
+ AlertDateTime
+ System.DateTime
+
+
+ ErrorNbr
+ System.String
+
+
+ GroupOrder
+ System.Int32
+
+
+
+
+
+ dsDMDev
+
+select di.InstanceName
+ ,di.Environment
+ ,fb.DatabaseName
+ ,fb.LastFullBackup
+ ,fb.LastDiffBackup
+ ,CASE
+ WHEN di.Environment = 'Prod' THEN 1
+ WHEN di.Environment = 'Test' THEN 2
+ WHEN di.Environment = 'Dev' THEN 3
+ WHEN di.Environment = 'DR' THEN 4
+ ELSE 5
+ END AS GroupOrder
+from Sys_Admin.RunBook.FailedBackups fb
+ INNER JOIN Sys_Admin.RunBook.DatabaseInstances di
+ ON di.InstanceName = fb.InstanceName
+ AND di.LastCheckDateTime = fb.CheckDateTime
+
+
+
+ InstanceName
+ System.String
+
+
+ Environment
+ System.String
+
+
+ DatabaseName
+ System.String
+
+
+ LastFullBackup
+ System.DateTime
+
+
+ LastDiffBackup
+ System.DateTime
+
+
+ GroupOrder
+ System.Int32
+
+
+
+
+
+ dsDMDev
+ select di.InstanceName
+ ,di.Environment
+ ,fj.JobName
+ ,fj.RunDateTime
+ ,fj.RanSuccessfulAfter
+ ,CASE
+ WHEN di.Environment = 'Prod' THEN 1
+ WHEN di.Environment = 'Test' THEN 2
+ WHEN di.Environment = 'Dev' THEN 3
+ WHEN di.Environment = 'DR' THEN 4
+ ELSE 5
+ END AS GroupOrder
+from Sys_Admin.RunBook.FailedJobs fj
+ INNER JOIN Sys_Admin.RunBook.DatabaseInstances di
+ ON di.InstanceName = fj.InstanceName
+ AND di.LastCheckDateTime = fj.CheckDateTime
+
+
+
+ InstanceName
+ System.String
+
+
+ Environment
+ System.String
+
+
+ JobName
+ System.String
+
+
+ RunDateTime
+ System.DateTime
+
+
+ RanSuccessfulAfter
+ System.Boolean
+
+
+ GroupOrder
+ System.Int32
+
+
+
+
+
+ dsDMDev
+
+select di.InstanceName
+ ,di.Environment
+ ,md.MemoryDumpDateTime
+ ,CASE
+ WHEN di.Environment = 'Prod' THEN 1
+ WHEN di.Environment = 'Test' THEN 2
+ WHEN di.Environment = 'Dev' THEN 3
+ WHEN di.Environment = 'DR' THEN 4
+ ELSE 5
+ END AS GroupOrder
+from Sys_Admin.RunBook.MemoryDumps md
+ INNER JOIN Sys_Admin.RunBook.DatabaseInstances di
+ ON di.InstanceName = md.InstanceName
+ AND di.LastCheckDateTime = md.CheckDateTime
+
+
+
+ InstanceName
+ System.String
+
+
+ Environment
+ System.String
+
+
+ MemoryDumpDateTime
+ System.DateTime
+
+
+ GroupOrder
+ System.Int32
+
+
+
+
+
+ dsDMDev
+ SELECT TOP (1) [CheckDateTime]
+FROM [Sys_Admin].[RunBook].[ServerCheckDates]
+ORDER BY CheckDateTime DESC;
+
+
+
+ CheckDateTime
+ System.DateTime
+
+
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ Run Book
+
+
+
+
+
+
+ Title
+ ReportTitle
+ 0.11333in
+ 0.4in
+ 2.32417in
+
+
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+ 2.69915in
+
+
+ 1.14584in
+
+
+ 1.82291in
+
+
+ 0.85416in
+
+
+ 0.60417in
+
+
+ 0.66667in
+
+
+ 0.5625in
+
+
+ 0.625in
+
+
+
+
+ 0.41667in
+
+
+
+
+ true
+ true
+
+
+
+
+ Instance Name
+
+
+
+
+
+
+ Textbox1
+
+
+ Gainsboro
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ Server Use
+
+
+
+
+
+
+ Textbox3
+
+
+ Gainsboro
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ Last Restarted
+
+
+
+
+
+
+ Textbox15
+
+
+ Gainsboro
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ Unhealthy Databases
+
+
+
+
+
+
+ Textbox17
+
+
+ Gainsboro
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ Alerts
+
+
+
+
+
+
+ Textbox19
+
+
+ Gainsboro
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ Missing Backups
+
+
+
+
+
+
+ Textbox21
+
+
+ Gainsboro
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ Failed Jobs
+
+
+
+
+
+
+ Textbox23
+
+
+ Gainsboro
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ Memory Dumps
+
+
+
+
+
+
+ Textbox25
+
+
+ Gainsboro
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ 0.25in
+
+
+
+
+ true
+ true
+
+
+
+
+ =Fields!InstanceName.Value
+
+
+
+
+
+
+ InstanceName
+ =Fields!SQLEdition.Value & " " & Fields!SQLVersion.Value
+
+
+ =Iif(Fields!Environment.Value="Prod","No Color", "WhiteSmoke")
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ =Fields!ServerUse.Value +
+Switch(
+ IsNothing(Fields!IsCurrentPrimary.Value), "",
+ Fields!IsCurrentPrimary.Value = true, " (Primary)",
+ Fields!IsCurrentPrimary.Value = false, " (Secondary)",
+ true, ""
+ )
+
+
+
+
+
+
+ ServerUse
+
+
+ =Iif(Fields!Environment.Value="Prod","No Color", "WhiteSmoke")
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ =Fields!LastRestarted.Value
+
+
+
+
+
+
+ LastRestarted
+
+
+ =Iif(Fields!Environment.Value="Prod","No Color", "WhiteSmoke")
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ =Fields!UnhealthyDatabaseCnt.Value
+
+
+
+
+
+
+ UnhealthyDatabaseCnt
+
+
+
+ txtUnhealthy
+
+
+
+
+
+ =Iif(Fields!Environment.Value="Prod","No Color", "WhiteSmoke")
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ =Fields!AlertCnt.Value
+
+
+
+
+
+
+ AlertCnt
+
+
+
+ txtAlerts
+
+
+
+
+
+ =Iif(Fields!Environment.Value="Prod","No Color", "WhiteSmoke")
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ =Fields!BackupCnt.Value
+
+
+
+
+
+
+ BackupCnt
+
+
+
+ txtBackups
+
+
+
+
+
+ =Iif(Fields!Environment.Value="Prod","No Color", "WhiteSmoke")
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ =Fields!JobCnt.Value-Fields!SuccessAfterCnt.Value
+
+
+
+
+
+
+ JobCnt
+
+
+
+ txtJobs
+
+
+
+
+
+ =Iif(Fields!Environment.Value="Prod","No Color", "WhiteSmoke")
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+ =Fields!MemoryDmpCnt.Value
+
+
+
+
+
+
+ MemoryDmpCnt
+
+
+
+ txtMemory
+
+
+
+
+
+ =Iif(Fields!Environment.Value="Prod","No Color", "WhiteSmoke")
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0.68751in
+
+
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+ Textbox7
+
+
+ Gainsboro
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+ After
+
+
+
+
+ =Fields!GroupOrder.Value
+
+
+
+
+ =Fields!GroupOrder.Value
+
+
+
+ 0.68751in
+
+
+ true
+ true
+
+
+
+
+ =Fields!Environment.Value
+
+
+
+
+
+
+ Environment
+
+
+ =Iif(Fields!Environment.Value="Prod","No Color", "WhiteSmoke")
+ Middle
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Instance
+ 0.46944in
+ 0.11333in
+ 0.66667in
+ 9.66791in
+ 1
+
+
+
+
+
+ true
+ true
+
+
+
+
+ =Format(First(Fields!CheckDateTime.Value, "CheckDate"),”MMM-dd-yyyy”)
+
+
+
+
+
+
+ Textbox28
+ 6.21875in
+ 0.4in
+ 3.56249in
+ 2
+
+
+ Bottom
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+ true
+ true
+
+
+
+
+ Click here to view details
+
+
+
+
+
+
+ Textbox2
+
+
+
+
+ /Admin/Run Book Details
+
+
+
+
+ 1.23833in
+ 0.11333in
+ 0.25in
+ 2in
+ 3
+
+
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+ true
+ true
+
+
+
+
+ ="Server statistics update as of " + CStr(First(Fields!CheckDateTime.Value, "CheckDate"))
+
+
+
+
+
+
+ Textbox4
+ 1.23833in
+ 4.64583in
+ 0.25in
+ 5.13541in
+ 4
+
+
+ 2pt
+ 2pt
+ 2pt
+ 2pt
+
+
+
+ 1.61334in
+
+
+
+
+ 10.04167in
+
+ 0in
+ 8.5in
+ 1in
+ 1in
+ 1in
+ 1in
+
+
+
+
+ Inch
+ http://chdc-cls-dhsql9/ReportServer_DEV
+ 171bb502-1003-4802-9236-98babc1a76e2
+
\ No newline at end of file
diff --git a/RunBook/RunBook - Job.sql b/RunBook/RunBook - Job.sql
new file mode 100644
index 0000000..f25eed7
--- /dev/null
+++ b/RunBook/RunBook - Job.sql
@@ -0,0 +1,355 @@
+USE [msdb]
+GO
+
+/****** Object: Job [Run Book] Script Date: 4/25/2019 11:55:06 AM ******/
+BEGIN TRANSACTION
+DECLARE @ReturnCode INT
+SELECT @ReturnCode = 0
+/****** Object: JobCategory [[Uncategorized (Local)]] Script Date: 4/25/2019 11:55:06 AM ******/
+IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'[Uncategorized (Local)]' AND category_class=1)
+BEGIN
+EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N'JOB', @type=N'LOCAL', @name=N'[Uncategorized (Local)]'
+IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
+
+END
+
+DECLARE @jobId BINARY(16)
+EXEC @ReturnCode = msdb.dbo.sp_add_job @job_name=N'Run Book',
+ @enabled=1,
+ @notify_level_eventlog=0,
+ @notify_level_email=0,
+ @notify_level_netsend=0,
+ @notify_level_page=0,
+ @delete_level=0,
+ @category_name=N'[Uncategorized (Local)]',
+ @owner_login_name=N'sa', @job_id = @jobId OUTPUT
+IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
+/****** Object: Step [PS - Query Servers] Script Date: 4/25/2019 11:55:07 AM ******/
+EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'PS - Query Servers',
+ @step_id=1,
+ @cmdexec_success_code=0,
+ @on_success_action=1,
+ @on_success_step_id=0,
+ @on_fail_action=2,
+ @on_fail_step_id=0,
+ @retry_attempts=0,
+ @retry_interval=0,
+ @os_run_priority=0, @subsystem=N'PowerShell',
+ @command=N'$RunBookInstance = "CHDC-CAR-THSQL2\DataMartDev"
+
+$ServersQuery = "SELECT InstanceName FROM Sys_Admin.RunBook.DatabaseInstances WHERE IsActive = 1"
+$LastCheckQuery = "SELECT TOP (1) CheckDateTime FROM Sys_Admin.RunBook.ServerCheckDates ORDER BY CheckDateTime DESC"
+$Servers = Invoke-Sqlcmd -Query $ServersQuery -ServerInstance $RunBookInstance
+$LastCheck = Invoke-Sqlcmd -Query $LastCheckQuery -ServerInstance $RunBookInstance
+[datetime]$LastCheckDate = Get-Date -Date $LastCheck.CheckDateTime -Format ''yyyy-MM-dd hh:mm:ss.fff''
+[datetime]$CurrentCheckDate = Get-Date -Format ''yyyy-MM-dd HH:mm:ss.fff''
+
+$RestartQuery = "SELECT create_date AS LastRestarted
+ ,LEFT(@@VERSION, CHARINDEX(''('', @@VERSION) - 1) + CAST(SERVERPROPERTY (''edition'') AS varchar(50)) AS SQLEdition
+ ,SERVERPROPERTY(''productversion'') AS SQLVersion
+FROM sys.databases WHERE name = ''tempdb''"
+
+$PrimaryReplicaQuery = "DECLARE @PrimaryReplica NVARCHAR(254)
+ ,@Version NUMERIC(18,10)
+SET @Version = CAST(LEFT(CAST(SERVERPROPERTY(''ProductVersion'') AS nvarchar(max)),CHARINDEX(''.'',CAST(SERVERPROPERTY(''ProductVersion'') AS nvarchar(max))) - 1) + ''.'' + REPLACE(RIGHT(CAST(SERVERPROPERTY(''ProductVersion'') AS nvarchar(max)), LEN(CAST(SERVERPROPERTY(''ProductVersion'') AS nvarchar(max))) - CHARINDEX(''.'',CAST(SERVERPROPERTY(''ProductVersion'') AS nvarchar(max)))),''.'','''') AS numeric(18,10))
+
+IF @Version < 11 -- Below 2012;
+ BEGIN
+ SET @PrimaryReplica = NULL;
+ END
+ELSE
+ BEGIN
+
+ SELECT @PrimaryReplica = Primary_Replica
+ FROM sys.dm_hadr_availability_group_states;
+
+ IF @PrimaryReplica IS NOT NULL AND @PrimaryReplica = @@SERVERNAME
+ SET @PrimaryReplica = 1;
+ ELSE IF @PrimaryReplica IS NOT NULL AND @PrimaryReplica <> @@SERVERNAME
+ SET @PrimaryReplica = 0;
+ ELSE
+
+ SET @PrimaryReplica = NULL;
+ END
+SELECT @PrimaryReplica AS PrimaryReplica;
+"
+
+$DatabaseHealthQuery = "SELECT name AS DatabaseName, state_desc AS DatabaseState FROM sys.databases WHERE state <> 0"
+
+$FailedBackupsQuery = ";WITH cteBackups AS
+(
+ SELECT
+ DB_ID(bus.database_name) AS DatabaseId
+ ,MAX(CASE WHEN bus.type = ''D'' THEN bus.Backup_Finish_Date END) AS LastFullBackup
+ ,MAX(CASE WHEN bus.Type <> ''D'' THEN bus.Backup_Finish_Date END) AS LastDiffBackup
+ FROM msdb.dbo.backupset bus
+ GROUP BY bus.Database_Name
+)
+SELECT d.name AS DatabaseName
+ ,b.LastFullBackup
+ ,b.LastDiffBackup
+FROM sys.Databases d
+ LEFT JOIN cteBackups b
+ ON d.database_id = b.DatabaseId
+WHERE b.DatabaseId IS NULL
+ AND d.database_id NOT IN (2,3)
+ AND d.State = 0
+ AND d.name NOT LIKE ''AdventureWorks%''
+ AND d.name NOT LIKE ''x^_%'' ESCAPE ''^''
+ OR (b.LastDiffBackup < ''$LastCheckDate''
+ AND b.LastFullBackup < ''$LastCheckDate''
+ );"
+
+$AlertsQuery = ";WITH cteAlerts AS
+(
+ SELECT a.name AS AlertName
+ ,a.message_id AS MessageId
+ ,a.severity
+ ,msdb.dbo.agent_datetime(a.last_occurrence_date, a.last_occurrence_time) AS AlertDateTime
+ FROM msdb.dbo.sysalerts a
+ WHERE a.last_occurrence_date > 0
+ AND (a.Severity > 20
+ OR a.Severity = 0)
+)
+SELECT ca.AlertName
+ ,ca.MessageId
+ ,ca.Severity
+ ,ca.AlertDateTime
+FROM cteAlerts ca
+WHERE ca.AlertDateTime > ''$LastCheckDate'';"
+
+$FailedJobsQuery = ";WITH cteFailedJobs AS
+(
+ SELECT sjh.job_id
+ ,MAX(msdb.dbo.agent_datetime(sjh.run_date, sjh.run_time)) AS RunDateTime
+ FROM msdb.dbo.sysjobhistory sjh
+ WHERE sjh.run_status NOT IN (1,4) -- Succeed, In Progress
+ AND sjh.step_id <> 0
+ AND sql_message_id <> 50000
+ group by sjh.job_id
+),
+cteSuccessAfter AS
+(
+ SELECT cfj.job_id
+ ,cfj.RunDateTime
+ ,COUNT(sjh.job_id) AS Success
+ FROM cteFailedJobs cfj
+ LEFT JOIN msdb.dbo.sysjobhistory sjh
+ ON sjh.job_id = cfj.job_id
+ AND msdb.dbo.agent_datetime(sjh.run_date, sjh.run_time) > cfj.RunDateTime
+ AND sjh.run_status = 1 -- Succeed
+ AND sjh.step_id = 0
+ GROUP BY cfj.job_id, cfj.RunDateTime
+)
+SELECT sj.name AS JobName
+ ,csa.RunDateTime
+ ,CASE
+ WHEN csa.Success > 0 THEN 1
+ ELSE 0
+ END AS RanSuccessfulAfter
+FROM cteSuccessAfter csa
+ inner join msdb.dbo.sysjobs sj
+ ON sj.job_id = csa.job_id
+WHERE RunDateTime > ''$LastCheckDate''"
+
+$MemoryDumpQuery = "SELECT creation_time
+FROM sys.dm_server_memory_dumps
+WHERE creation_time > ''$LastCheckDate''"
+
+
+Foreach ($Server in $Servers) {
+ $InstanceName = $Server.InstanceName
+ $RestartTime = Invoke-Sqlcmd -ServerInstance $InstanceName -Query $RestartQuery
+ [datetime]$rs = get-date -date $RestartTime.LastRestarted -Format ''yyyy-MM-dd HH:mm:ss.fff''
+ $SQLEdition = $RestartTime.SQLEdition
+ $SQLVersion = $RestartTime.SQLVersion
+ $InstanceUpdate = "UPDATE Sys_Admin.RunBook.DatabaseInstances
+ SET LastRestarted = ''$rs''
+ ,LastCheckDateTime = ''$CurrentCheckDate''
+ ,SQLEdition = ''$SQLEdition''
+ ,SQLVersion = ''$SQLVersion''
+ WHERE InstanceName = ''$InstanceName'';"
+ Invoke-Sqlcmd -Query $InstanceUpdate -ServerInstance $RunBookInstance
+
+ $PrimaryReplicas = Invoke-SqlCmd -ServerInstance $InstanceName -Query $PrimaryReplicaQuery
+ $PrimaryReplica = $PrimaryReplicas.PrimaryReplica
+ if ($PrimaryReplica -ne [System.DBNULL]::Value){
+ $ReplicaUpdate = "UPDATE Sys_Admin.RunBook.DatabaseInstances
+ SET IsCurrentPrimary = $PrimaryReplica
+ WHERE InstanceName = ''$InstanceName'';"
+ Invoke-SqlCmd -Query $ReplicaUpdate -ServerInstance $RunBookInstance
+ }
+
+ $DatabasesHealth = Invoke-Sqlcmd -ServerInstance $InstanceName -Query $DatabaseHealthQuery
+ if ($DatabasesHealth.count -gt 0) {
+ foreach ($DatabaseHealth in $DatabasesHealth) {
+ $DBName = $DatabaseHealth.DatabaseName
+ $DBState = $DatabaseHealth.DatabaseState
+ $UnhealthyDatabaseInsert = "INSERT INTO Sys_Admin.RunBook.UnhealthyDatabases (InstanceName, DatabaseName, DatabaseState, CheckDateTime)
+ VALUES (''$InstanceName'', ''$DBName'', ''$DBState'', ''$CurrentCheckDate'');"
+ Invoke-Sqlcmd -Query $UnhealthyDatabaseInsert -ServerInstance $RunBookInstance
+ }
+ }
+
+$FailedBackupsQuery = "DECLARE @SQL NVARCHAR(4000)
+ ,@Version NUMERIC(18,10)
+ SET @Version = CAST(LEFT(CAST(SERVERPROPERTY(''ProductVersion'') AS nvarchar(max)),CHARINDEX(''.'',CAST(SERVERPROPERTY(''ProductVersion'') AS nvarchar(max))) - 1) + ''.'' + REPLACE(RIGHT(CAST(SERVERPROPERTY(''ProductVersion'') AS nvarchar(max)), LEN(CAST(SERVERPROPERTY(''ProductVersion'') AS nvarchar(max))) - CHARINDEX(''.'',CAST(SERVERPROPERTY(''ProductVersion'') AS nvarchar(max)))),''.'','''') AS numeric(18,10))
+
+ IF @Version < 11 -- Below 2012
+ BEGIN
+ SET @SQL =
+ ''WITH cteBackups AS
+ (
+ SELECT
+ DB_ID(bus.database_name) AS DatabaseId
+ ,MAX(CASE WHEN bus.type = ''''D'''' THEN bus.Backup_Finish_Date END) AS LastFullBackup
+ ,MAX(CASE WHEN bus.Type <> ''''D'''' THEN bus.Backup_Finish_Date END) AS LastDiffBackup
+ FROM msdb.dbo.backupset bus
+ GROUP BY bus.Database_Name
+ )
+ SELECT d.name AS DatabaseName
+ ,b.LastFullBackup
+ ,b.LastDiffBackup
+ FROM sys.Databases d
+ LEFT JOIN cteBackups b
+ ON d.database_id = b.DatabaseId
+ WHERE d.database_id NOT IN (2,3)
+ AND d.name NOT LIKE ''''AdventureWorks%''''
+ AND d.name NOT LIKE ''''x^_%'''' ESCAPE ''''^''''
+ AND (b.DatabaseId IS NULL
+ OR (b.LastDiffBackup < ''''$LastCheckDate''''
+ AND b.LastFullBackup < ''''$LastCheckDate''''
+ )
+ );''
+ END
+ ELSE
+ BEGIN
+ SET @SQL =
+ ''WITH cteBackups AS
+ (
+ SELECT
+ DB_ID(bus.database_name) AS DatabaseId
+ ,MAX(CASE WHEN bus.type = ''''D'''' THEN bus.Backup_Finish_Date END) AS LastFullBackup
+ ,MAX(CASE WHEN bus.Type <> ''''D'''' THEN bus.Backup_Finish_Date END) AS LastDiffBackup
+ FROM msdb.dbo.backupset bus
+ GROUP BY bus.Database_Name
+ )
+ SELECT d.name AS DatabaseName
+ ,b.LastFullBackup
+ ,b.LastDiffBackup
+ FROM sys.Databases d
+ LEFT JOIN cteBackups b
+ ON d.database_id = b.DatabaseId
+ WHERE d.database_id NOT IN (2,3)
+ AND d.name NOT LIKE ''''AdventureWorks%''''
+ AND d.name NOT LIKE ''''x^_%'''' ESCAPE ''''^''''
+ AND (d.group_database_id IS NULL
+ OR EXISTS
+ (
+ SELECT 1
+ FROM sys.dm_hadr_availability_group_states States
+ INNER JOIN master.sys.availability_groups Groups ON States.group_id = Groups.group_id
+ INNER JOIN sys.availability_databases_cluster AGDatabases ON Groups.group_id = AGDatabases.group_id
+ WHERE primary_replica = @@Servername
+ AND d.group_database_id = AGDatabases.group_database_id
+ )
+ )
+ AND (b.DatabaseId IS NULL
+ OR (b.LastDiffBackup < ''''$LastCheckDate''''
+ AND b.LastFullBackup < ''''$LastCheckDate''''
+ )
+ );''
+ END;"
+
+ $FailedBackups = Invoke-Sqlcmd -ServerInstance $InstanceName -Query $FailedBackupsQuery
+ foreach ($FailedBackup in $FailedBackups) {
+ $DBName = $FailedBackup.DatabaseName
+
+ if (-not [String]::IsNullOrEmpty($DBName)){
+ $FailedBackupInsert = "INSERT INTO Sys_Admin.RunBook.FailedBackups (InstanceName, DatabaseName, CheckDateTime"
+ $FailedBackupValues = " VALUES (''$InstanceName'', ''$DBName'', ''$CurrentCheckDate''"
+ if ($FailedBackup.LastFullBackup -isnot [DBNull]){
+ $LastFull = $FailedBackup.LastFullBackup
+ $FailedBackupInsert = $FailedBackupInsert + ", LastFullBackup"
+ $FailedBackupValues = $FailedBackupValues + ", ''$LastFull''"
+ }
+ if ($FailedBackup.LastDiffBackup -isnot [DBNull]){
+ $LastDiff = $FailedBackup.LastDiffBackup
+ $FailedBackupInsert = $FailedBackupInsert + ", LastDiffBackup"
+ $FailedBackupValues = $FailedBackupValues + ", ''$LastDiff ''"
+ }
+ $FailedBackupInsert = $FailedBackupInsert + ")"
+ $FailedBackupValues = $FailedBackupValues + ")"
+
+ $FailedBackupInsertValues = $FailedBackupInsert + $FailedBackupValues
+ Invoke-Sqlcmd -Query $FailedBackupInsertValues -ServerInstance $RunBookInstance
+ }
+ }
+
+ $Alerts = Invoke-Sqlcmd -ServerInstance $InstanceName -Query $AlertsQuery
+ foreach ($Alert in $Alerts) {
+ $AlertName = $Alert.AlertName
+ $AlertMessageId = $Alert.MessageId
+ $AlertSeverity = $Alert.severity
+ $AlertDateTime = $Alert.AlertDateTime
+ $InsertAlert = "INSERT INTO Sys_Admin.RunBook.Alerts (InstanceName, AlertName, MessageId, Severity, AlertDateTime, CheckDateTime)
+ VALUES (''$InstanceName'', ''$AlertName'', $AlertMessageId, $AlertSeverity, ''$AlertDateTime'', ''$CurrentCheckDate'')"
+ Invoke-Sqlcmd -Query $InsertAlert -ServerInstance $RunBookInstance
+ }
+
+ $FailedJobs = Invoke-Sqlcmd -ServerInstance $InstanceName -Query $FailedJobsQuery
+ foreach ($FailedJob in $FailedJobs) {
+ $JobName = $FailedJob.JobName
+ $JobDate = $FailedJob.RunDateTime
+ $JobSuccess = $FailedJob.RanSuccessfulAfter
+ if (-not [String]::IsNullOrEmpty($JobName)) {
+ $InsertJob = "INSERT INTO Sys_Admin.RunBook.FailedJobs (InstanceName, JobName, RunDateTime, RanSuccessfulAfter, CheckDateTime)
+ VALUES (''$InstanceName'', ''$JobName'', ''$JobDate'', $JobSuccess, ''$CurrentCheckDate'')"
+ $InsertJob
+ Invoke-Sqlcmd -Query $InsertJob -ServerInstance $RunBookInstance
+ }
+ }
+
+ $MemoryDumps = Invoke-Sqlcmd -ServerInstance $InstanceName -Query $MemoryDumpQuery
+ foreach ($MemoryDump in $MemoryDumps) {
+ $MemoryDumpDate = $MemoryDump.Creation_time
+ if (-not [String]::IsNullOrEmpty($MemoryDumpDate)) {
+ $InsertMemoryDump = "INSERT INTO Sys_Admin.RunBook.MemoryDumps (InstanceName, MemoryDumpDateTime, CheckDateTime)
+ VALUES (''$InstanceName'',''$MemoryDumpDate'',''$CurrentCheckDate'')"
+ Invoke-Sqlcmd -Query $InsertMemoryDump -ServerInstance $RunBookInstance
+ }
+ }
+}
+
+$ServerCheckDateInsert = "INSERT INTO Sys_Admin.RunBook.ServerCheckDates (CheckDateTime) VALUES (''$CurrentCheckDate'')"
+Invoke-Sqlcmd -Query $ServerCheckDateInsert -ServerInstance $RunBookInstance',
+ @database_name=N'master',
+ @output_file_name=N'\\chdc-car-thsql2\d$\SQLAgent_Output\DATAMARTDEV\RunBook\Step01.txt',
+ @flags=0
+IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
+EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1
+IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
+EXEC @ReturnCode = msdb.dbo.sp_add_jobschedule @job_id=@jobId, @name=N'Daily - 7 AM',
+ @enabled=1,
+ @freq_type=4,
+ @freq_interval=1,
+ @freq_subday_type=1,
+ @freq_subday_interval=0,
+ @freq_relative_interval=0,
+ @freq_recurrence_factor=0,
+ @active_start_date=20190222,
+ @active_end_date=99991231,
+ @active_start_time=70000,
+ @active_end_time=235959,
+ @schedule_uid=N'745f4a10-2bc2-42ea-b333-a7e25daafcb1'
+IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
+EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)'
+IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
+COMMIT TRANSACTION
+GOTO EndSave
+QuitWithRollback:
+ IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION
+EndSave:
+GO
+
+
diff --git a/RunBook/RunBook - Permissions.sql b/RunBook/RunBook - Permissions.sql
new file mode 100644
index 0000000..33b8c17
Binary files /dev/null and b/RunBook/RunBook - Permissions.sql differ
diff --git a/RunBook/RunBook.sql b/RunBook/RunBook.sql
new file mode 100644
index 0000000..1a6834d
--- /dev/null
+++ b/RunBook/RunBook.sql
@@ -0,0 +1,177 @@
+
+use Sys_Admin
+go
+
+
+CREATE SCHEMA RunBook AUTHORIZATION dbo;
+GO
+
+create table RunBook.ServerCheckDates
+(
+ CheckDateTime DATETIME2 NOT NULL
+ ,CONSTRAINT PK_ServerCheckDates_CheckDateTime PRIMARY KEY CLUSTERED
+ (CheckDateTime)
+);
+
+create table RunBook.DatabaseInstances
+(
+ InstanceName varchar(254) NOT NULL
+ ,Environment varchar(5) NOT NULL
+ ,ServerUse varchar(20) NOT NULL
+ ,LastRestarted DATETIME2 NOT NULL
+ ,LastCheckDateTime DATETIME2 NOT NULL
+ ,IsActive BIT NOT NULL CONSTRAINT DF_DatabaseInstances_IsActive DEFAULT (1)
+ ,Comments varchar(254) NULL
+ ,SQLEdition varchar(100) NULL
+ ,SQLVersion varchar(20) NULL
+ ,IsCurrentPrimary BIT NULL
+ ,CONSTRAINT PK_DatabaseInstances_InstanceName PRIMARY KEY CLUSTERED
+ (InstanceName)
+);
+
+INSERT INTO RunBook.DatabaseInstances (InstanceName, Environment, ServerUse, LastRestarted, LastCheckDateTime,
+ IsActive, SQLEdition, SQLVersion, Comments, IsCurrentPrimary)
+VALUES ('CHDC-CAR-PHSQL4\DataMartProd','Prod','DataMart','2019-01-01','2019-01-01',1,NULL,NULL,NULL,1)
+ ,('CHDC-CAR-PHSQL5\DataMartProd','Prod','DataMart','2019-01-01','2019-01-01',1,NULL,NULL,NULL,0)
+ ,('CHDC-CAR-THSQL2\DataMartDev','Dev','DataMart','2019-01-01','2019-01-01',1,NULL,NULL,NULL,NULL)
+ ,('CHDC-CAR-THSQL2\DataMartTest','Test','DataMart','2019-01-01','2019-01-01',1,NULL,NULL,NULL,NULL)
+ ,('CHDC-CLS-PHSQL9\Prod','Prod','SQL9','2019-01-01','2019-01-01',1,NULL,NULL,NULL,NULL)
+ ,('CHDC-CLS-DHSQL9\Dev','Dev','SQL9','2019-01-01','2019-01-01',1,NULL,NULL,NULL,NULL)
+ ,('CHDC-S13-PCSQL1\S13','Prod','SharePoint','2019-01-01','2019-01-01',1,NULL,NULL,NULL,1)
+ ,('CHDC-S13-PCSQL2\S13','Prod','SharePoint','2019-01-01','2019-01-01',1,NULL,NULL,NULL,0)
+ ,('CHDC-SQL-DVCH1C\I1','Dev','Apps','2019-01-01','2019-01-01',1,NULL,NULL,NULL,NULL)
+ ,('CHDC-SQL-PCCH2A\I1','Prod','Apps','2019-01-01','2019-01-01',1,NULL,NULL,NULL,1)
+ ,('CHDC-SQL-PCCH2B\I1','Prod','Apps','2019-01-01','2019-01-01',1,NULL,NULL,NULL,0)
+ ,('CHDC-SQL-UCCH2A\I1','Test','Apps','2019-01-01','2019-01-01',1,NULL,NULL,NULL,1)
+ ,('CHDC-SQL-UCCH2B\I1','Test','Apps','2019-01-01','2019-01-01',1,NULL,NULL,NULL,0)
+ ;
+
+create table RunBook.UnhealthyDatabases
+(
+ UnhealthyDatabaseId INT NOT NULL IDENTITY(1,1)
+ ,InstanceName varchar(254) NOT NULL
+ ,DatabaseName sysname NOT NULL
+ ,DatabaseState varchar(60) NOT NULL
+ ,CheckDateTime DATETIME2 NOT NULL
+ ,CONSTRAINT PK_UnhealthyDatabases_InstanceNameCheckDateTimeUnhealthyDatabaseId PRIMARY KEY CLUSTERED
+ (InstanceName, CheckDateTime, UnhealthyDatabaseId)
+);
+
+create table RunBook.FailedBackups
+(
+ FailedBackupId INT NOT NULL IDENTITY(1,1)
+ ,InstanceName varchar(254) NOT NULL
+ ,DatabaseName varchar(254) NOT NULL
+ ,LastFullBackup DATETIME2 NULL
+ ,LastDiffBackup DATETIME2 NULL
+ ,CheckDateTime DATETIME2 NOT NULL
+ ,CONSTRAINT PK_FailedBackups_InstanceNameCheckDateTimeFailedBackupId PRIMARY KEY CLUSTERED
+ (InstanceName, CheckDateTime, FailedBackupId)
+);
+
+create table RunBook.Alerts
+(
+ AlertId INT NOT NULL IDENTITY(1,1)
+ ,InstanceName varchar(254) NOT NULL
+ ,AlertName sysname NOT NULL
+ ,MessageId INT NOT NULL
+ ,Severity INT NOT NULL
+ ,AlertDateTime DATETIME2 NOT NULL
+ ,CheckDateTime DATETIME2 NOT NULL
+ ,CONSTRAINT PK_Alerts_InstanceNameCheckDateTimeAlertId PRIMARY KEY CLUSTERED
+ (InstanceName, CheckDateTime, AlertId)
+);
+
+create table RunBook.FailedJobs
+(
+ FailedJobId INT NOT NULL IDENTITY(1,1)
+ ,InstanceName varchar(254) NOT NULL
+ ,JobName sysname NOT NULL
+ ,RunDateTime DATETIME2 NOT NULL
+ ,RanSuccessfulAfter BIT NOT NULL CONSTRAINT DF_FailedJobs_RanSuccessfulAfter DEFAULT 0
+ ,CheckDateTime DATETIME2 NOT NULL
+ ,CONSTRAINT PK_FailedJobs_InstanceNameCheckDateTimeFailedJobId PRIMARY KEY CLUSTERED
+ (InstanceName, CheckDateTime, FailedJobId)
+);
+
+
+/*
+/* Queries */
+-- Last Run:
+SELECT create_date AS LastRestarted FROM sys.databases WHERE name = 'tempdb';
+
+-- Database Health:
+SELECT name AS DatabaseName, state_desc AS DatabaseState FROM sys.databases WHERE state <> 0
+
+-- Failed Backup:
+;WITH cteBackups AS
+(
+ SELECT
+ DB_ID(bus.database_name) AS DatabaseId
+ ,MAX(CASE WHEN bus.type = 'D' THEN bus.Backup_Finish_Date END) AS LastFullBackup
+ ,MAX(CASE WHEN bus.Type <> 'D' THEN bus.Backup_Finish_Date END) AS LastDiffBackup
+ FROM msdb.dbo.backupset bus
+ GROUP BY bus.Database_Name
+)
+SELECT d.name AS DatabaseName
+ ,b.LastFullBackup
+ ,b.LastDiffBackup
+FROM sys.Databases d
+ LEFT JOIN cteBackups b
+ ON d.database_id = b.DatabaseId
+WHERE b.DatabaseId IS NULL
+ AND d.database_id NOT IN (2,3)
+ OR (b.LastDiffBackup < DATEADD(HOUR, -24, SYSDATETIME())
+ AND b.LastFullBackup < DATEADD(HOUR, -24, SYSDATETIME())
+ );
+
+-- Alerts
+;WITH cteAlerts AS
+(
+ SELECT a.name AS AlertName
+ ,a.message_id AS MessageId
+ ,a.severity
+ ,msdb.dbo.agent_datetime(a.last_occurrence_date, a.last_occurrence_time) AS AlertDateTime
+ FROM msdb.dbo.sysalerts a
+ WHERE a.last_occurrence_date > 0
+)
+SELECT *
+FROM cteAlerts ca
+WHERE ca.AlertDateTime > DATEADD(HOUR, -24, SYSDATETIME());
+
+-- Failed Jobs
+;WITH cteFailedJobs AS
+(
+ SELECT sjh.job_id
+ ,MAX(msdb.dbo.agent_datetime(sjh.run_date, sjh.run_time)) AS RunDateTime
+ FROM msdb.dbo.sysjobhistory sjh
+ WHERE sjh.run_status NOT IN (1,4) -- Succeed, In Progress
+ AND sjh.step_id <> 0
+ group by sjh.job_id
+),
+cteSuccessAfter AS
+(
+ SELECT cfj.job_id
+ ,cfj.RunDateTime
+ ,COUNT(sjh.job_id) AS Success
+ FROM cteFailedJobs cfj
+ LEFT JOIN msdb.dbo.sysjobhistory sjh
+ ON sjh.job_id = cfj.job_id
+ WHERE msdb.dbo.agent_datetime(sjh.run_date, sjh.run_time) > cfj.RunDateTime
+ AND sjh.run_status = 1 -- Succeed
+ AND sjh.step_id = 0
+ GROUP BY cfj.job_id, cfj.RunDateTime
+)
+SELECT sj.name AS JobName
+ ,csa.RunDateTime
+ ,CASE
+ WHEN csa.Success > 0 THEN 1
+ ELSE 0
+ END AS RanSuccessfulAfter
+FROM cteSuccessAfter csa
+ inner join msdb.dbo.sysjobs sj
+ ON sj.job_id = csa.job_id
+WHERE RunDateTime > DATEADD(HOUR, -24, SYSDATETIME())
+
+
+*/
\ No newline at end of file