How to get path to active SQL Server - sql

How do you get ask PowerShell for the following path:
C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER
If I open PowerShell and execute the following command:
Set-Location SQLSERVER:\SQL
PowerShell will change my location to SQLServer. I want the physical path to that SQLServer
I want to script the SQL server management studio's db restore command.
The above is SQL code is auto-generated from SQL server Management Restore db dialog:

This is all stored in the registry for the directory paths, and you can retrieve it with Get-ItemPropertyValue. First you have to find the instance name that is running on your server.
$InstanceName=Get-ItemPropertyValue -Path 'HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL' -Name 'MSSQLServer'
Once you have that you can get the rest easily enough from the Setup key for that instance:
$BackupDir = Get-ItemPropertyValue -Path "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\$InstanceName\MSSQLServer" -Name 'BackupDirectory'
$RootDataDir = Get-ItemPropertyValue -Path "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\$InstanceName\Setup" -Name 'SQLDataRoot'
$MasterDataDir = Get-ItemPropertyValue -Path "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\$InstanceName\MSSQLServer\Parameters" -Name 'SQLArg0' | ForEach-Object {$_.Substring(2)}
$MasterLogsDir = Get-ItemPropertyValue -Path "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\$InstanceName\MSSQLServer\Parameters" -Name 'SQLArg2' | ForEach-Object {$_.Substring(2)}
The last two values have some extra characters before the path so I trimmed those, you may want to double check that yours are correct once you get the values. If you want other paths just poke around the MSSQLServer and Setup keys in the registry to find what you're looking for.

Related

Running SQL against multiple DB in azure pipeline

I want to set up the step in release process for azure pipeline where I can run the SQL from the file checked into the repo against multiple databases.
In my environment, I have one central db, one of the table for e.g "Control" table, keeps the connection to all the databases against which I need to run the sql during the deployment.
What I dont want to do is to setup the deployment step for each database. Is Powershell my only friend?
If so, how can I let powershell know what is the SQL in the file checked in during the deployment?
What I dont want to do is to setup the deployment step for each database. Is Powershell my only friend? If so, how can I let powershell know what is the SQL in the file checked in during the deployment?
In your case, Powershell seems to be the most appropriate.
In order to get the SQL in the file checked in during the deployment, we could use the powershell scripts to get the file names and paths, like:
$files=$(git diff HEAD HEAD~ --name-only)
$temp=$files -split ' '
$count=$temp.Length
echo "Total changed $count files"
For ($i=0; $i -lt $temp.Length; $i++)
{
$name=$temp[$i]
echo "this is $name file"
Copy-Item "$name" -Destination "$(System.DefaultWorkingDirectory)\SQLDeploymentFolder"
}
Check the ticket for some more details.
Then, we could use the extension Run SQL Server Scripts or Run SQL / SQLCMD Scripts passing multiple SQLCMD variables to all SQL Scripts in a folder.
Hope this helps.

Creating Registered Servers via Powershell in SSMS

A cool trick that used to work for me is creating Registered Server groups and registrations in SQL Server Management Studio via PowerShell. However, now that I am running the current version (SSMS 17.9.1) I find the functionality has been lost. I'm not sure when it broke.
After installing the SQLServer module:
Install-Module -Name SqlServer
you can open a PowerShell prompt by right-clicking on server group in the Registered Servers window, and clicking Start Powershell. Here, in the past, I've been able to create new groups and registrations with commands like:
Set-Location "sqlserver:\SQLRegistration\Database Engine Server Group"
# group
New-Item -Path "sqlserver:\SQLRegistration\Database Engine Server Group\AllServers"
# registration
New-Item -Name $(encode-sqlname 'sqlsrv') -path "sqlserver:\SQLRegistration\Database Engine Server Group\AllServers" -ItemType Registration -Value ("Server=sqlsrv ; integrated security=true");
These commands still run without error. But the new server registrations are not shown in the Registered Servers window afterwards after a refresh (or even a reboot).
And, server groups and registrations that are setup in the Registered Servers window are not shown with Get-Item/Get-ChildItem at the PowerShell prompt.
Is this functionality still working for anyone else in the current version?
I'm guessing something changed when the SQLPS powershell module were supplanted with the SQLServer module, but that's just a guess. If so I'm hoping there is just a tweak I need to use these commands under the new toolset.
This is an apparent bug in version 21.1.18068 of the SQLServer PowerShell module. Uninstalling that version and installing 21.0.17279 resolves the issue.
uninstall-module SQLServer
install-module -RequiredVersion 21.0.17224 -Name SQLServer

Remove-AzureRmSqlDatabase keeps asking me to run LoginAzureRmAccount

I have an Azure SQL database which I want to delete. The command should be:
Remove-AzureRmSqlDatabase -ResourceGroupName $dbResourceGroup -ServerName $dbServerName -DatabaseName $dbToDelete -Whatif -Force
The error I keep getting back is
Remove-AzureRmSqlDatabase : Run Login-AzureRmAccount to login.
I tried running Login-AzureRmAccount as myself, then as a service principal I use for unattended scripts, and nothing worked.
I am able to log into the Azure RM portal and delete databases. I am also able to run Invoke-SqlCmd against this database to query and manipulate data.
How can I make this work?
According to this error message, it seems that you have not login Azure whit the right subscription.
We can use this command to get the sql database's information, and check the subscription.
(Get-AzureRmSqlDatabase -DatabaseName jasontest1 -ServerName jasontest -ResourceGroupName jasontest).resourceid
Then we can find the subscription in the powershell output.
PS C:\Users> (Get-AzureRmSqlDatabase -DatabaseName jasontest1 -ServerName jasontest -ResourceGroupName jasontest).resourceid
/subscriptions/5384xxxx-xxxx-xxxx-xxxx-xxxxe29axxxx/resourceGroups/jasontest/providers/Microsoft.Sql/servers/jasontest/databases/jasontest1
To find which subscription, we can use this command Get-AzureRmSubscription to list it:
PS C:\Users> Get-AzureRmSubscription
Name : Visual Studio Ultimate with MSDN
Id : 5384xxxx-xxxx-xxxx-xxxx-xxxxe29axxxx
TenantId : 1fcfxxx-xxxx-xxxx-xxxx9-xxxx8bf8xxxx
State : Enabled
Also we can use this command to select the subscription:
Get-AzureRmSubscription -SubscriptionId 5384xxxx-xxxx-xxxx-xxx-xxxxe29axxxx
My Powershell Azure modules had dependency errors for something. To fix it I (at the behest of Microsoft tech support) ran:
PS C:\> Install-Module AzureRM -Force
This re-installed it and fixed the dependency problems.

Running Powershell via SQL Server Job

I have a very basic script which runs fine on my local PC. It simply backs up some folders and their contents then adds a date stamp on the folder name.
The script backs up folders on two different servers (Server2 & Server3).
Set-ExecutionPolicy -Scope Process -ExecutionPolicy RemoteSigned
#Part 1
Copy-Item -Path "\\Server3\Example Location" -Destination "\\Server3\Example Location_$(get-date -f yyyyMMdd)" -Recurse
#Part 2
Copy-Item -Path "\\Server2\Example Location" -Destination "\\Server2\Example Location_$(get-date -f yyyyMMdd)" -Recurse
It runs both parts perfectly in the below environments:
On my local PC
When I remotely connect to Server 2 and right click > Run with PowerShell
When I remotely connect to Server 2 and edit > Run script
However, when I try to automate this and create a SQL Server Agent Job (again, on Server 2) only Part 2 actually backs up. The job successfully completes, but Part 1 appears to get ignored (i.e. running on Server 2, backing up on Server 3).
Any ideas why running as a SQL job would cause this?
n.b. The job is set to run as 'SQL Server Agent Service Account'.
Couple things...
If you run your PS script as a step type Operating system (CmdExec) then there will never be an error message returned to the SQL-Server Job.
With that being said, if your SQL-Server Agent Service account does not have access to the \Server3... folders, the copy will fail and as above said, no error message will be transferred to the calling SQL-Agent Job.

How to execute .sql file using powershell?

I have a .sql file. I am trying to pass connection string details through a Powershell script and invoke an .sql file.
I was searching and came up with a cmdlet related to Invoke-sqlcmd. While I was trying to find a module corresponding to SQL, I did not find any one in my machine.
Should I install anything in my machine (the machine already has SQL Server Management Studio 2008 R2) to get the modules or is there any easy way to execute .sql files using Powershell?
Try to see if SQL snap-ins are present:
get-pssnapin -Registered
Name : SqlServerCmdletSnapin100
PSVersion : 2.0
Description : This is a PowerShell snap-in that includes various SQL Server cmdlets.
Name : SqlServerProviderSnapin100
PSVersion : 2.0
Description : SQL Server Provider
If so
Add-PSSnapin SqlServerCmdletSnapin100 # here lives Invoke-SqlCmd
Add-PSSnapin SqlServerProviderSnapin100
then you can do something like this:
invoke-sqlcmd -inputfile "c:\mysqlfile.sql" -serverinstance "servername\serverinstance" -database "mydatabase" # the parameter -database can be omitted based on what your sql script does.
Quoting from Import the SQLPS Module on MSDN,
The recommended way to manage SQL Server from PowerShell is to import
the sqlps module into a Windows PowerShell 2.0 environment.
So, yes, you could use the Add-PSSnapin approach detailed by Christian, but it is also useful to appreciate the recommended sqlps module approach.
The simplest case assumes you have SQL Server 2012: sqlps is included in the installation so you simply load the module like any other (typically in your profile) via Import-Module sqlps. You can check if the module is available on your system with Get-Module -ListAvailable.
If you do not have SQL Server 2012, then all you need do is download the sqlps module into your modules directory so Get-Module/Import-Module will find it. Curiously, Microsoft does not make this module available for download! However, Chad Miller has kindly packaged up the requisite pieces and provided this module download. Unzip it under your ...Documents\WindowsPowerShell\Modules directory and proceed with the import.
It is interesting to note that the module approach and the snapin approach are not identical. If you load the snapins then run Get-PSSnapin (without the -Registered parameter, to show only what you have loaded) you will see the SQL snapins. If, on the other hand, you load the sqlps module Get-PSSnapin will not show the snapins loaded, so the various blog entries that test for the Invoke-Sqlcmd cmdlet by only examining snapins could be giving a false negative result.
2012.10.06 Update
For the complete story on the sqlps module vs. the sqlps mini-shell vs. SQL Server snap-ins, take a look at my two-part mini-series Practical PowerShell for SQL Server Developers and DBAs recently published on Simple-Talk.com where I have, according to one reader's comment, successfully "de-confused" the issue. :-)
if(Test-Path "C:\Program Files\Microsoft SQL Server\MSSQL11.SQLEXPRESS") { #Sql Server 2012
Import-Module SqlPs -DisableNameChecking
C: # Switch back from SqlServer
} else { #Sql Server 2008
Add-PSSnapin SqlServerCmdletSnapin100 # here live Invoke-SqlCmd
}
Invoke-Sqlcmd -InputFile "MySqlScript.sql" -ServerInstance "Database name" -ErrorAction 'Stop' -Verbose -QueryTimeout 1800 # 30min
Here is a function that I have in my PowerShell profile for loading SQL snapins:
function Load-SQL-Server-Snap-Ins
{
try
{
$sqlpsreg="HKLM:\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.SqlServer.Management.PowerShell.sqlps"
if (!(Test-Path $sqlpsreg -ErrorAction "SilentlyContinue"))
{
throw "SQL Server Powershell is not installed yet (part of SQLServer installation)."
}
$item = Get-ItemProperty $sqlpsreg
$sqlpsPath = [System.IO.Path]::GetDirectoryName($item.Path)
$assemblyList = #(
"Microsoft.SqlServer.Smo",
"Microsoft.SqlServer.SmoExtended",
"Microsoft.SqlServer.Dmf",
"Microsoft.SqlServer.WmiEnum",
"Microsoft.SqlServer.SqlWmiManagement",
"Microsoft.SqlServer.ConnectionInfo ",
"Microsoft.SqlServer.Management.RegisteredServers",
"Microsoft.SqlServer.Management.Sdk.Sfc",
"Microsoft.SqlServer.SqlEnum",
"Microsoft.SqlServer.RegSvrEnum",
"Microsoft.SqlServer.ServiceBrokerEnum",
"Microsoft.SqlServer.ConnectionInfoExtended",
"Microsoft.SqlServer.Management.Collector",
"Microsoft.SqlServer.Management.CollectorEnum"
)
foreach ($assembly in $assemblyList)
{
$assembly = [System.Reflection.Assembly]::LoadWithPartialName($assembly)
if ($assembly -eq $null)
{ Write-Host "`t`t($MyInvocation.InvocationName): Could not load $assembly" }
}
Set-Variable -scope Global -name SqlServerMaximumChildItems -Value 0
Set-Variable -scope Global -name SqlServerConnectionTimeout -Value 30
Set-Variable -scope Global -name SqlServerIncludeSystemObjects -Value $false
Set-Variable -scope Global -name SqlServerMaximumTabCompletion -Value 1000
Push-Location
if ((Get-PSSnapin -Name SqlServerProviderSnapin100 -ErrorAction SilentlyContinue) -eq $null)
{
cd $sqlpsPath
Add-PsSnapin SqlServerProviderSnapin100 -ErrorAction Stop
Add-PsSnapin SqlServerCmdletSnapin100 -ErrorAction Stop
Update-TypeData -PrependPath SQLProvider.Types.ps1xml
Update-FormatData -PrependPath SQLProvider.Format.ps1xml
}
}
catch
{
Write-Host "`t`t$($MyInvocation.InvocationName): $_"
}
finally
{
Pop-Location
}
}
Here's a light weight approach for simple scripts that requires no additional tools / setup / PowerShell add-ons.
$conn = New-Object System.Data.SqlClient.SqlConnection
$conn.ConnectionString = $connectionStringGoesHere
$conn.Open()
$content = Get-Content $scriptFileNameGoesHere
$cmds = New-Object System.Collections.ArrayList
$cmd = ""
$content | foreach {
if ($_.Trim() -eq "GO") { $cmds.Add($cmd); $cmd = "" }
else { $cmd = $cmd + $_ +"`r`n" }
}
$cmds | foreach {
$sc = New-Object System.Data.SqlClient.SqlCommand
$sc.CommandText = $_
$sc.Connection = $conn
$sc.ExecuteNonQuery()
}
with 2008 Server 2008 and 2008 R2
Add-PSSnapin -Name SqlServerCmdletSnapin100, SqlServerProviderSnapin100
with 2012 and 2014
Push-Location
Import-Module -Name SQLPS -DisableNameChecking
Pop-Location
Invoke-Sqlcmd -Database MyDatabase -Query "exec dbo.sp_executesql N'$(Get-Content "c:\my.sql")'"