Powershell to find the principal/mirror in SQL servers - sql

I would like to know if it is possible to know if a instance of sql server is in mirror/prinicipal by running any sql query? and secondly i want to run this on say 60-80 instances everyday at 4am automatically possible? I would like to use powershell used it before quite easy to use from experience. Tks

It is possible. You will need to play around with SMO objects.
$server = "dwhtest-new"
$srv = New-Object Microsoft.SqlServer.Management.Smo.Server $server
$db = New-Object Microsoft.SqlServer.Management.Smo.Database
$dbs = $srv.Databases
foreach ($db1 in $dbs)
{
$db = New-Object Microsoft.SqlServer.Management.Smo.Database
$db = $db1
$DatabaseName = $db.Name
Write-Host $DatabaseName
Write-Host "MirroringStatus:" $db.MirroringStatus
Write-Host "DBState:" $db.Status
Write-Host
}
If your DB's mirroring is still intact you will recieve 'Synchronized' for MirroringStatus and its its the Primary it will say "Normal" for the status and if its the failover it will say "Restoring". Unfortunately there is no way, that im aware of, to just pull out the status of "Mirror" or "principle". You will jsut have to build logic to check both fo those values.
Restoring

It depends on how are you going to setup the job?
If you want to run it from one central server that collects all the information then SMO would be the way to go with PowerShell. The answer provided by KickerCost can work but would need some more work to be able to run it for multiple servers. It would be best to take his example and turn it into a working function that will allow the server names to be piped in.
If you are going to just run a job locally on each server (scheduled task or SQL Agent job) that may point to the script on a network share, then maybe output that info to a file (like servername_instance.log) you can use a one-liner with SQLPS:
dir SQLSERVER:\SQL\KRINGER\Default\Databases | Select Name, MirroringStatus
KRINGER is my server name, with a default instance. If you have named instances then replace the "default" with the instance name.
Your output from this command would be similar to this:
Name MirroringStatus
---- ---------------
AdventureWorks None
AdventureWorksDW None
Obviously I don't have any databases involved in mirroring.

Related

How to correctly store SQL data in a variable?

So I am currently writing a script to create a Jira Issue every morning with all the aborted processes of our Adeptia Broker's. All of this works, except for the part that I get the SQL data and get it into the Jira issue's description.
This is what I use to collect the SQL Server Data a the moment;
$SELECTQUERY = "
SELECT DISTINCT COLUMN, COLUMN, COLUMN, COLUMN
FROM [$DB].[dbo].[$TABLE]
WHERE COLUMN= 'x' AND COLUMN = 'x'
ORDER BY COLUMN DESC
"
try {
# Run SQL Query
Invoke-Sqlcmd -ServerInstance $SI -Database $DB -Username $UID -Password $PASS -Query $SELECTQUERY
$test = $SELECTQUERY.output
CreateJiraIncident -summary $summary -description $test
}
catch {
# Error handling
Write-Warning -Message "Well, the script didn't work..."
break
}
Whenever I call the $SELECTQUERY.output with echo, return or Write-Host it gives me back the correct data. Does anyone know of a different way to store this data in a string so I can send it off to Jira? (No the issue isn't with the Jira part since I can add anything I want to the 'description' parameter it will show up in the Jira Issue.
I really just need a way to store all this data in a string so I can correctly send it.

How to read/fetch data from Oracle SQL database using PowerShell Core?

I have been researching on this for a couple of days but have been going in circles here.
I need to write a script that fetches the data from Oracle db and do something with the data. In my script I will have to fetch data multiple times.
My machine has the SQLDeveloper-21.4.3 which I got from installing InstantClient-Basic-Windows-21.3.0. I use the SQL Developer to connect to the db which is on another machine; this is how I can look into tables, views etc. of the db.
Secondly, this script will be hosted on another server that runs Windows-Server-2012-R2. I am just using my machine to write the script because I cannot use the server to do this. Therefore, I am looking for a solution that requires minimum amount of installing.
Thirdly, we do not have Oracle commercial license. This Oracle db I am trying to access is on the machine installed by a third party that installed some instruments. This company uses Oracle as they collect data on the instruments installed.
I was hoping the solution would be something similar to invoking connection to MS SQL where I downloaded module that gave cmdlets to connect to the MS SQL.
Oracle does have Oracle Modules for PowerShell but neither have I found information on how to use them nor have I understood the little information provided by Oracle on this. For this to work one of the requirement is:
A configuration file and key pair used for signing API requests, with
the public key uploaded to Oracle Cloud using Oracle Cloud
Infrastructure Console. Only the user calling the API should possess
the private key.
I don't know the heck Oracle is talking about here. Like, what is this configuration file, where is it? Where would I get the key pair from for signing API request. What is Oracle Infrastructure Console, where do I get it from? You get the idea.
Link: https://docs.oracle.com/en-us/iaas/Content/API/SDKDocs/powershell.htm
Therefore, I went the .DLL route.
This is what I have done so far:
I installed Oracle.ManagedDataAccess.Core -Version 3.21.61 from NuGet.
Unzipped the package and moved the Oracle.ManagedDataAccess.dll to the location of my script.
The code is:
$OracleDLLPath = "C:\Users\Desktop\CNC_File_Transfer_VSCode\Fastems_NicNet\Oracle.ManagedDataAccess.dll"
$datasource = " (DESCRIPTION =
(ADDRESS =
(PROTOCOL = TCP)
(HOST = 10.50.61.9)(PORT = 1521))
(CONNECT_DATA = (SERVER = DEDICATED)
(SERVICE_NAME = Fa1)
(FAILOVER_MODE = (TYPE = SELECT)
(METHOD = BASIC)
(RETRIES = 180)
(DELAY = 5))))"
$username = "username"
$password = "password"
$queryStatment = "SELECT [PROG_TYPE] FROM NC_PROGRAMS FETCH FIRST 10 ROWS ONLY"
#Load Required Types and modules
Add-Type -Path $OracleDLLPath
Import-Module SqlServer
Write-Host $queryStatment
#Create the connection string
$connectionstring = 'User Id=' + $username + ';Password=' + $password + ';Data Source=' + $datasource
#Creates a data adapter for the command
$da = New-Object Oracle.ManagedDataAccess.Client.OracleDataAdapter($cmd);
#The Data adapter will fill this DataTable
$resultSet = New-Object System.Data.DataTable
#Only here the query is sent and executed in Oracle
[void]$da.fill($resultSet)
#Close the connection
$con.Close()
WRITE-HOST $resultSet
This gives an error though:
Add-Type : Unable to load one or more of the requested types. Retrieve
the LoaderExceptions property for more information.
I am new to programming in general. I would really appreciate if someone could provide detailed steps on resolving this. Thanks in advance.

SQL Server audit extended event metadata change

We have extended event running in SQL Server 2014. We also have a task that run every few minutes and check that the Xevent is running -> Audit the Xevent trace.
I'm trying to find a way (in T-SQL) to audit also changes on the Xevent metadata.
If the Xevent change (by alter), or drop and create.
No need to monitor stop and start session.
I thought about hash function on the Xevent metadata, but I can not find a T-SQL way to get the Xevent string.
Any idea how this can be achieved?
Thanks,
I managed to get the Xevent metadata by using PowerShell SQLPS module.
Then Hash function on the string result:
$server="localhost"
Import-Module sqlps -DisableNameChecking
CD SQLSERVER:\
CD xevent\$server\default\Sessions
$xe=Get-ChildItem |Where-Object {$_.name -eq $XeName}
#$xe.Targets
#$xe.IsRunning
$Xeventmetadata=$xe.ScriptCreate().GetScript()
$Xeventmetadata
#Getting String hash value
function Hash($textToHash)
{
$hasher = new-object System.Security.Cryptography.SHA256Managed
$toHash = [System.Text.Encoding]::UTF8.GetBytes($textToHash)
$hashByteArray = $hasher.ComputeHash($toHash)
foreach($byte in $hashByteArray)
{
$res += $byte.ToString()
}
return $res;
}
Hash("$Xeventmetadata")

How to determine SQL database replication roles using the Azure PowerShell command Get-AzureRMSqlDatabase

Using the Azure Resource Manager PowerShell commands, is there a simple way to tell whether a database is involved in geo-replication role as either a Primary or Secondary? I used to read the Status property returned by Get-AzureSqlDatabase, and a value of 0 meant that the database was Primary. However, there is no corresponding property returned by Get-AzureRMSqlDatabase; it still returns a status column, but the value is "Online" for both primary and secondary databases.
The reason I need this is that I'm trying to maintain dozens of databases across multiple subscriptions and servers, and I am trying to automate actions that should only be taken on the primary databases.
I found a reasonable solution to this problem, making one extra call per database. The commandlet Get-AzureRmSqlDatabaseReplicationLink does exactly what I needed, with one caveat; I know that I'm not supposed to be passing the same value as both ResourceGroupName and PartnerResourceGroupName, but it seems to work (at least for now), so I'm going with it to avoid having to make one call per resource group in the subscription.
Using that, I was able to create this simple function:
Function IsSecondarySqlDatabase {
# This function determines whether specified database is performing a secondary replication role.
# You can use the Get-AzureRMSqlDatabase command to get an instance of a [Microsoft.Azure.Commands.Sql.Database.Model.AzureSqlDatabaseModel] object.
param
(
[Microsoft.Azure.Commands.Sql.Database.Model.AzureSqlDatabaseModel] $SqlDB
)
process {
$IsSecondary = $false;
$ReplicationLinks = Get-AzureRmSqlDatabaseReplicationLink `
-ResourceGroupName $SqlDB.ResourceGroupName `
-ServerName $SqlDB.ServerName `
-DatabaseName $SqlDB.DatabaseName `
-PartnerResourceGroupName $SqlDB.ResourceGroupName
$ReplicationLinks | ForEach-Object -Process `
{
if ($_.Role -ne "Primary")
{
$IsSecondary = $true
}
}
return $IsSecondary
}
}

SQL SMO Objects SqlRestore Method (ReadFileList)

Good afternoon all-
I've searched around quite a bit, and found a few good resources on how to dynamically determine the names of the logical data file names contained within an and SQL .bak file. The SMO method Im working with requires that I pass the ServerName, however my requirement calls for passing the actual file path to the backup. I can get what I need in T-SQL, but I'd really like to determine a way to do it leveraging SMO's. Below is the T-SQL which gets me the information I require:
RESTORE FILELISTONLY
FROM N'C:\Directory\File.bak'
WITH FILE = 1
Unfortunately SqlRestore.ReadFileList(ServerName) will not work, as the backup set has not been restored to a server yet. Essentially I need this information so I can pass it to Restore.RelocateFiles.Add. I'm actually a DBA just dabbling in C#, so if you need more information just let me know and I will try to fill in the gaps. Thanks for any assistance!
The Powershell script below shows how you can read a backup file based on a file path:
$ServerName="SERVER\MYSQLSERVER"
$svrConn = new-object Microsoft.SqlServer.Management.Common.ServerConnection
$svrConn.ServerInstance=$secondaryServerName
$svrConn.LoginSecure = $true
$svr = new-object Microsoft.SqlServer.Management.Smo.Server ($svrConn)
$fullResotrePath = "\\Path\MyDatabase.bak"
$res = new-object Microsoft.SqlServer.Management.Smo.Restore
$res.Devices.AddDevice($fullRestorePath, [Microsoft.SqlServer.Management.Smo.DeviceType]::File)
$dt = $res.ReadFileList($svr)
foreach($r in $dt.Rows)
{
foreach ($c in $dt.Columns)
{
Write-Host $c "=" $r[$c]
}
}