I would like to get the transaction begin timestamp with SQL Anywhere 17.
Below a sample script in Powershell:
Add-Type -AssemblyName ("Sap.Data.SQLAnywhere.v4.5, Version=17.0.8.40434, Culture=neutral, PublicKeyToken=f222fc4333e0d400")
$connectionString = "DSN=My_Source;DBN=My_Database;UID=My_User;PWD=My_Password;"
$conn = New-Object Sap.Data.SQLAnywhere.SAConnection($connectionString)
$conn.Open()
$cmd = New-Object Sap.Data.SQLAnywhere.SACommand('SELECT NOW()', $conn)
$cmd.Transaction = $conn.BeginTransaction([System.Data.IsolationLevel]'ReadCommitted')
$dt = New-Object System.Data.DataTable
0..1 | % {
Start-Sleep $_
$reader = $cmd.ExecuteReader()
$dt.Clear()
$dt.Load($reader)
Write-Host $dt.Rows[0].ItemArray[0]
}
$cmd.Transaction.Rollback()
$cmd.Dispose()
$conn.Close()
And the output:
6/4/2018 11:40:01 AM
6/4/2018 11:40:02 AM
As you can see consecutive calls to NOW() function provides an increasing timestamp.
I did try using "SELECT CURRENT TIME" without success as well.
Any advice?
I am trying to run a SQL from Power Shell(which is on my windows 7 64 bit desktop) and the remote database host is MS SQL Server 2012.
The code is:
$var1 = 'string';
function Get-ODBC-Data{
param(
[string]$query=$('
SELECT COUNT(*)
FROM [master].[sys].[table_name]
WHERE col2 = ''$var1''
;
'),
[string]$username='db_user_name',
[string]$password='db_password'
)
$conn = New-Object System.Data.Odbc.OdbcConnection
$conn.ConnectionString = "DRIVER={SQL Server};Server=123.456.78.90;Initial Catalog=master;Uid=$username;Pwd=$password;"
$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 "SQL_Output: " $result[0];
If I use 'string' in the SQL's where clause instead of $var1 then te script works fine and gives expected result.
Quetion
But I want to be able to pass any string as $var1 to the script as parameter. Then use it in the where clause of the SQL. How can I achieve this?
What I tried
I have tried to enclose $var1 in 1,2 or 3 single quotes in the where clause in attempt to escape the single quote. Also tried adding/removing single quote from 'string' when $var1 is assigned value. I did try [string]$var1 = 'string' as well but none of these worked and I keep getting error mostly related to SQL syntax.
Try this:
function Get-ODBC-Data{
param(
[string]$query=$("
SELECT COUNT(*)
FROM [master].[sys].[table_name]
WHERE col2 = '$($var1)'
;
"),
[string]$username='db_user_name',
[string]$password='db_password'
)
$conn = New-Object System.Data.Odbc.OdbcConnection
$conn.ConnectionString = "DRIVER={SQL Server};Server=123.456.78.90;Initial Catalog=master;Uid=$username;Pwd=$password;"
$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 "SQL_Output: " $result[0];
The following runs fine on my setup, and shows the correct results:
$var1 = "test22"
function Get-ODBC-Data{
param(
[string]$query=$("
SELECT COUNT(*)
FROM [master].[sys].[table_name]
WHERE col2 = '$($var1)'
;
"),
[string]$username='db_user_name',
[string]$password='db_password'
)
return $query
}
$result = Get-ODBC-Data
Write-Host " ################### Query ######################## "
Write-Host $result
However, you may have a much easier time just passing the entire query into the function as a parameter rather than just one variable part of the query.
Or setting it inside the function and passing $var1 as a mandatory parameter like so:
function Get-ODBC-Data{
param(
[parameter(Mandatory=$true)][string]$var1,
[string]$username='db_user_name',
[string]$password='db_password'
)
$query="
SELECT COUNT(*)
FROM [master].[sys].[table_name]
WHERE col2 = '$($var1)'
;"
return $query
}
$result = Get-ODBC-Data -var1 "working"
Write-Host " ################### Query ######################## "
Write-Host $result
My PowerShell script below works great and returns the two rows from different databases in 1 DataTable, but I can't work out how to compare these 2 rows.
The situation is I have 2 database servers, and want to compare max(id) from the same table on both, compare and then possibly alert if they're different.
The alerting bit I can do, but I haven't used DataTables before.
function readServer1 {
# Connection variables
$server = "db1"
$port = 1234
$driver = "Adaptive Server Enterprise"
$query = "select max(id) as 'id' from table"
$db = "db"
$uid = "uid"
$pwd = "pwd"
# Create Object and Connection
$conn = New-Object System.Data.Odbc.OdbcConnection
$conn.ConnectionString = "driver={$driver};db=$db;na=$server,$port;uid=$uid;pwd=$pwd;"
$conn.Open()
$cmd = New-Object System.Data.Odbc.OdbcCommand($query, $conn)
$cmd.CommandTimeout = 30
# Create a Data Table
$dt = New-Object System.Data.DataTable
$dt.Load($cmd.ExecuteReader())
$dt.Rows
# Close Connection
$conn.Close()
}
function readServer2 {
# Connection variables
$server = "db2"
$port = 1234
$driver = "Adaptive Server Enterprise"
$query = "select max(id) as 'id' from table"
$db = "db"
$uid = "uid"
$pwd = "pwd"
# Create Object and Connection
$conn = New-Object System.Data.Odbc.OdbcConnection
$conn.ConnectionString = "driver={$driver};db=$db;na=$server,$port;uid=$uid;pwd=$pwd;"
$conn.Open()
$cmd = New-Object System.Data.Odbc.OdbcCommand($query, $conn)
$cmd.CommandTimeout = 30
# Create a Data Table
$dt = New-Object System.Data.DataTable
$dt.Load($cmd.ExecuteReader())
$dt.Rows
# Close Connection
$conn.Close()
}
readServer1
readServer2
It returns results like this:
id
--
12345
12346
Just put function execution results to variables and compare them. Like so:
$var1 = readServer1 | Select -Expand id
$var2 = readServer2 | Select -Expand id
if ($var1 -ne $var2) { Do-That }
Is there a way to execute an arbitrary query on a SQL Server using Powershell on my local machine?
For others who need to do this with just stock .NET and PowerShell (no additional SQL tools installed) here is the function that I use:
function Invoke-SQL {
param(
[string] $dataSource = ".\SQLEXPRESS",
[string] $database = "MasterData",
[string] $sqlCommand = $(throw "Please specify a query.")
)
$connectionString = "Data Source=$dataSource; " +
"Integrated Security=SSPI; " +
"Initial Catalog=$database"
$connection = new-object system.data.SqlClient.SQLConnection($connectionString)
$command = new-object system.data.sqlclient.sqlcommand($sqlCommand,$connection)
$connection.Open()
$adapter = New-Object System.Data.sqlclient.sqlDataAdapter $command
$dataset = New-Object System.Data.DataSet
$adapter.Fill($dataSet) | Out-Null
$connection.Close()
$dataSet.Tables
}
I have been using this so long I don't know who wrote which parts. This was distilled from others' examples, but simplified to be clear and just what is needed without extra dependencies or features.
I use and share this often enough that I have turned this into a script module on GitHub so that you can now go to your modules directory and execute git clone https://github.com/ChrisMagnuson/InvokeSQL and from that point forward invoke-sql will automatically be loaded when you go to use it (assuming your using PowerShell v3 or later).
You can use the Invoke-Sqlcmd cmdlet
Invoke-Sqlcmd -Query "SELECT GETDATE() AS TimeOfQuery;" -ServerInstance "MyComputer\MyInstance"
http://technet.microsoft.com/en-us/library/cc281720.aspx
This function will return the results of a query as an array of powershell objects so you can use them in filters and access columns easily:
function sql($sqlText, $database = "master", $server = ".")
{
$connection = new-object System.Data.SqlClient.SQLConnection("Data Source=$server;Integrated Security=SSPI;Initial Catalog=$database");
$cmd = new-object System.Data.SqlClient.SqlCommand($sqlText, $connection);
$connection.Open();
$reader = $cmd.ExecuteReader()
$results = #()
while ($reader.Read())
{
$row = #{}
for ($i = 0; $i -lt $reader.FieldCount; $i++)
{
$row[$reader.GetName($i)] = $reader.GetValue($i)
}
$results += new-object psobject -property $row
}
$connection.Close();
$results
}
Here's an example I found on this blog.
$cn2 = new-object system.data.SqlClient.SQLConnection("Data Source=machine1;Integrated Security=SSPI;Initial Catalog=master");
$cmd = new-object system.data.sqlclient.sqlcommand("dbcc freeproccache", $cn2);
$cn2.Open();
if ($cmd.ExecuteNonQuery() -ne -1)
{
echo "Failed";
}
$cn2.Close();
Presumably you could substitute a different TSQL statement where it says dbcc freeproccache.
If you want to do it on your local machine instead of in the context of SQL server then I would use the following. It is what we use at my company.
$ServerName = "_ServerName_"
$DatabaseName = "_DatabaseName_"
$Query = "SELECT * FROM Table WHERE Column = ''"
#Timeout parameters
$QueryTimeout = 120
$ConnectionTimeout = 30
#Action of connecting to the Database and executing the query and returning results if there were any.
$conn=New-Object System.Data.SqlClient.SQLConnection
$ConnectionString = "Server={0};Database={1};Integrated Security=True;Connect Timeout={2}" -f $ServerName,$DatabaseName,$ConnectionTimeout
$conn.ConnectionString=$ConnectionString
$conn.Open()
$cmd=New-Object system.Data.SqlClient.SqlCommand($Query,$conn)
$cmd.CommandTimeout=$QueryTimeout
$ds=New-Object system.Data.DataSet
$da=New-Object system.Data.SqlClient.SqlDataAdapter($cmd)
[void]$da.fill($ds)
$conn.Close()
$ds.Tables
Just fill in the $ServerName, $DatabaseName and the $Query variables and you should be good to go.
I am not sure how we originally found this out, but there is something very similar here.
There isn't a built-in "PowerShell" way of running a SQL query. If you have the SQL Server tools installed, you'll get an Invoke-SqlCmd cmdlet.
Because PowerShell is built on .NET, you can use the ADO.NET API to run your queries.
Invoke-Sqlcmd -Query "sp_who" -ServerInstance . -QueryTimeout 3
To avoid SQL Injection with varchar parameters you could use
function sqlExecuteRead($connectionString, $sqlCommand, $pars) {
$connection = new-object system.data.SqlClient.SQLConnection($connectionString)
$connection.Open()
$command = new-object system.data.sqlclient.sqlcommand($sqlCommand, $connection)
if ($pars -and $pars.Keys) {
foreach($key in $pars.keys) {
# avoid injection in varchar parameters
$par = $command.Parameters.Add("#$key", [system.data.SqlDbType]::VarChar, 512);
$par.Value = $pars[$key];
}
}
$adapter = New-Object System.Data.sqlclient.sqlDataAdapter $command
$dataset = New-Object System.Data.DataSet
$adapter.Fill($dataset) | Out-Null
$connection.Close()
return $dataset.tables[0].rows
}
$connectionString = "connectionstringHere"
$sql = "select top 10 Message, TimeStamp, Level from dbo.log " +
"where Message = #MSG and Level like #LEVEL"
$pars = #{
MSG = 'this is a test from powershell'
LEVEL = 'aaa%'
};
sqlExecuteRead $connectionString $sql $pars
You can even format string and pass parameters as you want.
case "ADDSQLSERVERUSER":
//0 = coprorateName;
//1 = user password
//2 = servername
command = #"$sqlQuery = Use JazzUWS_'{0}'
Create login UWSUser_'{0}' with password='{1}';
Create user UWSUser_'{0}' for login UWSUser_'{0}';
Grant Execute to UWSUser_'{0}';
Use ReportSvrUWS_'{0}'
Create user UWSUser_'{0}' for login UWSUser_'{0}';
Grant Execute to UWSUser_'{0}';
Invoke-Sqlcmd -Query $sqlQuery -ServerInstance '{2}'";
break;
C# Code for remote execution(you can organize your way)
string script = PowershellDictionary.GetPowershellCommand("ADDSQLSERVERUSER");
script = String.Format(script, this.CorporateName, password, this.SQLServerName)
PowerShellExecution.RunScriptRemote(_credentials.Server, _credentials.Username, _credentials.Password, new List<string> { script });
You could use the best SQL Server module around: DBATOOLS. You would also benefit from running a query to multiple sql instances.
Install-Module dbatools -Scope CurrentUser
$sql = 'SQL1','SQL1\INSTANCE1','SQL2'
$query = "SELECT 'This query would run on all SQL instances'"
Invoke-DbaQuery -SqlInstance $sqlinstances -Query $query -AppendServerInstance
I have been trying to create a ConnnectionString that will allow me to connect to my local database using PowerShell. Below is my code:
$conn = New-Object System.Data.SqlClient.SqlConnection
$conn.ConnectionString = "Server=localhost;Database=test;Uid=<username here>;Pwd=<password here>;"
$conn.Open()
$sql = "SELECT EMP_STATUS FROM test_table"
$cmd = New-Object System.Data.SqlClient.SqlCommand($sql,$conn)
$rdr = $cmd.ExecuteReader()
while($rdr.Read())
{
$test = $rdr["EMP_STATUS"].ToString()
}
Write-Output $test
However, I have NO CLUE what I am doing wrong and have been pulling my hair out for quite some time. Can anyone help me figure out what I am doing wrong in the ConnectionString?
Thanks everyone!!
I realized that my first problem was that I have MySQL database, not SQL database. As a result, I will have to connect using a different method. This is exactly where I need your help!! So far I have modified my code as follows:
[void][System.Reflection.Assembly]::LoadWithPartialName("MySql.Data")
$conn = New-Object MySql.Data.MySqlClient.MySqlConnection
$connString = "server=localhost;port=3306;uid=<username here>;pwd=<password here> ;database=test;"
$conn.ConnectionString = $connString
$conn.Open()
$sql = "SELECT EMP_STATUS FROM test_table"
$cmd = New-Object MySql.Data.MySqlClient.MySqlCommand($sql,$conn)
$rdr = $cmd.ExecuteReader()
$test = #()
while($rdr.Read())
{
$test += ($rdr["EMP_STATUS"].ToString())
}
Write-Output $test
However, here are a few more questions:
1) How do you use the MySQL .NET connection tool to connect to a local MySQL database?
2) Where should this PowerShell script be saved?
3) Are there any additional changes I should make?
Thanks so much
try this:
$conn.ConnectionString = "Server=localhost;Database=test;User ID=<username here>;Password=<password here>;"
then $test give you only the last value found in the select!
To have $test containing all value from select change your code like this:
$conn = New-Object System.Data.SqlClient.SqlConnection
$conn.ConnectionString = "Server=localhost;Database=test;User ID=<username here>;Password=<password here>;"
$conn.Open()
$sql = "SELECT EMP_STATUS FROM test_table"
$cmd = New-Object System.Data.SqlClient.SqlCommand($sql,$conn)
$rdr = $cmd.ExecuteReader()
$test = #()
while($rdr.Read())
{
$test += ($rdr["EMP_STATUS"].ToString())
}
Write-Output $test