How to connect to ODBC in Powershell? - database

How can I connect to odbc from powershell?
I have found this function:
function Get-ODBC-Data{
param(
[string]$query=$('select count(*) from [master].[sys].[table_name]'),
)
$conn = New-Object System.Data.Odbc.OdbcConnection
$conn.ConnectionString = "DSN=AllSecure;"
$conn.open()
$cmd = New-object System.Data.Odbc.OdbcCommand($query,$conn)
$ds = New-Object system.Data.DataSet
(New-Object system.Data.odbc.odbcDataAdapter($cmd)).fill($ds) | out-null
$conn.close()
$ds.Tables[0]
}
$result = Get-ODBC-Data
Write-Host "Statistic: " $result[0];
Write-Host "Message: " $result[0] ;
But I still don't know how to use it!
Where am I supposed to provide a username and a password?
Can you please provide me with the command to run on Powershell to run the script?
Or is there a better way to connect?
THANKS!

Where am I supposed to provide a username and a password?
You include them as UID= and PWD= in the connection string:
$connStr = #"
DSN=mssqlLocal64;
UID=scott;
PWD=tiger;
"#
$con = New-Object System.Data.Odbc.OdbcConnection $connStr
$con.Open()
$sql = "SELECT name, create_date FROM sys.tables ORDER BY name"
$cmd = New-Object System.Data.Odbc.OdbcCommand $sql, $con
$rdr = $cmd.ExecuteReader()
while ($rdr.Read())
{
Write ("[{0}] -> {1}" -f $rdr["name"], $rdr["create_date"])
}
$rdr.Close()
$con.Close()

Related

How to pass csv file as query param in api call using powershell

I have developed two simple PS scripts that work fine separately. Script1 connects to a DB, run a sql query and save the output (only one column that is a list of the project names) as csv file. Script2 connects to an endpoint using API calls and prints the details of a projects. I use script1's output as script2's input manually. I have tried a couple of different ways to automate this process but I haven't been able to get it to work. Does anyone know how can I pass the csv file as query param in api call?
Here is what I have so far:
This is Script1:
#SQL Connection variables
$Server = "my server"
$DBName = "db name"
$credential = Import-CliXml -Path "C:\Test\MyCredential.xml"
$User = $Credential.UserName
$PW = $credential.GetNetworkCredential().Password
$Connection = New-Object System.Data.SqlClient.SqlConnection
$Connection.ConnectionString = "Server = $Server; Database = $DBName; User ID = $User; Password = $PW;"
$Connection.Open()
#$Connection.State
$SqlQuery = "select from table example"
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.Connection = $Connection
$SqlCmd.CommandText = $SqlQuery
$CxSqlCmd.CommandTimeout = 0
#Creating sql adapter
$SqlAdapter = New-Object System.Data.sqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $SqlCmd
#Creating Dataset
$DataSet = New-Object System.Data.DataSet
$SqlAdapter.Fill($DataSet)
$DataSet.Tables[0] | export-csv -Path $OuputFile -NoTypeInformation
The output for script 1 is 11223344, So I use this project name as my input or query param in my second script.
And this is Script2:
$credential = Import-CliXml -Path "C:\Test\MyCredential2.xml"
$credential = Import-CliXml -Path "C:\Test\MyCredential2.xml"
$APIKEY = $credential.GetNetworkCredential().Password
$token = "APIKEY " + "$APIKEY"
$Params = #{
uri = 'https:myendpoint/search?name=11223344'
Headers = #{'Authorization' = "API KEY $token"}
Method ='GET'
ContentType = 'application/json'
}
$Response = Invoke-RestMethod #Params
I really appreciate it if someone can help me with this.

PowerShell System.Data.SqlClient.SqlConnection shows no error but also no result

This script runs without any problems for a SQL Server connection:
[string] $connectionString = "Server=$server;Database=$database;Integrated Security = False; User ID = $uid; Password = $pwd;"
$sqlConn = New-Object System.Data.SqlClient.SqlConnection
$sqlConn.ConnectionString = $connectionString
$sqlConn.Open()
Write-Host "The connection is $($sqlConn.State)"
$command = $sqlConn.CreateCommand()
$command.CommandText = $query
$result = $command.ExecuteReader()
$sqlConn.Close();
Write-Host "The connection is $($sqlConn.State)"
$table = new-object “System.Data.DataTable”
$table.Load($result)
But only with that result
The connection is Open
The connection is Closed
I have tried many proper SQL queries which run in Management Studio without any problems. Any hint how to properly execute and maybe check the SQL connection?
The $result variable is a SqlDataReader. You need to leave the connection open when loading the data table from the reader:
$sqlConn.Open()
Write-Host "The connection is $($sqlConn.State)"
$command = $sqlConn.CreateCommand()
$command.CommandText = $query
$table = new-object “System.Data.DataTable”
$result = $command.ExecuteReader()
$table.Load($result)
$sqlConn.Close();
Write-Host "The connection is $($sqlConn.State)"
Consider simplifying using a SqlDataAdapter:
$dataAdapter = New-Object System.Data.SqlClient.SqlDataAdapter($query, $connectionString)
$table = new-object “System.Data.DataTable”
$dataAdapter.Fill($table)

How to execute stored procedure from Powershell?

Hopefully, this is not a duplicate. I aggregated numerous solutions I came across from the last year or so to get where I am. This is all relatively new to me and I am looking for the most secure and effective solution. When I run this, nothing happens. The intended result is to execute the stored procedure.
$Server = 'Server Name'
$database = 'DBName'
$userName = 'un'
$password = 'pw'
$Name = 'Name'
$Job = '15'
$Logs = Get-Content -Path $global:LOGFILE
$StartTime ='time'
$End = 'End'
$Connection = New-Object System.Data.SQLClient.SQLConnection
$Connection.ConnectionString = "Server=$('$Server');Database=$('$Database');trusted_connection=true;User Id=$('$userName');Password=$('$password')"
$Connection.Open()
$Command = New-Object System.Data.SQLClient.SQLCommand
$Command.Connection = $Connection
$Command.CommandText ="EXEC dbo.UpdateOutput #Name,#Job,#StartTime,#End,#Status,#Logs"
$Command.Parameters.AddWithValue("#Name", $Name)| Out-Null
$Command.Parameters.AddWithValue("#Job", $Job)| Out-Null
$Command.Parameters.AddWithValue("#Start", $StartTime)| Out-Null
$Command.Parameters.AddWithValue("#End", $End)| Out-Null
$Command.Parameters.AddWithValue("#Status", $Status)| Out-Null
$Command.Parameters.AddWithValue("#Logs", $Logs)| Out-Null
$Command.ExecuteNonQuery()
$Connection.Close()
Get rid of the apostrophes in the ConnectionString line as such:
$Connection.ConnectionString = "Server=$($Server);Database=$($Database);trusted_connection=true;User Id=$($userName);Password=$($password)"

Powershell SQL Select statements using csv variables

In the code below, I'm trying to query a DB with multiple select statements using variables brought in from a csv and load a data-table using a reader.
The code runs without error but does not retrieve any data.
$csv = Import-Csv $filepath
$database = "DBNAME"
$connectionString = "Server=$dataSource;uid=$user; pwd=$pwd;Database=$database;Integrated Security=True;"
$connection = New-Object System.Data.SqlClient.SqlConnection
$connection.ConnectionString = $connectionString
$connection.Open()
$sqlCommand = $connection.CreateCommand()
$Datatable = New-Object System.Data.DataTable
ForEach ($row in $csv){
$query = "Select Emailaddress,Column2 from Users Where [Emailaddress] = '$row.Email'"
$sqlCommand.CommandText = $query
$DataReader = $sqlCommand.ExecuteReader()
$DataTable.Load($DataReader)
}
$DataTable | export-csv "c:\Output\Seereader.csv" -NoTypeInformation
$connection.Close()
This:
$query = "Select Emailaddress,Column2 from Users Where [Emailaddress] = '$row.Email'"
Should probably be this:
$query = "Select Emailaddress,Column2 from Users Where [Emailaddress] = '$($row.Email)'"
Whilst the previous answer works, it is vulnerable to SQL injection.
Obligatory xkcd
If you're not sure what "SQL Injection" is; it's only a very worthy Google away...
i.e. you really need to go and find out!
The correct way...
Parameterise your queries!
# Your query; with a #param
$Query = "SELECT Emailaddress, Column2 FROM [Users] WHERE [Emailaddress] = #emailAddress";
# Set up your basic command
$command = $connection.CreateCommand()
$command.CommandText = $Query
# Fill in the parameters!
$command.Parameters.AddWithValue("#emailAddress", $row.Email)
# Run boy, run!
$results = $command.ExecuteReader()
# Resultification (that's definitely not a made up word)
$table = New-Object System.Data.DataTable
$table.Load($results)
Safe and sound :-)

SQL query for Bulk Update

I need to update a table using text file. Currently my code works fine if I perform Get-Content from txt file and then run the SQL update query, but only in case of small data. If the size of text is too long or it contains some special characters, it throws an error as following:
Exception calling "ExecuteReader" with "0" argument(s): "Incorrect syntax near
')</td><td style=\"border:1px solid #cccccc\">#fieldValueEmpty($issue.getCustom
FieldValue($componentTypeCf),'."
At C:\Users\d-mansings\Desktop\Scripted Field Configuration\Script\Prod_UpdateS
cript.ps1:78 char:37
+ $Reader = $Command.ExecuteReader <<<< ()
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
Following is the code I'm using:
Function DatabaseQueries(){
#To connect to the SQL database
$Connection = New-Object System.Data.SQLClient.SQLConnection
$Connection.ConnectionString = "Server=$IPSource ; Database=$DBNameSource ; User ID=$UserIDSource ; Password=$LoginPwdSource;"
$Connection.Open()
#Query to get the ID of the stored script field from propertyentry
$Command1 = New-Object System.Data.SQLClient.SQLCommand
$Command1.Connection = $Connection
$Command1.CommandText = "SELECT [ID] FROM [dbo].[propertyentry] WHERE [PROPERTY_KEY]='com.onresolve.jira.groovy.groovyrunner:customfields' "
$Reader = $Command1.ExecuteReader()
while ($Reader.Read()) {
$ID = $Reader.GetValue($1)
}
#To get the updated script file
$ScriptDir = $ParentDir + '\Script.txt'
$ScriptData = Get-Content "$ScriptDir"
$Connection.Close()
#Query to update the Script in JIRA database
$Connection.Open()
$Command = New-Object System.Data.SQLClient.SQLCommand
$Command.Connection = $Connection
$Command.CommandText = #"
Update [dbo].[propertytext] set [propertyvalue] ='$ScriptData' Where ID=$ID
"#
$Reader = $Command.ExecuteReader()
$Connection.Close()
}
It is difficult to write a complete solution if file contents and database structure are not specified. You surely encountered some kind of SQL injection. SQL Query concatenation is considered harmful and you should avoid it. Use ADO.NET parameters to pass variables ($Command.Parameters.AddWithValue in your example). See the following example:
function Invoke-Sql(
$ConnectionString,
$Query,
$Parameters
) {
$conn = New-Object System.Data.SqlClient.SqlConnection -ArgumentList $ConnectionString
$cmd = New-Object System.Data.SqlClient.SqlCommand -ArgumentList $Query,$conn
$conn.Open()
foreach ($arg in $Parameters.GetEnumerator()){
$cmd.Parameters.AddWithValue($arg.Key, $arg.Value) | Out-Null;
}
$reader = $cmd.ExecuteReader()
if ($reader.Read()) {
[string[]]$columns = 0..($reader.FieldCount-1) |
% { if ($reader.GetName($_)) { $reader.GetName($_) } else { "(no name $_)" } }
do {
$obj = #{}
0..($reader.FieldCount-1) | % { $obj.Add($columns[$_], $reader[$_]) }
New-Object PSObject -Property $obj
} while ($reader.Read())
}
$reader.Dispose()
$cmd.Dispose()
$conn.Dispose()
}
Invoke-Sql `
-ConnectionString "Server=.\SQL2014;Database=Test1;Integrated Security=true" `
-Query 'SELECT Name, Id [ObjectId], Id + 3, #arg FROM IdNameTest' `
-Parameters #{arg = 'Some text'''}
Invoke-Sql `
-ConnectionString "Server=.\SQL2014;Database=Test1;Integrated Security=true" `
-Query 'UPDATE IdNameTest SET Name=#name WHERE Id=#id' `
-Parameters #{name = "'DROP DATABASE Death;! %&#!$"; id=1}
Thanks for the response, I have figured out a way to execute the query by just using a replace function, as it was getting confused between the single inverted commas
select REPLACE(Cast(propertyvalue AS varchar(Max)), '''', '''''') FROM [dbo].[propertytext] WHERE ID=$ID

Resources