How do you retrieve the return value of a DB2 SQL sproc using Perl DBI? - sql

I need to retrieve the value returned by a DB2 sproc that I have written. The sproc returns the number of rows in a table and is used by the calling process to decide whether or not to update other data.
I have looked at several similar questions on SO but they refer to the use of out parameters instead of using the sproc's return value, for example:
Perl Dbi and stored procedures
I am using a standard DBI connection to the database with both RaiseError and PrintError enabled.
$sql_stmt = "call MY_TABLE_SPACE.MY_SPROC('2011-10-31')";
$sth = $dbh->prepare($sql_stmt)
or die "Unable to prepare SQL '$sql_stmt': $rps_met_dbh->errstr";
$rsp = 0;
$rsp = $sth->execute();
unless($rsp) {
print(STDERR "Unable to execute sproc: $rps_met_dbh->errstr\n");
}
print(STDERR "$?\n");
I have tried looking at $h->err for both the statement handle and the db handle.
I would really prefer communicating the number of rows via a return code rather than using SQLSTATE mechanism if I can.
Edit:
I have finished up using a dedicated out parameter to communicate the number of rows updated as follows:
$sql_stmt = "call MY_TABLE_SPACE.MY_SPROC('2011-10-31')";
$sth = $dbh->prepare($sql_stmt)
or die "Unable to prepare SQL '$sql_stmt': $rps_met_dbh->errstr";
$sth = $dbh->bind_param_inout(1, $rows_updated, 128)
or die "Unable to prepare SQL '$sql_stmt': $rps_met_dbh->errstr";
$rows_updated = 0;
$rsp = 0;
$rsp = $sth->execute();
unless($rsp) {
print(STDERR "Unable to execute sproc: $rps_met_dbh->errstr\n");
}
print(STDERR "$rows_updated\n");
Edit 2:
And now thinking about this further I have realised that I should apply the PragProg principle of "Tell. Don't Ask." That is, I shouldn't call the sproc. then have it give me back a number before I decide whether or not to call the anopther sproc, i.e. "Ask".
I should just call the first sproc. and have it decide whether it should call the other sproc or not, i.e. "Tell" and let it decide.

What is wrong with using an output parameter in your procedure. I've not got a working DB2 lying around right now or I'd provide an example but when I was using it I'm sure you can define output parameters in procedures and bind them with bind_param_inout. I cannot remember if a DB2 procedure can return a value (like a function) but if it can them using "? = call MY_TABLE_SPACE.MY_SPROC('2011-10-31')" would allow you to bind the output return value. If this doesn't work you could use a DB2 function which definitely can return a value. However, at the end of the day the way you get data out of a procedure/function is to bind output parameters - that is just the way it is.
I've no idea what you mean by "using SQLSTATE". I've also no idea what you mean by looking at $h->err as that is only set if the procedure fails or you cannot call the procedure (SQL error etc).

Related

Catching OUT parameter value of a bigquery Procedure from composer

I am calling a bigquery procedure using BigQueryInsertJob operator using "declare out_var String; call bq_sp("input params", out_var)". This is getting called properly and executing the stored procedure properly also. But what I need to do along with that, is to print the value of out_var to the composer log, to catch the value of out_var, so that I can do some more things depending on the value of that variable. Could you please help me, how can I catch the value of the OUT parameter value from the cloud composer. Thank you.
I have a stored procedure with input and output parameters. and calling that from composer.
This is working absolutely fine.
I am expecting to fetch the OUT parameter value in the cloud composer job

Manually sanitize SQL parameters

I would like to run a script like:
CREATE LOGIN [me] WITH PASSWORD = #0
and run it like:
var createUserCommand = conn.CreateCommand();
createUserCommand.CommandText = script;
createUserCommand.Parameters.AddWithValue("#0", passwordDecrypted);
However, this throws:
A first chance exception of type 'System.Data.SqlClient.SqlException' occurred in System.Data.dll
Additional information: Incorrect syntax near '#0'.
From what I read online (nowhere official, just from SO answers/comments) it is not possible to use SQL parameters with DDL statements. Link to official docs for this are welcome!
OK. I do need this parametrized. As I see it, there are 2 options:
I manually sanitize (.Replace("'", "''") => how can I do this best?
I call into .NET to sanitize for me. However I assume this is not sanitized within ADO.NET, but just past to SQL Server, and sanitized there...
What would be the best approach?
All you need to escape is the single ' to 2 x '
commandText = string.Format("CREATE LOGIN [me] WITH PASSWORD = '{0}'", pass.Replace("'", "''"));
An alternative would be to create a stored procedure with a password parameter and use it to build a CREATE LOGIN string which you then sp_executeSQL.

SQL Parameter not found

The error:
Procedure or Function '' expects parameter '#Param1' which was not supplied.
An excerpt of the stored procedure:
I have a stored procedure on a SQL Server 2012. The procedure looks something like this...
SELECT *
FROM Orders
WHERE Orders.CustomerID = #param1 AND
Orders.CustomerJoinDate = #param2
I call it from my code {Using Visual Studio 2008} like so...
The calling method in Visual Studios:
First I create an array of parameters I'm going to pass...
Dim Param() As SqlClient.SqlParameter =
New SqlClient.SqlParameter()
{
New SqlClient.SqlParameter("#Param1", Me.cmbFilter1.Text),
New SqlClient.SqlParameter("#Param2", Me.cmbFilter2.Text)
}
Then I loop through the parameters and add them to a command to be executed by a datareader.
The mSQLCmd is set to call the stored procedure described above...
mSQLCmd.Parameters.Clear()
mSQLCmd.CommandText = SQLCmd
For Each sParam As SqlClient.SqlParameter In Param
mSQLCmd.Parameters.AddWithValue(sParam.ParameterName, sParam.Value)
Next
Error occurs when:
I try to run mSQL.ExecuteReader() Can someone point me in the right direction on this? I've verified that each parameter is included in the Param() with the correct values.
I've also tested the stored procedure on SQL Server and verified when the two necessary parameters are provided it works correctly. Something is wrong on the vb side.
If you're calling a stored procedure, you need to set the CommandType of the SqlCommand accordingly!
mSQLCmd.CommandText = SQLCmd
// add this line!
mSQLCmd.CommandType = CommandType.StoredProcedure
Otherwise the name of the stored procedure you're trying to call is interpreted as a SQL command you're trying to execute.

How to call Sybase stored procedure with named params using JDBC

I have a stored procedure in Sybase which I can invoke from my favourite SQL client like this:
exec getFooBar #Foo='FOO', #Bar='BAR'
It returns a table of results, so its like a query. It has actually many parameters, but I only want to call it with Foo and sometimes with Foo and Bar specified.
Sybase is ASE 15.0, I am using jConnect 6.0.5.
I can invoke this using a PreparedCall if I specify only the first parameter:
CallableStatement cs = conn.prepareCall("{call getFooBar(?) }");
cs.setString(1,"FOO");
However I can't use the #Foo notation to pass my params:
conn.prepareCall("{call getFooBar #Foo='FOO' }");
conn.prepareCall("call getFooBar #Foo='FOO' ");
conn.prepareCall("{call getFooBar #Foo=? }"); // + setString(1,'FOO')
In all these cases I get exception from the DB telling me that the Foo parameter is expected:
com.sybase.jdbc3.jdbc.SybSQLException: Procedure getFooBar expects
parameter #Foo, which was not supplied
Ideally I'd like to do this with Spring JdbcTemplate or SimpleJdbcCall, but with those I could not even get to the point where I could with plain old JDBC.
So to summarize, I'd like to avoid ending up with:
{ call getFooBar(?,null,null,null,null,null,?,null,null) }
Is that possible using JDBC or better Spring?
Not the most efficient solution, but, have you tried using the plain Statement itself with EXEC.
eg.
String mySql = "EXEC getFooBar #Foo='FOO', #Bar='BAR'";
ResultSet rs = conn.getConnection().createStatement().executeQuery(mySql);

Executing the contents of a memo on a TADOQuery

I have a really long list of sql commands on a memo, when I try to execute it I get the following error:
Parameter object is improperly defined. Inconsistent or incomplete information was provided.
The code to execute it:
Query.SQL.Text := Memo1.Lines.Text;
Query.ExecSQL;
I have a vague idea that the error is caused due to the way the query content was added, so, here's how I'm doing it now:
1) Memo1.Lines.LoadFromFile('Patch.sql');
2) Proceed to the query commands
As you can see, the contents of the memo is loaded from a file. Is there any other way to successfully do this?
P.S.: I'm using Microsoft SQL 2008.
Thank you!
It looks like you're not using parameters, so set ParamCheck off
Query.ParamCheck := false;
If there is a colon ":" in a string in the SQL, the TADOQuery thinks it's a parameter