I know how to read value from database using connectionstring, i.e.
Establish database connection to read
$conn = New-Object System.Data.SqlClient.SqlConnection
$conn.ConnectionString = "Server=10.10.10.10;Initial Catalog=database_name;User Id=$username;Password=$password;"
$SQL = "..."
$conn.Open()
# Create and execute the SQL Query
$cmd = New-Object System.Data.SqlClient.SqlCommand($sql,$conn)
$count=0
do{
try{
$rdr = $cmd.ExecuteReader()
while ($rdr.read()){
$sql_output += ,#($rdr.GetValue(0), $rdr.GetValue(1))
$count=$count + 1
}
$transactionComplete = $true
}
catch{
$transactionComplete = $false
}
}until ($transactionComplete)
# Close the database connection
$conn.Close()
How can I accomplish the same thing with ODBC, i.e I have DSN (data source name) set up on the server?
According to https://www.connectionstrings.com/odbc-dsn/ you would use something like...
DSN=myDsn;Uid=myUsername;Pwd=;
Can probably just go with DSN=... if creds not required.
This works if your ODBC connection is under User DSN but not under System DSN. I cannot find a way to make it check for System DSN connections.
$conn = new-object System.Data.Odbc.OdbcConnection
$conn.connectionstring = "DSN=DSNNAME"
$conn.open()
$cmd = New-object System.Data.Odbc.OdbcCommand($sqlCommand,$conn)
$dataset = New-Object System.Data.DataSet
(New-Object System.Data.Odbc.OdbcDataAdapter($cmd)).Fill($dataSet) | Out- Null
$conn.Close()
You may want to put this in front of the code...
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.
if ($env:Processor_Architecture -ne "x86")
{ write-warning 'Launching x86 PowerShell'
&"$env:windir\syswow64\windowspowershell\v1.0\powershell.exe" -noninteractive -noprofile -file $myinvocation.Mycommand.path -executionpolicy bypass
exit
}
Always running in 32bit PowerShell at this point.
$env:Processor_Architecture
Related
I'm trying to take some data through InterSystems ODBC driver with Powershell, but there is an error from the query execution (01004 "String data, right-truncated"). I want to ignore that (or handle this error in PS) and keep the script moving on. Here is the part of my code:
$c = new-object system.data.odbc.odbcconnection
$c.connectionstring = "..."
$c.open()
$cmd = New-object System.Data.Odbc.OdbcCommand( $sql , $c )
$dst = New-Object System.Data.DataSet
$oda = New-Object System.Data.Odbc.OdbcDataAdapter( $cmd )
$oda.Fill( $dst )
This works, i.e., doesn't crash and take the data, when I'm running the script with -NoExit parameter, i.e.:
Powershell -NoExit Y:\test.ps1
Otherways, the Powershell crashes, and the console closes. I need to run this script from another script and eventually receive the result. In the end, I want to close the console window (now I invoke it by exit).
I tried the try-catch block, throws, Invoke-Expression in a few ways, functions with return, etc., as far. I searched for a solution to handle such a type of error, but no result.
I have found the solution (or maybe the workaround). It is better to use ADODB objects instead of System.Data.Odbc. The most straightforward code looks as follows:
$connection = New-Object -ComObject ADODB.Connection
$command = New-Object -ComObject ADODB.Command
$recordset = New-Object -ComObject ADODB.Recordset
$connection.CursorLocation = 3
$connection.ConnectionString = $c_s
$connection.Open()
$command.ActiveConnection = $connection
$command.CommandText = $sql
$command.CommandType = 1
$recordset.ActiveConnection = $connection
$recordset.Open( $command )
Trying to build a PowerShell script to connect to Analysis Services Tabular Model and pull the output of DMV queries(eg : SELECT * FROM $System.DBSchema_Tables)
Tried Below, but its fails, it seems there is something wrong with connection string or the way I am trying to connect:
$connectionString = "server=TabularServerName;database='ModelName';trusted_connection=true;";
$CubeQuery = "SELECT * FROM $System.DBSchema_Tables";
#SQL Connection - connection to SQL server
$sqlConnection = new-object System.Data.SqlClient.SqlConnection;
$sqlConnection.ConnectionString = $connectionString;
#SQL Command - set up the SQL call
$sqlCommand = New-Object System.Data.SqlClient.SqlCommand;
$sqlCommand.Connection = $sqlConnection;
$sqlCommand.CommandText = $CubeQuery;
#SQL Adapter - get the results using the SQL Command
$sqlAdapter = new-object System.Data.SqlClient.SqlDataAdapter
$sqlAdapter.SelectCommand = $sqlCommand
$dataSet = new-object System.Data.Dataset
$recordCount = $sqlAdapter.Fill($dataSet)
What are you not just using the SQLPS module or DBA Tools module?
There are of course other modules you can leverage:
Find-Module -Name '*sql*' | Format-Table -AutoSize
Find-Package -Name '*sql*' | Format-Table -AutoSize
Here is the stuff I've passed on to others messing with SQL.
Install the SQL Server PowerShell module
https://learn.microsoft.com/en-us/sql/powershell/download-sql-server-ps-module?view=sql-server-ver15
https://learn.microsoft.com/en-us/powershell/module/sqlps/?view=sqlserver-ps
https://learn.microsoft.com/en-us/sql/powershell/sql-server-powershell?view=sql-server-ver15
Then see:
Connecting PowerShell to SQL Server
As an overview the following is the list of options I will go over in
this article:
SQL Server PowerShell (SQLPS)
SQL Server Management Objects (SMO)
.NET (System.Data.SqlClient)
SQLPS
SQL Server PowerShell SQLPS is a utility that was first released
with SQL Server 2008, you may see this referenced in various ways. It
exists as a (1) utility and (2) as a PS module. The utility and module
are installed with the SQL Server Management tools from SQL Server
2008 and up. There are a few ways of connecting to SQL Server using
this utility, and each one has strengths and weaknesses.
SQLPS.exe
This is a utility that you should be able to open by typing
it in the run prompt (Start > Run). A second option, right-click a
node under Object Explorer, within SQL Server Management Studio
(SSMS), and select “Start PowerShell”. The SQLPS utility’s main access
point is using the provider “SQLSERVER:\” to browse SQL Server like a
file directory. With that, based on the node you open SQLPS from will
place you within that path of the provider. Under each “folder” you
are in for the provider offers properties to read or set, and some
methods to use for administration.
Get-ChildItem SQLSERVER:\SQL\LOCALHOST\SQL12\Databases | foreach { $_.RecoveryModel = "SIMPLE"; $_.Alter() }
SQLPS Module
Importing the SQLPS module into a PS session provides the
same access using the utility does but allows you to operate in the
PS version of the OS you operate under. In SQL Server 2008 and 2008 R2
you will load the SQLPS as a snap-in (Add-PSSnapin), then with SQL
Server 2012 and up it is imported (Import-Module).
# Loading SMO
Add-Type -AssemblyName "Microsoft.SqlServer.Smo,Version=11.0.0.0,Culture=neutral,PublicKeyToken=89845dcd8080cc91"
# Connecting with SMO
$srv = New-Object Microsoft.SqlServer.Management.Smo.Server “localhost\sql12”
$srv.Databases | select name
# .NET Framework
# Create a connection
$sqlConn = New-Object System.Data.SqlClient.SqlConnection
$sqlConn.ConnectionString = “Server=localhost\sql12;Integrated Security=true;Initial Catalog=master”
$sqlConn.Open()
# Create your command (the T-SQL that will be executed)
$sqlcmd = $sqlConn.CreateCommand()
<# or #>
$sqlcmd = New-Object System.Data.SqlClient.SqlCommand
$sqlcmd.Connection = $sqlConn
$query = “SELECT name, database_id FROM sys.databases”
$sqlcmd.CommandText = $query
# Create your data adapter (if you want to retrieve data)
$adp = New-Object System.Data.SqlClient.SqlDataAdapter $sqlcmd
# Create your dataset (the adapter fills this object)
$data = New-Object System.Data.DataSet
$adp.Fill($data) | Out-Null
# Retrieving Your Data
$data.Tables
<# or #>
$data.Tables[0]
Lastly:
USE POWERSHELL TO GET ALL THE MEASURES FROM A 2016 TABULAR CUBE
So, here’s the PowerShell script that will get the measures from a
cube (change the first three variables to fit your environment):
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.AnalysisServices.Tabular");
$tab = "YourSSASserver";
$dbId = "ID_or_DB";
$saveas = "C:\YourFolder\{0}.dax" -f $tab.Replace('\', '_');
$as = New-Object Microsoft.AnalysisServices.Tabular.Server;
$as.Connect($tab);
$db = $as.Databases[$dbId];
# in case you want to search by the name of the cube/db:
# $as.Databases.GetByName("DB Name");
$out = "";
foreach($t in $db.Model.Tables) {
foreach($M in $t.Measures) {
$out += "// Measure defined in table [" + $t.Name + "] //" + "`n";
$out += $M.Name + ":=" + $M.Expression + "`n";
}
}
$as.Disconnect();
$out = $out.Replace("`t"," "); # I prefer spaces over tabs :-)
$out.TrimEnd() | Out-File $saveas;
Below is what worked for me
$connectionString = $connectionString = “Provider=MSOLAP;Data Source=TabularServerName;”
$CubeQuery = 'SELECT * FROM $System.DBSchema_Tables';
$connection = New-Object -TypeName System.Data.OleDb.OleDbConnection
$connection.ConnectionString = $connectionString
$sqlCommand = $connection.CreateCommand()
$sqlCommand.CommandText = $CubeQuery;
#SQL Adapter - get the results using the SQL Command
$sqlAdapter = new-object System.Data.SqlClient.SqlDataAdapter
$sqlAdapter.SelectCommand = $sqlCommand
$dataSet = new-object System.Data.Dataset
$recordCount = $sqlAdapter.Fill($dataSet)```
I have tried every recommendation from the link below, but nothing works.
How do you do a ‘Pause’ with PowerShell 2.0?
Here is my code:
Read-Host -Prompt "Press Enter to continue"
Invoke-Sqlcmd -Query "Select * from TBL_AGG_BOC" -ServerInstance "server_name\SQL2008" -Database "db_name" > "C:\Users\TBL_AGG_BOC.txt"
Read-Host -Prompt "Press Enter to continue"
The script keeps failing, and it shuts down so fast that I can't see what is actually happening. How can I force this to stay open for a few seconds so I can see what is happening here?
The file is saved and named 'test_export.ps1', and I right-click the file and then click 'Run with PowerShell' to fire it off. I don't have administrator rights on this machine. I hope that's not a problem.
Finally I got this working. It was a combination of a few things.
Open PowerShell as Administrator and run Set-ExecutionPolicy -Scope CurrentUser
Provide RemoteSigned and press Enter
Run Set-ExecutionPolicy -Scope CurrentUser
Provide Unrestricted and press Enter
This link helped a lot!
PowerShell says "execution of scripts is disabled on this system."
Then, run this:
$server = "SERVERNAME\INSTANCE"
$database = "DATABASE_NAME"
$tablequery = "SELECT name from sys.tables"
# Declare connection variables
$connectionTemplate = "Data Source={0};Integrated Security=SSPI;Initial Catalog={1};"
$connectionString = [string]::Format($connectionTemplate, $server, $database)
$connection = New-Object System.Data.SqlClient.SqlConnection
$connection.ConnectionString = $connectionString
$command = New-Object System.Data.SqlClient.SqlCommand
$command.CommandText = $tablequery
$command.Connection = $connection
# Load up the tables in a dataset
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $command
$DataSet = New-Object System.Data.DataSet
$SqlAdapter.Fill($DataSet)
$connection.Close()
# Loop through all tables and export a CSV of the table data
foreach ($Row in $DataSet.Tables[0].Rows)
{
$queryData = "SELECT * FROM [$($Row[0])]"
# Specify the output location of your dump file
$extractFile = "C:\mssql\export\$($Row[0]).csv"
$command.CommandText = $queryData
$command.Connection = $connection
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $command
$DataSet = New-Object System.Data.DataSet
$SqlAdapter.Fill($DataSet)
$connection.Close()
$DataSet.Tables[0] | Export-Csv $extractFile -NoTypeInformation
}
It turned out to be this: $server = "SERVERNAME". Not this: $server = "SERVERNAME\INSTANCE"
After I incorporated these changes, everything worked fine.
I need to make SQL azure database as readonly using PowerShell script.
How can we do it?
I have created following PS script for making databae readonly for some time. This could be helpful to anyone who are looking for this type of solution.
Add-AzureAccount
$subscription = "subscriptioname";
$serverName = "servername";
$database = "dbname";
$userid = "user#servername";
$password = "password";
$sleeptimeinsecond = 120;
Select-AzureSubscription $subscription
# Create DB connection
$connectionString = "Server=tcp:$serverName.database.windows.net;
Database=master;User ID=$userid;
Password=$password;Trusted_Connection=False;MultipleActiveResultSets=True;Encrypt=True;"
$connection = New-Object System.Data.SqlClient.SqlConnection
$connection.ConnectionString = $connectionString
$connection.Open()
echo '**connection opened'
# Run readonly command on database
$command = New-Object System.Data.SQLClient.SQLCommand
$command.Connection = $connection
$command.CommandText = "ALTER DATABASE $database SET READ_ONLY"
$reader = $Command.ExecuteReader()
echo '**command executed'
echo "**Database is now in readonly state"
$reader.Close()
$connection.Close()
echo '**reader & connection object closed'
#sleep for some time till process is going on.
echo "**Sleeping for $sleeptimeinsecond seconds..."
Start-Sleep $sleeptimeinsecond
echo '**Awake from sleep'
#reopen connection
$connection.Open()
# Run read_write command on database
$command = New-Object System.Data.SQLClient.SQLCommand
$command.Connection = $connection
$command.CommandText = "ALTER DATABASE $database SET READ_WRITE"
$reader = $Command.ExecuteReader()
echo '**command executed'
echo "**Database is now in read_write state"
$reader.Close()
$connection.Close()
echo '**reader & connection object closed'
echo '**Script execution done'
Use TSQL command alter database like so,
ALTER DATABASE [Foo] SET READ_ONLY WITH NO_WAIT
You can execute the statement via quite few a ways: sqlcmd, Sql Server's Powershell provider and .Net's System.Data.SqlClient classes.
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