How can I invoke sp_prepexecrpc in SQL Server? - sql-server

I'm currently trying to invoke in SQL Server through ODBC. I tried executing queries like:
Declare #Out int;
EXEC #Out output,
N'#myNumber int',
N'EXEC OdbcOneParameterProcedure #myNumber',
#myNumber = 0;
EXEC #Out;
and
DECLARE #Out int;
EXEC #Out OUTPUT,
N'OdbcOneParameterProcedure',
#myNumber = 0;
SELECT #Out
But all I see is it was invoked in SQL Server as SQL Batch in packet trace in Wireshark. What else should I try?

I figured it out, one way of solving this is executing your StoredProcedure through PHP connector to ODBC using PDO
$odbcDataSource = 'dataSource';
$user = 'userName';
$password = 'userPassword';
$call = "{CALL OdbcOneParameterProcedure( ? )}";
$connection = new PDO($odbcDataSource, $user, $password);
if (!$connection) {
echo 'Connection failed' . odbc_errormsg();
} else {
echo 'Connected';
$param = 0;
$statement = $connection->prepare($call);
$statement->bindParam(1, $param, PDO::PARAM_INT);
$statement->execute();
// dump result to quickly verify correctness of query
$result = $statement->fetchAll();
var_dump($result);
}
$connection = null;

Related

Using stored procedures with cakephp 3.x

I am trying to use a SQL Server stored procedure with cakephp 3.x, but I get a database error.
This is my controller:
use Cake\Datasource\ConnectionManager;
if($this->request->is('post')){
$data = $this->request->getData();
$param1 = $data['playId'];
$param2 = $data['cardboard'];
if(is_numeric($param1) && is_numeric($param2)){
$param1 = $data['playId'];
$param2 = $data['cardboard'];
$conn = ConnectionManager::get('ssql');
$requested = $conn->query(
'call searchPrem(?, ?)',
[$param1, $param2]
)->fetchAll('assoc');
//$exec = debug($requested);
}
echo json_encode( $requested );
}
I get this SQL error:
Error: SQLSTATE[42000]: [Microsoft][ODBC Driver 13 for SQL Server][SQL Server]Incorrect syntax near '#P1'.
How can I execute a stored procedure and retrieve the result data?
I found the solution:
$conn = ConnectionManager::get('ssql');
$sql = $conn->execute("yourfunction #id = $playId, #type = $type")->fetchAll('assoc');
In Cake 2.x I used solution like below:
if ($connection = $this->getDataSource()->connection) {
$statement = oci_parse($connection, "DECLARE x number; BEGIN :x := searchPrem(" . $var1 . ", " . $var2 . "); END;");
oci_bind_by_name($statement, ':x', $result, 10);
if (oci_execute($statement)) {
// Success
}
}
This example works with Oracle dialect. You should modify to Cake 3.x and Your database dialect.

Output XML directly to file from SQL server

Output the results (XML) of a stored procedure to a file.
I have a stored procedure in SQL server that creates an XML file. It currently displays the resulting XML and I have to manually save as a file.
I have tried to call the procedure from Powershell, as in this question, this works for small files but not for large (>1gb files) as Powershell tries to store the entire thing as a variable and it quickly runs out of memory.
I'm opening this as a new question as I think there should be a way of doing this within SQL server (or a better way of doing it with Powershell).
You shouldn't use a stored procedure here. Just use better PowerShell. You can stream large types to and from SQL Server with SqlClient. So you just need to drop down and use ADO.NET instead of using the invoke-sqlcmd convenience method.
EG:
$conString = "server=localhost;database=tempdb;integrated security=true"
$sql = #"
select top (1000*1000) *
from sys.messages m
cross join sys.objects o
for xml auto
"#
$fn = "c:\temp\out.xml"
$con = new-object System.Data.SqlClient.SqlConnection
$con.connectionstring = $conString
$con.Open()
$cmd = $con.createcommand()
$cmd.CommandText = $sql
$cmd.CommandTimeout = 0
$rdr = $cmd.ExecuteXmlReader()
$w = new-object System.Xml.XmlTextWriter($fn,[System.Text.Encoding]::UTF8)
$w.WriteNode($rdr,$true)
$w.Close()
$rdr.Close()
write-host "Process Memory: $( [System.GC]::GetTotalMemory($false) )"
write-host "File Size: $( (ls $fn)[0].Length )"
outputs
Process Memory: 34738200
File Size: 468194885
Other solution if you can you have to build your XML file in Temporary Table line by line and then output and read the result line by line from Powershell or other code :
SQL Example :
/*
**
** Stored procedure
**
*/
/*** Effacement: ********************************************************
IF EXISTS ( SELECT name FROM sysobjects
WHERE type = 'P' AND name = 'procTEST' )
DROP PROCEDURE procTEST
*** Effacement: ********************************************************/
CREATE PROCEDURE procTEST
AS
CREATE TABLE #TEMP (vInfo VARCHAR(MAX), nLine int)
INSERT INTO #TEMP
SELECT 'Line 1',1
UNION ALL
SELECT 'Line 2',2
UNION ALL
SELECT 'Line 3',3
SELECT vInfo FROM #TEMP ORDER BY nLine ASC
SET NOCOUNT OFF
/*** TESTS ****************************************************************************************************************************************
sp_helptext procTEST
-- DROP PROCEDURE procTEST
EXEC procTEST
*** TESTS ****************************************************************************************************************************************/
Powershell Script :
$readconn = New-Object System.Data.OleDb.OleDbConnection
$writeconn = New-Object System.Data.OleDb.OleDbConnection
[string]$connstr="Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=TEST;Data Source=.\XXXXX;Workstation ID=OMEGA2"
$readconn.connectionstring = $connstr
$readconn.open()
$readcmd = New-Object system.Data.OleDb.OleDbCommand
$readcmd.connection=$readconn
$readcmd.commandtext='EXEC procTEST'
$reader = $readcmd.executereader()
# generate header
$hash=#{}
for ($i=0;$i -lt $reader.FieldCount;$i++){
$hash+=#{$reader.getname($i)=''}
}
$dbrecords=while($reader.read()) {
for ($i=0;$i -lt $reader.FieldCount;$i++){
$hash[$reader.getname($i)] = $reader.GetValue($i)
}
New-Object PSObject -Property $hash
}
$reader.close()
$readconn.close()
$dbrecords

Return Stored Procedure value from invoke-sqlcmd

I have a stored procedure that returns a value, 0 or 1. This is required in powershell to determine the next steps the script or user should take. The problem is, I can't find any documentation on how to access that value.
Here's the powershell invoke-sqlcmd command:
invoke-sqlcmd -ServerInstance $Server -query (storedProcedureQuery $firstName $lastName "*" "*" "*") -ErrorVariable var | Format-Table;
Heres the function storedProcedureQuery:
function storedProcedureQuery($firstName, $lastName, $phoneExtension, $updateEmployeeRecord, $commitUpdate)
{
"
exec [dbo].[usp_PhoneRemoveDuplicateExtensions_upd]
#firstName = '$firstName',
#lastName = '$lastName',
#phoneExtension = '$phoneExtension',
#updateEmployeeRecord = '$updateEmployeeRecord',
#commitUpdate = '$commitUpdate'
"
}
Any help is much appreciated.

How to get the value of a stored procedure OUTPUT variable

I have a simple SQL Server stored procedure that accepts an input parameter and sets an output parameter. The essence of the stored procedure is as follows:
CREATE PROC SomeDB.dbo.SomeProc
#input varchar(255),
#output int OUTPUT
AS
IF #input = 'a'
BEGIN
SET #output = 0;
END
ELSE
BEGIN
SET #output = 1;
END
;
GO
I want to get the value of the #output variable in PowerShell. If I were to do this in SSMS, I would do something like:
DECLARE #out int;
EXEC SomeDB.dbo.SomeProc 'a', #out OUTPUT;
PRINT #out;
But, I don't think it's that straightforward in PowerShell.
Here is my script so far in PowerShell (which I know is incomplete):
$ErrorActionPreference = "Stop"
$server = "some_IP_address"
$db = "SomeDB"
$input = "'a'"
$query = "EXEC dbo.SomeProc $input;"
try {
Invoke-Sqlcmd -ServerInstance $server -Database $db -Query $query -QueryTimeout 60000
} catch {
Write-Host "stored proc error"
}
How do I get the value of the #output variable in PowerShell?
Something like this might work:
$cn = New-Object Data.SqlClient.SqlConnection
$cn.ConnectionString = '...'
$cmd = New-Object Data.SqlClient.SqlCommand
$cmd.CommandText = 'dbo.SomeProc'
$cmd.Connection = $cn
$cmd.CommandType = [Data.CommandType]::StoredProcedure
$p = $cmd.Parameters.Add('#output', '')
$p.Direction = [Data.ParameterDirection]::Output
$p.Size = 42
$cn.Open()
$cmd.ExecuteNonQuery()
$p.SqlValue.Value
[source]

Automatically save my SQL Server query results

I have a query that compiles some data based on a supplied Id number. I want to run it once for a long list of Ids that I have, and save the result set to a CSV. I know I can do it manually, but I'm looking for an automated way.
I already tried running my query without specifying the Id in the where clause. This ended up giving my a file a little smaller than 1Gb which is too big for needs.
Here is the basic idea of what I am trying to accomplish:
Declare #num int
set #num = 0
While #num < 100
Begin
--I'm trying to figure out a way to store the
--result set generateed by this procedure is saved to 'DataExtract' + #num + '.csv'
Exec LongRunningProcedure #num
Set #num = #num + 1
End
If you have sufficient permissions you could use powershell to accomplish this. I can't really be sure that this will run exactly right for you because I don't know what your output looks like, but hopefully this will get you where you're going.
$SQLAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SQLCommand = New-Object system.Data.SqlClient.SqlCommand
$DataSet = New-Object System.Data.DataSet
[STRING]$SQLServer = 'YourServer';
[STRING]$SQLDatabase = 'YourDatabase';
[STRING]$SQLConnectString = "Data Source=$SQLServer; Initial Catalog=$SQLDatabase; Integrated Security=True";
$SQLConnection = New-Object System.Data.SqlClient.SqlConnection($SQLConnectString)
$extractFile = "C:\test.csv"
for($x = 0; $x -le 100; $x++) {
$file = "$($extractFile.Split('.')[0])$($x).csv"
$SQLQuery = "Exec LongRunningProcedure #num = $x"
$SQLConnection.Open()
$SQLCommand.CommandText = $SQLQuery
$SQLCommand.Connection = $SQLConnection
$SQLAdapter.SelectCommand = $SQLCommand
$SqlAdapter.Fill($DataSet) | Out-Null
$SQLConnection.Close()
$DataSet.Tables[0] | Export-Csv $file
}

Resources