Format Powershell SQL query to print all items in columns - sql-server

I am using this style of sql connection and want to output the data into a table format but am only getting back the number of items. Having issues installing invoke-sql on old server not sure what the deal is... If any suggestions that would be great, for users that are stuck invoking sql like this :)
$user = "user"
$pwd = "password"
$SQLDBNAME = "database"
$SQLServer = ".\SQLEXPRESS"
$TagTable = "TagTable"
$sqlQuery = "SELECT TOP (10) [TagName] FROM [FactoryTalk_Datalog].[dbo].[TagTable]"
$sqlConnection = New-Object System.Data.SqlClient.SqlConnection
$sqlConnection.ConnectionString = "Server=$SQLServer;Database=$SQLDBName;uid=$user;pwd=$pwd"
#Create and configure a command object
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = $SqlQuery
$SqlCmd.Connection = $sqlConnection
#Create and configure a DataAdpater/DataSet pair of objects
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $SqlCmd
$DataSet = New-Object System.Data.DataSet
#Fill Dataset with Data and close the connection to the database
$SqlAdapter.Fill($Dataset)
Write-Host $DataSet
#$DataSet | Export-Csv -Path "C:\Users\admin\Documents\sqlApplication" -NoTypeInformation -Force
$sqlConnection.Close()

This worked for me :) using .Tables wrote it out perfect.
#Fill Dataset with Data and close the connection to the database
$SqlAdapter.Fill($Dataset)
$DataSet.Tables | Format-Table
write-host $DataSet
#$DataSet | Export-Csv -Path "C:\Users\admin\Documents\sqlApplication" -NoTypeInformation -Force
$sqlConnection.Close()

Related

Connecting to an SQL server using a different domain account

I am currently trying to connect to an SQL server using a different domain/username that has permissions for querying the server. Here is the powershell just to test whether or not the connection works,
$connectionString = "Server=<my_server>;Database=<db>;User ID=<domain>\<testuser>;Password=<password>;Trusted_Connection=False;Encrypt=True;TrustServerCertificate=True;";
$connection = New-Object System.Data.SqlClient.SqlConnection($connectionString);
$connection.Open();
$connection.Close();
I end up getting this error.
Exception calling "Open" with "0" argument(s): "Login failed for user '<testuser>'.
I am certain that the username and password is correct. As that's what's in the Client Settings.
But I am wondering if there's additional arguments needed to add to the connection string?
This task needed to be automated, but the solution was to connect to the server using -Credentials to login to the desired user.
$computerName = 'SQLServer'
$adminUsername = 'username'
$adminPassword = ConvertTo-SecureString 'password' -AsPlainText -Force
$adminCreds = New-Object PSCredential $adminUsername, $adminPassword
Invoke-Command -ScriptBlock {
$SQLServer = "sqlserver"
$SQLDBName = "database"
$uid ="account"
$pwd = "password"
$SqlQuery = "SELECT TOP (12) [attribute1]
FROM [table].[dbo].[AAG00200];"
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server = $SQLServer; Database = $SQLDBName; Integrated Security = True; User ID = $uid; Password = $pwd;"
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = $SqlQuery
$SqlCmd.Connection = $SqlConnection
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $SqlCmd
$DataSet = New-Object System.Data.DataSet
$SqlAdapter.Fill($DataSet)
} -ComputerName $computerName -Credential $adminCreds

MSSQl 'GO' handling in Powershell connection String

I have a sql query which is patched with a Go to check the orphan objects in mssql.
use DBName
go
sp_change_users_login 'report'
Now, I am automating the above in Powershell for all the user databases and trying to get the orphan users.
Here is the code:
if($port)
{
$connectionString ="server=$servername,$port;Integrated Security=true;" #uid=$DBUserName; pwd=$dbpwd;Database=$DB;
}
else
{
$connectionString ="server=$servername;Integrated Security=true;"
}
$connection = New-Object System.Data.SqlClient.SqlConnection -ea Stop
$connection.ConnectionString=$connectionString
$connection.Open()
$db_query = #"
Select name from sys.sysdatabases where dbid > 4 and name not in ('ReportServer')
"#
$command = $connection.CreateCommand()
$command.CommandText = $db_query
$result = $command.ExecuteReader()
$object= New-Object System.Data.DataTable
$object.Load($result)
[System.Array]$DBs = $object.name
if($DBs -is [System.Array])
{
foreach($DB in $DBs)
{
## PROBLEM IS HERE ###
$orphan_users_query = #"
use $DB
GO
sp_change_users_login 'report'
"#
$command = $connection.CreateCommand()
$command.CommandText = $orphan_users_query
$result = $command.ExecuteReader()
$object= New-Object System.Data.DataTable
$object.Load($result)
$object | Out-File C:\temp\outfile_property.txt -Append -Force
}
}
Problem is PS cannot identify the go separator because it is specific to MSSQL/SSMS. So, how can I still iterate and run the query in all user databases without creating multiple connections specific to each DB?
Calling ChangeDatabase on the connection is an alternate means of switching databases.
You can then just execute sp_change_users_login as is. No need for GO.

Calling stored procedure using powershell

i am trying to call a stored procedure from powershell by running the following. The name of the stored procedure is sp_sample (residing in ssms). But i am not able to see any output for the code in powershell and neither is the procedure getting triggered. Could someone please correct it.
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server=LABVM-
40\RTC;Database=testDB;Integrated Security=True"
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText ="sp_sample"
$SqlCmd.Connection = $SqlConnection
$sqlConnection.Open()
$Result = $SqlCmd.ExecuteNonQuery()
$sqlConnection.Close()
PS: I dont have knowledge on powershell and i picked the above code from the internet.
Invoke-Sqlcmd -ServerInstance "ServerName" -database "DatabaseName" -Query "EXEC dbo.sp_sample"

Get-ClusterGroup and foreach using imported SQL table

I am looking at getting information from a number of servers i.e. clustername, nodename, and state.
I can get the correct ouput when I hardcode the names into a foreach loop like this:
$clusters = "Cluster1", "Cluster2"
foreach ($cluster in $clusters) {
Get-ClusterGroup -Cluster $cluster
}
but when I run this version that pulls the information from a SQL table its coming up with the below error.
$clusters = $SQLServer = "DatawarehouseServer" #use Server\Instance for named SQL instances!
$SQLDBName = "Datawarehouse"
$SqlQuery = "SELECT clusters FROM dbo.clusters"
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server=$SQLServer;Database=$SQLDBName;Integrated Security=True"
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = $SqlQuery
$SqlCmd.Connection = $SqlConnection
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $SqlCmd
$DataSet = New-Object System.Data.DataSet
$SqlAdapter.Fill($DataSet)
$SqlConnection.Close()
clear
$DataSet.Tables[0]
foreach ($cluster in $clusters) {
Get-ClusterGroup -Cluster $cluster
}
WARNING: If you are running Windows PowerShell remotely, note that some failover
clustering cmdlets do not work remotely. When possible, run the cmdlet locally
and specify a remote computer as the target. To run the cmdlet remotely, try
using the Credential Security Service Provider (CredSSP). All additional errors
or warnings from this cmdlet might be caused by running it remotely.
Get-ClusterGroup : The cluster service is not running. Make sure that the
service is running on all nodes in the cluster. There are no more endpoints
available from the endpoint mapper
At line:26 char:2
+ {Get-ClusterGroup -Cluster $cluster}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ConnectionError: (:) [Get-ClusterGroup], ClusterCmdletException
+ FullyQualifiedErrorId : ClusterEndpointNotRegistered,Microsoft.FailoverClusters.PowerShell.GetClusterGroupCommand.
I have now been trying this I seem to be getting step closer or a step back depedant on how you look at it. It pulls the correct information out now but for only one cluster:
Thanks to the comments I have managed to get a step further or a step backwards with this:
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server=Datawarehouseserver;Database=Datawarehouse;Integrated Security=True"
$SqlConnection.Open()
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = "SELECT clusters FROM dbo.clusters"
$SqlCmd.Connection = $SqlConnection
$clustername = $SqlCmd.ExecuteScalar()
$SqlConnection.Close()
#Write-Output "Cluster is " $dbname
clear
foreach ($cluster in $clustername) {
Get-ClusterGroup -Cluster $cluster
}
You need to iterate over the cluster names returned by your SQL query, but your variable $cluster is never assigned that list of names. Use this instead:
foreach ($cluster in $DataSet.Tables[0].clusters) {
...
}

In powershell, how can I append one table to another and export to CSV?

I'm relatively new to Powershell, but here's what I'm trying to do:
I need to make multiple SQL queries and store the results to all of the queries in the same csv. With Powershell 3.0 I could use Export-CSV -Append, but unfortunately I need to use Powershell 2.0. Here is what I have right now.
#Connection Strings
$Database = "DB"
$Server = "localhost"
#Export File
$AttachmentPath = "C:\Users\Administrator\Desktop\SQLData.csv"
# Connect to SQL and query data, extract data to SQL Adapter
$SqlQuery = "select * from DB.dbo.DB1"
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Data Source=$Server;Initial Catalog=$Database;Integrated Security = True"
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = $SqlQuery
$SqlCmd.Connection = $SqlConnection
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $SqlCmd
$DataSet = New-Object System.Data.DataSet
$nRecs = $SqlAdapter.Fill($DataSet)
$nRecs | Out-Null
#Populate Hash Table
$objTable = $DataSet.Tables[0]
#Export Hash Table to CSV File
$objTable | Export-CSV $AttachmentPath
Write-Output "REPORT: Successfully created ${AttachmentPath}"
This will successfully create and export my table into a csv file that looks like this:
Table 1
----------------
col1(int) col2(string) col3(string)
col1(int) col2(string) col3(string)
but now I want to run a different query the exact same way
# Connect to SQL and query data, extract data to SQL Adapter
$SqlQuery = "select * from DB.dbo.DB2"
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Data Source=$Server;Initial Catalog=$Database;Integrated Security = True"
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = $SqlQuery
$SqlCmd.Connection = $SqlConnection
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $SqlCmd
$DataSet = New-Object System.Data.DataSet
$nRecs = $SqlAdapter.Fill($DataSet)
$nRecs | Out-Null
#Populate Hash Table
$objTable = $DataSet.Tables[0]
#IN POWERSHELL 3.0 THIS WOULD WORK
$objTable | Export-CSV $AttachmentPath -Append
and append it onto the first table. The final CSV would look like this:
Table 1
----------------
col1(int) col2(string) col3(string)
col1(int) col2(string) col3(string)
Table 2
----------------
col1(string) col2(int) col3(int)
col1(string) col2(int) col3(int)
I can't find any way to do this, any help is appreciated!
EDIT
Found a workaround by exporting the second query to a csv,
$objTable | Export-CSV $AttachmentPath
Then I used the Get-Content and Add-Content cmdlets to append to the first csv. It's hacky but it works. If you have anything better let me know!
$file2=Get-Content $AttachmentPath
Add-Content "SQLData.csv" "`n"
Add-Content "SQLData.csv" $file1
Why can't you use UNION in your query like below to get a merged data from both table
$SqlQuery = "select * from DB.dbo.DB1 UNION select * from DB.dbo.DB2"
Then you can use Export-CSV filename.csv commandlet to export the data to a CSV file (OR) see this thread How to export data to CSV in PowerShell?
While Union might not be acceptable for all situations, it is possible to merge two queries... just cast the output of numbers and dates to varchar/char.
SELECT Cast(col1(int) as varchar(7)) as col1, col2(string) as col2,
col3(string)
FROM [Table 1]
UNION ALL SELECT col1(string), Cast(col2(int) as varchar(7)),
Cast(col3(int) as varchar(7))
Just make sure you aren't truncating any data and you can mash em together.
Of course with 15 tables joining them in powershell would seem easier to maintain.

Resources