XML data coming in newline using invoke-sql command in powershell - sql-server

I am using a powershell script which will return an XML from a sqlquery of FOR XML EXPLICIT type.
Now, the query returned the XML in a column with header and dashed lines
XML 32776498797309
---------------------
<data>asdsafafaf<\data><value>dfsasfasfdfasdf....
dfdsfsdgregrge<\value><value>asdfasdfadfadfsda<\v
alue>
Here, some how we were able to remove header , dashed line and truncating of data.
but still the data comes in new line so if we open the XML it throws error because at some places the tag gets distributed as shown above.
Basically, new line issue is there.
We tried -width 4096
but since XML is huge it is not proper.
Please help, stuck big time.
Query used :
invoke-sqlcmd -inputFile $inputFilePath -serverinstance $dbHostName
-database $dbName -username $userName -password $password
| Format-Table -hide -Wrap -AutoSize
| Out-File -filePath $outputFilePath -width 4096

Try using set-content instead of out-file. Out-file will use the host/console formatting while set-content does not. You'll need to handle outputting XML to string
invoke-sqlcmd ....| select -expandproperty XML | set-content -path $outputFilePath
Edited. Added full working example:
#Contents of my test inputfile.sql:
SELECT CAST ('<EVENT_INSTANCE>
<EventType>CREATE_TABLE</EventType>
<PostTime>2011-04-26T15:05:21.333</PostTime>
<SPID>56</SPID>
<ServerName>Z001\SQL1</ServerName>
<LoginName>Contoso\u00</LoginName>
<UserName>dbo</UserName>
<DatabaseName>AdventureWorksDW2008R2</DatabaseName>
<SchemaName>dbo</SchemaName>
<ObjectName>AdventureWorksDWBuildVersion</ObjectName>
<ObjectType>TABLE</ObjectType>
<TSQLCommand>
<SetOptions ANSI_NULLS="ON" ANSI_NULL_DEFAULT="ON" ANSI_PADDING="ON" QUOTED_IDENTIFIER="ON" ENCRYPTED="FALSE" />
<CommandText>CREATE TABLE [dbo].[AdventureWorksDWBuildVersion] (
[DBVersion] [nvarchar] (50) NULL,
[VersionDate] [datetime] NULL
) ON [PRIMARY];
</CommandText>
</TSQLCommand>
</EVENT_INSTANCE>' AS XML)
$inputFilePath = "C:\Temp\inputfile.sql"
$dbHostName = "$env:computername\sql1"
$outputFilePath = "C:\Temp\output.txt"
#Notice Extra Line Breaks
invoke-sqlcmd -inputFile $inputFilePath -serverinstance $dbHostName |
Format-Table -hide -Wrap -AutoSize |
Out-File -filePath $outputFilePath -width 4096
#No Extra line breaks using set-content
invoke-sqlcmd -inputFile $inputFilePath -serverinstance $dbHostName | select -expandproperty Column1 | set-content -Path $outputFilePath

Use -MaxCharLength parameter of Invoke-SQLCMD command. By default it 4000. it will truncate big XMLs.
See Invoke-SqlCmd doesn't return long string?

Related

Loading URL result in SQL Server table with PowerShell

I have a PowerShell script that gives the latest SP and CU available of all the versions of SQL Server by directly querying over the web by using the below method and saving the output into an HTML file.
Invoke-WebRequest -UseBasicParsing -Uri $URI
I want the same result in a SQL Server table but I'm unable to do so. please help me understand how to achieve this.
Below is the complete code:
Note: You can directly execute this script.
-----------------------------------------------------------------------------------------------------
# Script to display all SQL Server Service Packs per version available on microsoft technet
$URI = "https://learn.microsoft.com/en-us/sql/database-engine/install-windows/latest-updates-for-microsoft-sql-server?view=sql-server-ver15"
$WebResponse = Invoke-WebRequest -UseBasicParsing -Uri $URI
# $WebResponse
# -----------------------------------------------------------------------------------------------------
# -------------------------------------------------
# Format the Output
# -------------------------------------------------
$content = $WebResponse.RawContent -replace "\s*`n", " "
$Tab=$content -match "<table(.*)</table>"
$Output=$matches[0]
while ($Output.Contains(" ")){
$Output = $Output -replace " "," "
}
$Output= $Output.replace('class="grid"','id="grid"').replace("<td> <strong>","<th>").replace("</strong> </td>","</th>")
$OutputFile=".\SQLServer-Latest-SP-CU.html"
$PageTableHeader | out-file $OutputFile -encoding default
out-file $OutputFile -encoding default -Append
$Output | out-file $OutputFile -encoding default -Append
out-file $OutputFile -encoding default -Append
Write-Host "Output written to $OutputFile"
start $OutputFile
Since your html is well-formed, you can use XML methods in T-SQL to parse and insert into a table. The example below take your existing $Output string with html and passes it as an XML parameter.
$sql = #"
CREATE TABLE dbo.SqlPatches(
ProductVersion varchar(30)
, LatestServicePack varchar(30)
, LatestCumulativeUpdate varchar(30)
, GeneralGuidance varchar(30)
);
INSERT INTO dbo.SqlPatches
SELECT
b.value('./td[1]','varchar(100)') AS ProductVersion
, b.value('./td[2]','varchar(100)') AS LatestServicePack
, b.value('./td[2]','varchar(100)') AS LatestCumulativeUpdate
, b.value('./td[2]','varchar(100)') AS GeneralGuidance
FROM #SqlPatches.nodes('/table/tbody/tr') AS a(b);
"#
$connection = New-Object System.Data.SqlClient.SqlConnection("Data Source=.;Initial Catalog=tempdb;Integrated Security=SSPI")
$command = New-Object System.Data.SqlClient.SqlCommand($sql, $connection)
$command.Parameters.Add("#SqlPatches", [System.Data.SqlDbType]::Xml).Value = $Output
$connection.Open()
[void]$command.ExecuteNonQuery()
$connection.Close()

How may I export the output of SQL query in Excel fetched through PowerShell?

I am using this power-shell script to fetch the versions of all SQL Servers in a list.
How may I export the result columns (only query output not error messages) into excel and send to email after the script is run?
Can someone help me add the required script please?
Import-Module SQLPS -DisableNameChecking
$ServerInstences = Get-Content "D:\DBA\All_Server_monitoring\ServerList.txt"
$SQLQuery = #"
Select ##Servername 'Server Name' ,##version 'Version'
"#
$DBName = "master"
$ServerInstences |
ForEach-Object {
$ServerObject = New-Object -TypeName Microsoft.SqlServer.Management.Smo.Server -ArgumentList $_
Invoke-Sqlcmd -ServerInstance $_ -Database $DBName -Query $SQLQuery
}
The easiest way to export data to a csv file is by using Export-CSV which takes an input object (or object array) and a path and can fill out the csv file from that object/array. For you, it would look like this:
$results = Invoke-Sqlcmd -ServerInstance $_ -Database $DBName -Query $SQLQuery
New-Item -Path "MYPATH.csv"
Export-CSV -Path "MYPATH.csv" -InputObject $results -Append
CSV files are versatile and can be opened with the most lightweight text editors. They also can be easily emailed and opened with Excel.

Getting an error when importing Excel file to SQL server database

I want to import an Excel file into my SQL server DB. Here is my code below:
$dir = "\\server\files\"
$latest = Get-ChildItem -Path $dir |
Where-Object {$_.name -like "*Data Action source *"} |
Sort-Object LastWriteTime -Descending |
Select-Object -First 1
Write-Output "The latest file is: $latest"
Write-SqlTableData -ServerInstance "instance1" -DatabaseName "db1" -SchemaName dbo -TableName Table1 -InputData $latest -Force
Write-Output "The latest file is $latest. Let's start the import"
The code picks the latest file nicely but when it comes to inserting into a database its failing with the error below:
Write-SqlTableData : A mapping between .Net type 'System.IO.DirectoryInfo' and SQL type for column 'Directory' was not found. Consider removing the column with that type and repeat the operation
From the error: The variable $latest is of the type System.IO.DirectoryInfo, which is not expected by the Write-SqlTableData command's -InputData parameter.
Run this line in the console for the documentation:
Get-Help Write-SqlTableData -Full
There, you will see this entry for -InputData
-InputData <PSObject>
Specifies the data to write to the database.
Typical input data is a System.Data.DataTable, but you can specify System.Data.DataSet or
System.Data.DateRow objects.
Required? true
Position? named
Default value none
Accept pipeline input? true (ByValue)
Accept wildcard characters? false
So the solution is to convert the csv into a format that this command can understand. The first step is to actually import the data into PowerShell as the moment all you have is file information (path, size etc)
Below, I have cast the CSV as psobject data type. This may still give you an error. For converting to System.Data.Datable which will be accepted, check out this link
dir = "\\server\files\"
$latest = Get-ChildItem -Path $dir |
Where-Object {$_.name -like "*Data Action source *"} |
Sort-Object LastWriteTime -Descending |
Select-Object -First 1
Write-Output "The latest file is: $latest"
# Import CSV to get the data
$csvData = Import-csv $latest.FullName
# Convert to psobject. This may still be rejected; I can't test. If it is, convert to DataTable.
$thingToImport = [psobject]$csvData
Write-SqlTableData -ServerInstance "instance1" -DatabaseName "db1" -SchemaName dbo -TableName Table1 -InputData $thingToImport -Force
Write-Output "The latest file is $latest. Let's start the import"

Read contents of an Excel file using PowerShell and store it in a SQL Server database

I am trying to write the contents of an Excel file (on tab 5) to a database but it keeps failing.
Here is my code:
$dir = "\\server\files\"
$latest = Get-ChildItem -Path $dir | Where-Object {$_.name -like "*Data Notes*"} | Sort-Object LastWriteTime -Descending | Select-Object -First 1
Write-Output "The latest file is: $latest"
Write-SqlTableData -ServerInstance "sql server" -DatabaseName "sql5" -SchemaName dbo -TableName Temptable100 -InputData $latest.FullName -Force
The table gets created fine but its empty. Can anyone please help me??
I have attached the contents of the Excel file here:
Write-SQLTableData won't be able to read an Excel file so you will need to use something like OLEDB to first read the Excel table into a DataTable and then pass that DataTable to Write-SQLTableData.
All I needed was to store the information in a data variable and then use the Write-SQLTableData to store the information in a database. See below:
Write-SqlTableData -ServerInstance "instance" -DatabaseName "db1" -SchemaName dbo -TableName TableName -InputData $DataTable -Force

How to search for a string in all stored procedures through SQL Powershell?

I have a bunch of stored procedures in my database, I launched the PowerShell for SQL Server by right clicking on the Stored Procedures folder in SSMS and choosing Start Powershell, I tried the following command but it gives me nothing
PS SQLSERVER:\SQL\MYCOMP\DEFAULT\Databases\MYDB\StoredProcedures> Get-ChildItem | ForEach-Object { (Invoke-SQLCMD -SuppressProviderContextWarning -Query ("sp_helptext '$_'" )) | Select-String mykeyword}
If I remove the | Select-String mykeyword part, it spits out the code for every stored procedure one by one. What am I missing?
Your command is returning an array of PSCustomObjects that have a string property named "Text". You need to pipe the value of that property to select-string. Right now you are calling select-string on an object that is not a string. Change to:
Get-ChildItem | ForEach-Object { (Invoke-SQLCMD -SuppressProviderContextWarning -Query ("sp_helptext '$_'" )) } | Select-Object Text | Select-String yourKeyword
To answer your later question about outputting the sp name, you could store the name in a variable and output it, something like:
$sName = '';
Get-ChildItem | ForEach-Object { $sName = $_.Name; (Invoke-SQLCMD -SuppressProviderContextWarning -Query ("sp_helptext '$_'" )) } | Select-Object Text | Select-String yourKeyword | ForEach-Object { Write-Host $sName }
I see that there's already an answer, but this was slightly more useful to me:
Get-ChildItem | ForEach-Object { if(($line=Invoke-SQLCMD -SuppressProviderContextWarning -Query ("sp_helptext '$_'" ) | Where Text -like '*Title*'| select -expand Text)) {$_;$line}}
I'm outputting the stored procedure objects as well as the matching lines (interspersed). It would probably be worthwhile to make this into a function and package the output as objects but this is a good start.

Resources