Using Powershell get Values from sql table - sql-server

we know that we can use sql query window to get values from Database like "select * from....". Is there any way to get a value through powershell way. I found the way to database table itself but not to the values..
Ex:
Set-location SQLserver:\sql\default\localhost\databases\database\tables
Get-childitem
Above command gives me tables in the DB , but how can i get the values from it.

Most concise and straightforward option is Invoke-SqlCommand
$results = Invoke-Sqlcmd -ServerInstance "mySqlServer" -Database "myDatabase" -Query "SELECT * FROM MyTable"

You can use this
$connectionString = “Server=$dataSource;uid=$user; pwd=$pwd;Database=$database;Integrated Security=False;”
$connection = New-Object System.Data.SqlClient.SqlConnection
$connection.ConnectionString = $connectionString
$connection.Open()
$query = “SELECT * FROM Tab”
$command = $connection.CreateCommand()
$command.CommandText = $query
$result = $command.ExecuteReader()

The SQL Server Powershell provider uses SMO to expose the database object hierarchy. Once you get a SMO child item, you can invoke the corresponding SMO methods on the object.
The SMO Database ExecuteQueryWithResults method can be used to execute a query in the context of a given database. Get the desired database item and invoke this method to return a DataSet object containing the results. Then retrieve the data as desired from the DataSet.
Below is an example gleaned from the SMO reference ((https://msdn.microsoft.com/en-us/library/ms205775.aspx) that can be run from the context of the Databases node:
$db = Get-Item SomeDatabase
$dt = $db.ExecuteWithResults("SELECT * FROM sys.objects;")
$dt.Tables[0] | Format-Table

Do you means the powershell command like below:
$MyVar = New-Object Microsoft.SqlServer.Management.SMO.Table
$MyVar | Get-Member -Type Properties
For more information you could visit https://technet.microsoft.com/en-us/library/cc281939(v=sql.105).aspx
If you want to get the value of table,
//Connect to the local, default instance of SQL Server.
{
Server srv = default(Server);
srv = new Server();
//Call the EnumCollations method and return collation information to DataTable variable.
DataTable d = default(DataTable);
//Select the returned data into an array of DataRow.
d = srv.EnumCollations;
//Iterate through the rows and display collation details for the instance of SQL Server.
DataRow r = default(DataRow);
DataColumn c = default(DataColumn);
foreach ( r in d.Rows) {
Console.WriteLine("=====================================");
foreach ( c in r.Table.Columns) {
Console.WriteLine(c.ColumnName + " = " + r(c).ToString);
}
}
}
The above is how to do the job via C# but how to do that in powershell: You have got $MyVar values, and you run "$MyVar |Get-Member" is to show all method of all method available for $MyVar, I believe there should have some method allow you iterator all row or column for thr table. The powerShell even can invoke C# method, but this is the last choose.

There is now an sqlserver module available for powershell
You now have available the following two additional commands and options
Read-SqlTableData [[-ServerInstance] <String[]> ] [-ColumnName <String[]> ] [-ColumnOrder <String[]> ] [-ColumnOrderType <OrderType[]> ] [-ConnectionTimeout <Int32> ] [-Credential <PSCredential> ] [-DatabaseName <String> ] [-IgnoreProviderContext] [-OutputAs <OutputTypeSingleTable> {DataSet | DataTable | DataRows} ] [-SchemaName <String> ] [-SuppressProviderContextWarning] [-TableName <String> ] [-TopN <Int64> ] [ <CommonParameters>]
Write-SqlTableData [[-ServerInstance] <String[]> ] -InputData <PSObject> [-ConnectionTimeout <Int32> ] [-Credential <PSCredential> ] [-DatabaseName <String> ] [-Force] [-IgnoreProviderContext] [-Passthru] [-SchemaName <String> ] [-SuppressProviderContextWarning] [-TableName <String> ] [-Timeout <Int32> ] [ <CommonParameters>

You can use the AdoLib module in SQLPSX (SQLPSX.codeplex.com).
With that, you can use cmdlets and do things like:
invoke-sqlquery -sql "select * from tab" -server SQLServer01 -database MyDatabase

Related

ADO.NET query not showing in XEvents

I sent a query to SQL Server using an ADO.Net SqlAdapter from PowerShell. The query returns the correct result.
When I run an XEvent session with the sqlserver.sql_statement_starting event, the query from ADO.NET does not show up. Queries I sent from SSMS are shown immediately.
Is this a bug, or why do I not see the ADO.NET queries?
The code I am using is
$serverName = 'localhost'
$databaseName = 'Contoso Retail DW'
$schemaName = 'dbo'
$tableName = 'FactSalesFMCG'
$connString = Get-ConnectionString -IntegratedSecurity -Server $serverName -Database $databaseName
$sqlConn = [System.Data.SqlClient.SqlConnection]::new($connString)
$sqlConn.Open()
$columnMetadataAdapter = Get-ColumnMetadataAdapter -Conn $sqlConn -SchemaName $schemaName -TableName $tableName
$table = [System.Data.DataTable]::new()
$columnMetadataAdapter.Fill($table)
$sqlConn.Close()
Get-ConnectionString and Get-ColumnMetadataAdapter are PowerShell functions that assist in creating the needed ADO.NET objects. The table gets filled with the column metadata I wanted, but the SELECT statement is not shown in XEvents.
Can't repro.
CREATE EVENT SESSION [trc] ON SERVER
ADD EVENT sqlserver.rpc_completed,
ADD EVENT sqlserver.sp_statement_completed,
ADD EVENT sqlserver.sql_batch_completed,
ADD EVENT sqlserver.sql_statement_completed
GO
Start the session and watch live events in SSMS.
Then
PS C:\Users\dbrowne> $da = new-object system.data.sqlclient.sqldataadapter
PS C:\Users\dbrowne> $con = new-object system.data.sqlclient.sqlconnection "server=.;database=tempdb;integrated security=true"
PS C:\Users\dbrowne> $con.open()
PS C:\Users\dbrowne> $cmd = $con.createcommand()
PS C:\Users\dbrowne> $cmd.commandtext = "select * from sys.objects"
PS C:\Users\dbrowne> $da.selectcommand = $cmd
PS C:\Users\dbrowne> $dt = new-object system.data.datatable
PS C:\Users\dbrowne> $da.fill($dt)
106
and see both the sql_statement_completed and the sql_batch_completed (note with different code you might get an rpc_completed instead of a sql_batch_completed).
If you bind parameters into the SqlCommand it will be sent as an RPC call instead of a batch call, and the events will be a bit different rpc/sp instead of batch/sql.
rpc_completed/sp_statement_completed
instead of
sql_batch_completed/sql_statement_completed

How to use PowerShell to batch call Update-Database

We use an Azure Elastic Pool resulting in multiple client databases and one master database with references to the client database.
We already have multiple databases and are working on a new version of the code. We use EF6 Code-First.
When we make a change to our model (add a property) we create the migration file and need to call Update-Database for all existing client databases.
This is monkey work we want to skip.
I already have a Powershell script to connect to the master database and execute a query on a table. This returns the names of the child databases.
With it I can change the Web.config and replace the Template database name with the proper name of the child database.
Now I need to call Update-Database to execute the migration scripts. With this last part I'm struggling because I'm running the ps1-script outside Visual Studio and thus the command Update-database is unknown. I tried using migrate.exe but then I get lots of errors.
I think the easiest solution is to run my script within the Package manager console but I can't figure out how to do that.
I managed to get it working. After I placed the ps1-file in the root of my code folder I could run it in the Package Manager Console using .\UpdateDatabases.ps1.
For completeness here's the script I created. I'm new to PowerShell so some optimizations might be possible.
cls
$currentPath = (Get-Item -Path ".\" -Verbose).FullName
#Read Web.config
$webConfig = $currentPath + "\<your project>\Web.config"
$doc = (Get-Content $webConfig) -as [Xml]
$DatabaseNamePrefix = $doc.configuration.appSettings.add | where {$_.Key -eq 'DatabaseNamePrefix'}
#Get Master connectionstring
$root = $doc.get_DocumentElement();
foreach($connString in $root.connectionStrings.add | where {$_.Name -eq "Master"})
{
$masterConn = $connString.connectionString
}
#Connect to master database
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = $masterConn
#Query Client table for the child database names
$SqlQuery = "select Code from Clients"
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = $SqlQuery
$SqlCmd.Connection = $SqlConnection
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $SqlCmd
#Put query result in dataset
$DataSet = New-Object System.Data.DataSet
$SqlAdapter.Fill($DataSet)
$SqlConnection.Close()
foreach ($row in $DataSet.Tables[0].Rows)
{
$clientDbName = $row[0].ToString().Trim()
#Change Web.Config
foreach($connString in $root.connectionStrings.add | where {$_.Name -eq "DevelopmentDb"})
{
$newDatabaseName = "Database=" + $DatabaseNamePrefix.value + $clientDbName + ";";
$newConn = $connString.connectionString -replace "(Database=.*?;)",$newDatabaseName
$connString.connectionString = $newConn;
}
$doc.Save($webConfig)
#Update database
Update-Database -ConfigurationTypeName Application
}
"Finished"
You may want to take a look at Azure Elastic Database Jobs. Which is designed to work with the elastic database pools.
The Elastic Database Jobs SDK includes also PowerShell components.

How do I execute a SELECT query against a SQLServer database and iterate results using PowerShell

Say I have a table with 3 columns - "Column1", "Column2", and "Column3" - datatype is varchar(100) for all 3.
Using PowerShell, how do I connect to SQL Server and use SqlDataReader and ForEach operator to view the contents of "Column2"?
Here's roughly how I'm doing it:
$SqlServer = 'sql.example.com';
$SqlDatabase = 'MyDB';
$SqlConnectionString = 'Data Source={0};Initial Catalog={1};Integrated Security=SSPI' -f $SqlServer, $SqlDatabase;
$SqlQuery = "SELECT Name FROM dbo.Person ORDER BY Name;";
$SqlConnection = New-Object -TypeName System.Data.SqlClient.SqlConnection -ArgumentList $SqlConnectionString;
$SqlCommand = $SqlConnection.CreateCommand();
$SqlCommand.CommandText = $SqlQuery;
$SqlConnection.Open();
$SqlDataReader = $SqlCommand.ExecuteReader();
#Fetch data and write out to files
while ($SqlDataReader.Read()) {
Write-Output $SqlDataReader['Name'];
}
$SqlConnection.Close();
$SqlConnection.Dispose();
If I remember right, I basically refactored the code from the MSDN example.
For those wondering why I'm using SqlDataReader: Most of my scripts use SqlDataAdapter, but this one retrieves about 8,000 PDFs from a database so I wasn't really interested in calling SqlDataAdapter.Fill(). In exchange for holding shared locks on the table much longer than SqlDataAdapter.Fill() would, SqlDataReader.Read() keeps memory usage down to a manageable level for the client by fetching one record at a time.

Powershell: Retrieve xml data from column in SQL Server database

Following this tutorial I tried to use PowerShell to retrieve xml data from SQL Server, but I only get one element back.
Here is a query to show the actual data:
But running this script I only get one element back:
$SQLServer = 'MYSERVER,1433'
$SQLDBName = "test"
$Query =
#'
USE test
SELECT EventLogXML FROM ForwardedEvents
'#
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server = $SQLServer; Database = $Database; Integrated Security = True"
$SqlConnection.open()
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = $Query
$SqlCmd.Connection = $SqlConnection
$xr = $SqlCmd.ExecuteXmlReader()
$xd = New-Object System.Xml.XmlDataDocument
$xd.Load($xr)
$xr.Close()
$SQLConnection.Close()
$xd
$xd only has one element. What am I doing wrong?
---edit
I can confirm its only one xml doc by doing $xd.outerxml which reveals the complete doc. It is only one of the thousand or so event xml docs I'm storing in the EventLogXML column.
I think that XmlDataDocument is mainly for returning a single xml. Basically if you do in sql select * from bla for xml, auto you then can read it with the ExecuteXmlReader and XmlDataDocument. This is not what you want.
Modifying the example you linked to your needs we'll get somethign like:
$con = New-Object System.Data.SqlClient.SqlConnection
$con.ConnectionString = "Server=.; Database=AdventureWorks2012;Integrated Security=true"
$con.open()
$cmd = New-Object System.Data.SqlClient.SqlCommand
$cmd.CommandText = "SELECT Instructions FROM Production.ProductModel WHERE Instructions is not null"
$cmd.Connection = $con
$as = New-Object System.Data.SqlClient.SqlDataAdapter
$ds = New-Object System.Data.DataSet
$as.SelectCommand = $cmd
$as.Fill($ds);
$xmlDocs = $ds.Tables[0] | %{ [xml]$_.Instructions }
Now xmlDocs will contain a list of xml documents, one document per row.
Powershell wraps XML stuff into handy little objects, which you can explore using .Property syntax. If you just look at $xd, powershell by default will only show you the root node.
I don't know the structure of your XML column, but if the root node is called MyRoot, followed by common subnodes called MySub, try something like this:
$xd.MyRoot.MySub
This is just as the linked example shows the need to use $xd.root.Location
Edit
Ok so that is not the problem. Looks like it is by-design to return back only the first row when calling ExecuteXmlReader with a normal select statement (doc here):
if more than one row is returned, the ExecuteXmlReader method attaches
the XmlReader to the value on the first row, and discards the rest of
the result set
From some basic searching around, this blog post seems to explain the issue the best, and provides a workaround. See also here.
I may be out to lunch, but couldn't it be because you are declaring the database as $SQLDBName and then trying to connect to $Database in your connectionstring?

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