Loop array and store all results - arrays

Admittedly I am not a strong developer but I have done some research and I want to get a solid answer to my problem. I see Multi-dimensional Arrays but I am not sure if this is the right answer
I have a three part issue. Database Server, Database, and Units
There are n Units, there are 4 Database Servers, there are n database (1 database per 1 Unit).
So for example:
Unit1 is on Database Server 4 using Database DB_Unit1
Unit2 is on Database Server 4 using Database DB_Unit2
Unit3 is on Database Server 2 using Database Unit3 (Some Databases are not named DB_Unit)
Unit4 is on Database Server 1 using Database XYZ
Unit5 is on Database Server 1 using Database DB_Unit5
I assumed I could use an array to store each string for each Agency but I'm not sure how that works.
So I am trying to write a PowerShell script that uses all of these functions
$units = ("Unit1","Unit2","Unit3","Unit4","Unit5")
FOREACH ($Unit in Units){
Invoke-Sqlcmd -ServerInstance $DatabaseServer -Database $Database -Query "Select * from tbl1"
}
My outcome is that it would Query each Database Server with the assigned database for each Unit.
Any ideas on how this works with an Array or is there a separate way to associate this data?

I think this might be more what you are after. It should run n times, where n is the number of strings in $Units. There should be 5 results added to $SQLResults.
$Units= ("Unit1","Unit2","Unit3","Unit4","Unit5")
$SQLResults = New-Object System.Collections.ArrayList
ForEach ($Unit in $Units){
switch ($Unit) {
"Unit1" { $DatabaseServer = "Database Server 4";$Database = "DB_Unit1" }
"Unit2" { $DatabaseServer = "Database Server 4";$Database = "DB_Unit2" }
"Unit3" { $DatabaseServer = "Database Server 2";$Database = "Unit3" }
"Unit4" { $DatabaseServer = "Database Server 1";$Database = "XYZ" }
"Unit5" { $DatabaseServer = "Database Server 1";$Database = "DB_Unit5" }
}
$UnitResults = Invoke-Sqlcmd -ServerInstance $DatabaseServer -Database $Database -Query "Select * from tbl1"
$UnitResults | Add-Member -MemberType NoteProperty -Name "Unit" -Value $Unit
$SQLResults.Add($UnitResults)
}
You should then be able to get the specific unit results by doing $SQLResults | where {$_.Unit -eq "Unit1"}

Related

How to delete record from database if no longer existed

If I have a new data/record in my CSV file then I'm importing it to my SQL Server database using PowerShell like this.
$CSVImport = Import-CSV $Global:ErrorReport
ForEach ($CSVLine1 in $CSVImport) {
$CSVHold1 = $CSVLine1.Hold
$CSVGSID1 = $CSVLine1.GSID
$CSVSource1 = $CSVLine1.Source
$CSVTYPE1 = $CSVLine1.TYPE
$CSVMessage1 = $CSVLine1.Message
$CSVCreatedDate1 = $CSVLine1.Time
$query = "USE $Global:Database
IF NOT EXISTS (SELECT * FROM Lit_Hold_Err
WHERE GSID = '$CSVGSID1'
AND Source = '$($CSVSource1 -replace "'","''")')
BEGIN
INSERT INTO Lit_Hold_Err (Hold, GSID, Source, Error, Type,Date)
VALUES('$CSVHold1', '$CSVGSID1', '$($CSVSource1 -replace "'","''")','$CSVMessage1','$CSVTYPE1', '$CSVCreatedDate1')
END"
Invoke-Sqlcmd -Query $query -ServerInstance $Global:Server -Database $Global:Database
I'm just wondering how should I write another query that compare my CSV file with my database and delete a particular/s record from my database if it's no longer existed in my CSV file?.
I know I'll need to use DELETE Statement but I'm kinda stuck on WHERE Clause so Any help or suggestion would be really appreciated.
A suggestion would be using DBATool's Import-DbaCsv to read the CSV file and bulk load it to a table on tempdb, then use a merge instruction to make the inserts/updates/deletes.
The import command would be something like:
$Credential = Get-Credential
Import-DbaCsv -Path .\test.csv -AutoCreateTable -SqlInstance my-instance -Database tempdb -SqlCredential $Credential -SupportsMultiline

How to drop sql server database that has not been logged in for over 30 days

I have 3 SQL Server instances running on 3 different servers. I want to be able to automatically drop any database that has not been logged in for more than 30 days.I am trying to do this in power-shell see below code:
$SQLInstances = "sql2016", "sql2014", "sql2012"
$SQLQuery = "SELECT * FROM sys.databases WHERE name not in ('tempdb','model', 'msdb', 'master','EVN') and name not like '%report%'"
foreach($sqLInstance in $SQLInstances) {
$ListOfDatabases = Invoke-Sqlcmd -ServerInstance $sqLInstance -Database "master" -Query $SQLQuery
ForEach ($Database in $ListOfDatabases ) {
Invoke-Sqlcmd -ServerInstance $sqLInstance -Database "$Database" -Query "IF (SELECT * FROM sys.dm_exec_sessions WHERE DATEDIFF(day, LOGIN_TIME , GETDATE()) > 30 )
BEGIN
DROP DATABASE $Database
END "
}
}
I'm getting stuck on how to drop the databases. The last thing I would need is to send an email with a list of databases that will be/have been dropped.
Any suggestions on how my code should be like?
The exact thing you need is mentioned in this article.
You can find the no used DB based on the number of connections and the login time.
You can schedule it as a SQL Job, so you do not need external scheduling and powershell to manage it.
There is option to send email from within Stored Procudure. You just need to configure the SMTP details for the outgoing EMail.
https://www.mssqltips.com/sqlservertip/3171/identify-sql-server-databases-that-are-no-longer-in-use/

Powershell script scripts on dbachecks to compare the MaxMemory of server listed in a table

Run checks against servers
Import-Module dbatools
Import-Module dbachecks
$Server = "AMCB123"
$Database = "DBA"
# Create recordset of servers to evaluate
$sconn = new-object System.Data.SqlClient.SqlConnection("server=$Server;Trusted_Connection=true");
$q = "SELECT DISTINCT servername FROM DBA.[dbo].[Server_Group] WHERE ID =1;"
$sconn.Open()
$cmd = new-object System.Data.SqlClient.SqlCommand ($q, $sconn);
$cmd.CommandTimeout = 0;
$dr = $cmd.ExecuteReader();
# Loop through the servers and build an array
while ($dr.Read()) {
Get-DbaMaxMemory -SqlServer $dr.GetValue(0) | Format-Table
}
$dr.Close()
$sconn.Close()
I have Listed the sql server(stage, prod, DR servers in a table as per the groups), Now I want to compare the servers with group id's to check wethere the servers(stage,prod, DR) with same group id is having same MAXMemory cofiguration or not.
For this I'm using the below powershell script can you please help me with this, I have created a table with all the servewith grop id.
Request to please help me with the loop thorugh the servers and build an array, so that I can run the MAXMEMORY powershell command to compare it using the group id for all servers.
I have collected all the servers details into a table dbo.server groups
the powershell script should iterate through the table by using the ID and check whether the servers in the ID group has same MAXMEMORY configuration ID server_name Environment
1 ABC0123 prod
1 ABC5123 stage
1 ABC4123 DR
2 DEF0123 prod
2 DEF5123 stage
2 DEF4123 DR
I'm trying to use a powershell script which will check and compare the MAXMEMORY configuration as per the ID(to check whether stage, prod, DR server of the same group_id have similar setting or not), if not then it will display a warning/message as group_ids servers are not configured similarly.
Please help me with the script
You're making this script longer than it needs to be. Also, you're using Format-Table prematurely - you should only use the Format-* functions for displaying final information to the user; they output strings, not properly typed data/variables that can be used down the line.
Use the tools that PowerShell and dbatools give you to get your server list, and then pass that list to Get-DbaMaxMemory as a collection.
import-module dbatools
$ServerList = Invoke-DbaSqlQuery -ServerInstance $Server -query "select distinct servername from dba.dbo.server_group where group_id = 1" | Select-Object -ExpandProperty servername;
Get-DbaMaxMemory -ServerInstance $ServerList | Select-Object SqlInstance, SqlMaxMB;
This will give you a list of your SQL instances and the memory they're configured to use. What you do after that...it's hard to say as you haven't clearly defined what you're looking for.
But this may not tell the full story. Wouldn't it be better to check the configured values and what you're currently running with? You can do that with Get-DbaSpConfigure.
import-module dbatools
$ServerList = Invoke-DbaSqlQuery -ServerInstance $Server -query "select distinct servername from dba.dbo.server_group where group_id = 1" | Select-Object -ExpandProperty servername;
Get-DbaSpConfigure -ServerInstance $ServerList | Select-Object ServerName,ConfiguredValue,RunningValue;
You can even create a computed column in that final Select-Object to tell you if the configured & running values differ.
If you just wanted to use dbachecks (which uses dbatools in the background) you can use
$ServerList = (Invoke-DbaSqlQuery -ServerInstance $Server -query "select distinct servername from dba.dbo.server_group where group_id = 1").servername
and
Invoke-DbcCheck -SQlInstance $ServerList -Check MaxMemory
Or you can set the configuration item app.computername and app.sqlinstance to your server list using
Set-DbcConfig -Name app.sqlinstance -Value $serverlist
Set-DbcConfig -Name app.computername -Value $serverlist
and then you can run this (or any other checks) using
Invoke-DbcCheck -Check MaxMemory

Powershell: Find all SQL Server instances per ser server?

Strictly speaking, the question is, I use this solution and it works, but is there a better way?
With the following caveats.
1) I don't want to do a network wide search for SQL instances, I am interrogating known SQL servers, but I want to grab the instance names on each.
2) The code assumes Microsoft will never change the display name for the SQL Server Service.
function getSQLInstance ([string]$SERVER) {
$services = Get-Service -Computer $SERVER
# Filter for SQL services
$services = $services | ? DisplayName -like "SQL Server (*)"
# Remove MSSQL$ qualifier to get instance name
try {
$instances = $services.Name | ForEach-Object {($_).Replace("MSSQL`$","")}
}catch{
# Error if none found
return -1
}
return $instances
}
getSQLInstance "YOUR_SERVER"
Rather than re-invent the wheel, take a look at how SQL Power Doc discovers instances on a server. Which, from looking at NetworkScan.psm1, appears to be very similar to your approach:
$ManagedComputer.Services | ForEach-Object {
if (($_.Name).IndexOf('$') -gt 0) {
$InstanceName = ($_.Name).Substring(($_.Name).IndexOf('$') + 1)
$IsNamedInstance = $true
$ManagedComputerServerInstanceName = $InstanceName
} else {
$InstanceName = $null
$IsNamedInstance = $false
$ManagedComputerServerInstanceName = $_.Name
}
Or, just use SQL Power Doc and point it at specific server names to collect this and more data about the instances.

How to copy tables plus data for testing purposes

How can I copy a number of tables, plus the data they contain, from a live SQL Server database?
I want to get some data for basic testing on my machine.
I was originally going to do a simple backup of the database, until I noticed that it was over 100GB in size. However the tables I'm after are only a number of the smaller ones. I then tried export to Excel, but hit the 65K limit (and we don't have Excel 2007)
You can try Exporting Data by Using the SQL Server Import and Export Wizard
Here is MSDN video
you can export it as Flat file
In Management Studio, select the database, right-click and select Tasks->Export Data. There you will see options to export to different kinds of formats including CSV.
You can also run your query from the Query window and save the results to CSV.
Can't you use the Export Data wizard from your live server to your testing machine? Or use bcp? Or even use a simple PowerShell script?
$Server = "MyServer"
$ServerInstance = "$Server\MyInstance"
$database = "MyDatabase"
$BackupFile = "c:\MyBackupFile.sql"
$tables = #('TableBlah','TableBluh','TableBloh')
$server = New-Object (
'Microsoft.SqlServer.Management.Smo.Server') $ServerInstance
$scripter = New-Object ('Microsoft.SqlServer.Management.Smo.Scripter') $server
$scripter.Options.SchemaQualify = $false
$scripter.Options.ScriptSchema = $false
$scripter.Options.ScriptData = $true
$scripter.Options.NoCommandTerminator = $true
$scripter.Options.ToFileOnly = $true
$scripter.Options.FileName = $BackupFile
$ServerUrn=$server.Urn
$UrnsToScript = New-Object Microsoft.SqlServer.Management.Smo.UrnCollection
foreach ($t in $tables)
{
# Could use bcp here for dumping big tables (like archives)
# $ret = (bcp.exe "$database..$t" out `"$ConfigBackupDir\$t.bcp`"
# -S $ServerInstance -U sa -P $SAPWD -n)
$Urn = "$ServerUrn/Database[#Name='" +
$database + "']/Table[#Name='" + $t + "' and #Schema='dbo']"
$UrnsToScript.Add($Urn)
}
$scripter.EnumScript($UrnsToScript)

Resources