DB2 ERROR [07004] SQL0313N - c#

I am a newbie in DB2 world and am using:
- DB2 Data Provider for .NET (IBM.Data.DB2.dll version 9.7.4.4)
- C# VS2010 with .NET Framework 4.0
I have problem with query that uses parameter.
My code snippet:
DB2Command cmd = new DB2Command();
cmd.CommandText = "SELECT COUNT(*) FROM CUSTOMERS t0 WHERE (t0.\"CITY\" < :p0)";
cmd.Connection = Db2Connection;
DB2Parameter param = cmd.CreateParameter();
param.DB2Type = DB2Type.VarChar;
param.ParameterName = ":p0";
param.Value = "Seattle";
var p = cmd.Parameters.Add(param);
var execResult = cmd.ExecuteScalar();
I get following error on cmd.ExecuteScalar():
The number of variables in the EXECUTE statement, the number of
variables in the OPEN statement, or the number of arguments in an OPEN
statement for a parameterized cursor is not equal to the number of
values required. SQLSTATE=07004
Please help how to fix the problem. Thank you in advance.
Additional information:
1. I just tried to use IBM Data Studio to verify the DB2 command using query editor. It doesn't recognize the prefix "#" for parameter. So I use oracle-liked prefix ":" for it. It works. But my C# code still raises the error [07004] SQL0313N
2. If I don't use any prefix for parameter on my C# code, I get ERROR [42703] [IBM][DB2/NT64] SQL0206N \"P0\" is not valid in this context.

Finally I find out 2 ways to fix the problem.
Using unnamed parameter "?" instead of parameter name ":p0".
DB2Command cmd = new DB2Command();
cmd.CommandText = "SELECT COUNT(*) FROM CUSTOMERS t0 WHERE (t0.\"CITY\" < ?)";
cmd.Connection = Db2Connection;
DB2Parameter param = cmd.CreateParameter();
param.DB2Type = DB2Type.VarChar;
param.ParameterName = "param1";
param.Value = "Seattle";
var p = cmd.Parameters.Add(param);
var execResult = cmd.ExecuteScalar();
Activate HostVarParameters property of class DB2ConnectionStringBuilder and the original code remains unchanged (keeping using named parameters).
My 2 cents,
Mag

Related

Oracle Managed Data Reader Returning DBNull for One Database Table

Issue:
I am using the Oracle managed data access client to connect to an Oracle eBS database. When selecting a value from one table I get a result; when changing the table I get a null value.
Background:
In my SQLDeveloper client I can connect to the database and run the following queries:
SELECT MSIB.SEGMENT1
FROM APPS.MTL_SYSTEM_ITEMS_B MSIB
WHERE MSIB.ORGANIZATION_ID = 255 AND MSIB.SEGMENT1 = '03F.211';
-- 1 ROW RETURNED - VALUE OF 03F.211
SELECT MC.SEGMENT1
FROM APPS.MTL_CATEGORIES_VL MC
WHERE MC.SEGMENT1 = 'A0042I';
-- 1 ROW RETURNED - VALUE OF A0042I
Then, in C#, I'm connecting to the database with exactly the same credentials (so it should not be a database permissions issue).
Running this code I get a message box returning what I would expect: 03F.211
OracleConnection oradbcon = new OracleConnection(strOracleConString);
oradbcon.Open();
strQuery = "SELECT MSIB.SEGMENT1 FROM APPS.MTL_SYSTEM_ITEMS_B MSIB WHERE MSIB.ORGANIZATION_ID = 255 AND MSIB.SEGMENT1 = " + ":ITEM_CODE";
// strQuery = "SELECT MC.SEGMENT1 FROM APPS.MTL_CATEGORIES_VL MC WHERE MC.SEGMENT1 = " + ":ITEM_CODE";
OracleCommand oradbcmd = new OracleCommand(strQuery, oradbcon);
oradbcmd.CommandType = CommandType.Text;
OracleParameter p_item_code = new OracleParameter();
p_item_code.OracleDbType = OracleDbType.Varchar2;
p_item_code.Value = "03F.211";
// p_item_code.Value = "A0042I";
oradbcmd.Parameters.Add(p_item_code);
OracleDataReader oradbdr = oradbcmd.ExecuteReader();
oradbdr.Read();
strProductMinor = oradbdr.GetString(0).ToString();
MessageBox.Show(strProductMinor);
But running the code with those commented lines switched I get an error indicating a database null:
OracleConnection oradbcon = new OracleConnection(strOracleConString);
oradbcon.Open();
// strQuery = "SELECT MSIB.SEGMENT1 FROM APPS.MTL_SYSTEM_ITEMS_B MSIB WHERE MSIB.ORGANIZATION_ID = 255 AND MSIB.SEGMENT1 = " + ":ITEM_CODE";
strQuery = "SELECT MC.SEGMENT1 FROM APPS.MTL_CATEGORIES_VL MC WHERE MC.SEGMENT1 = " + ":ITEM_CODE";
OracleCommand oradbcmd = new OracleCommand(strQuery, oradbcon);
oradbcmd.CommandType = CommandType.Text;
OracleParameter p_item_code = new OracleParameter();
p_item_code.OracleDbType = OracleDbType.Varchar2;
// p_item_code.Value = "03F.211";
p_item_code.Value = "A0042I";
oradbcmd.Parameters.Add(p_item_code);
OracleDataReader oradbdr = oradbcmd.ExecuteReader();
oradbdr.Read();
strProductMinor = oradbdr.GetString(0).ToString();
MessageBox.Show(strProductMinor);
What would cause one query to return results but the other to not?
(Finally - forgive my ignorance of C# if anything above is ugly. Years of Oracle experience - first C# program ever... :) )
The issue is language.
APPS.MTL_CATEGORIES_VL is a view that has another view in it's definition:
MTL_CATEGORIES_TL
The views ending in TL are "translated language" meaning they only return results for the language of your database session.
SQL Developer is declaring a default language when I connect.
.NET client is not.
I either need to figure out how to declare a language or re-write my queries to use base tables that don't have language.
Edit: There was a complaint that this wasn't an actual answer, but an explanation.
Here is the actual code that is the answer:
try // Open Connection
{
oradbcon = new OracleConnection(yourConnectionStringHere);
oradbcon.Open();
OracleGlobalization orainfo = oradbcon.GetSessionInfo();
orainfo.Language = "AMERICAN"; // Explicitly Set Language
oradbcon.SetSessionInfo(orainfo);
}

Getting output parameter from SqlCommand returns null

I have this piece of code:
using (SqlCommand cmd = new SqlCommand())
{
cmd.Connection = connection;
cmd.CommandText = "UPDATE S " +
"SET S.WebId = S.WebId + 1 " +
"OUTPUT DELETED.WebId " +
"FROM jcdSetting S";
SqlParameter parameter = cmd.Parameters.Add("#id", SqlDbType.Int);
parameter.Direction = ParameterDirection.Output;
int i = cmd.ExecuteNonQuery();
webId = Convert.ToInt32(cmd.Parameters["#id"].Value);
}
For some reason, the last line fails, the parameter I'm trying to access is always DbNull. I've tried the query in Management Studio and it returns the value just fine.
I've checked the return value of ExecureNonQuery and that as well returns 1 as expected. I'm totally lost here.
Any help would be appreciated.
Using the output within a update statement, is equivalent to a select, whereas from the code you've posted you're expecting it to come out in an output parameter named #id.
Where does #id come from? you haven't defined it anywhere.
output in the method that you've used it would return a rowset, not a scalar value.

SQL Parameters and Question Marks

I am making the switch from classic ASP to ASP.NET. And I am having some trouble doing some basic stuff that I used to do easily with the old method. Below is a handy ASP function that I used to execute scalar queries with a few lines.
FUNCTION ExecuteScalarParams(SQLQuery, Parameter_Array)
Set cmd1 = Server.CreateObject("ADODB.Command")
cmd1.ActiveConnection = con
cmd1.CommandText = SQLQuery
cmd1.CommandType = 1
FOR ParamCount = 0 TO UBOUND(Parameter_Array)
cmd1.Parameters(ParamCount) = Parameter_Array(ParamCount)
NEXT 'ParamCount
Set rstScalar = cmd1.Execute()
IF NOT rstScalar.EOF THEN
arrScalar = rstScalar.GetRows()
IF UBOUND(arrScalar,2) = 0 THEN
ExecuteScalarParams = arrScalar(0,0)
ELSE
ExecuteScalarParams = NULL
END IF
ELSE
ExecuteScalarParams = NULL
END IF
rstScalar.Close
Set rstScalar = Nothing
Set cmd1 = Nothing
END FUNCTION
I used to pass a SQL query with question marks as place holders for the parameters like this:
SELECT TOP 1 UserName FROM Members WHERE (Created>?) AND (AdminLevel=?);
I would then set up a parameters array and pass it on to the function:
MyArray = ARRAY("1-JAN-2012",1)
The parameters in the array would replace the question marks in the query string in the order they appear.
I am trying to mimic this function in C# but I am stuck in the part where I have to pass the parameters. So far I got to the point where I have to used named place holders such as #Created and #AdminLevel instead of the question marks and then I have to set up parameter objects like this:
SqlParameter param = new SqlParameter();
param.ParameterName = "#AdminLevel";
param.Value = 1;
Is there a way to pass the parameters without having to set the parameter names and simply use question marks and the order in which they appear to specify which parameter goes where?
edit: as pointed out by Dana the MSDN Docs for Parameters shows you need to use named parameters for SqlClient but can use positional parameters for OleDb/ODBC.
You can make adding parameters a lot easier by using the code below; it's the skeleton I use but I'm sure there's a better way of doing it.
You still need to used named parameters, but you can simulate your question marks to an extent by naming them #a, #b, #c.. - positional parameters are fine until you get more than a handful of parameters and you have to constantly count the number of question marks to figure out which parameter value is being applied where, often resulting in mistakes.
using (var con = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString))
{
con.Open();
{
using (var command = con.CreateCommand())
{
command.Connection = conn;
command.CommandText = "SELECT * FROM [dbo].[Table] WHERE [c1] = #a AND [c2] = #b";
command.Parameters.AddWithValue("#a", aVal);
command.Parameters.AddWithValue("#b", bVal);
command.CommandType = CommandType.Text;
using (var reader = command.ExecuteReader())
{
if (reader.HasRows)
{
while (reader.Read())
{
///
}
}
else
{
///
}
}
}
}
}

Parameters cause sql query to time out

I have a long SQL query, it does some inserts, updates, then deletes. Each query uses the same 2 parameters. If I pass them in as SQL parameters from C#, it times out, after 20 mins. I just put the parameters into the command text, and it works. When I use it with the parameters it doesn't even show up in the profiler till it times out. Am I missing something?
SqlCommand comm = new SqlCommand(cmdText, conn);
comm.CommandTimeout = 5 * 60;
SqlParameter p = new SqlParameter("#key1", SqlDbType.Int);
p.Value = key1;
comm.Parameters.Add(p);
p = new SqlParameter("#key2", SqlDbType.Int);
p.Value = 1000000;
comm.Parameters.Add(p);
comm.ExecuteNonQuery();
If you take the parameter code out, and just to a replace on cmdText before executing the query it works. The query itself is a 300 lines or so. Each parameter gets used 51 times.
You may be missing the comm.Prepare() call before ExecuteNonQuery().
The key is in the SQL command, instead of saying "cmdText" post your SQL command.
EDIT: You are also not specifying a parameter direction in the code, it might be important.
Did you set the command type?
var command = new SqlCommand() { CommandType = CommandType.StoredProcedure };

Using npgsql to call a function that takes character as parameter

I am trying to use Npgsql to invoke a function (stored procedure) that takes a CHARACTER as parameter, but it doesn't work. If I declare the same function without parameters, or with an INTEGER parameter, I get the result sets that I want. When I declare the parameter as CHARACTER, it stops working. What is wrong?
Here is the code of my function:
CREATE OR REPLACE FUNCTION testrefcursor1(in xxx character varying(10)) RETURNS SETOF refcursor AS
$$
DECLARE
ref1 refcursor;
ref2 refcursor;
BEGIN
OPEN ref1 FOR
SELECT * FROM accounts;
RETURN NEXT ref1;
OPEN ref2 FOR
SELECT * FROM accounts;
RETURN NEXT ref2;
RETURN;
END;
$$
LANGUAGE plpgsql;
And here is the C# code that I am using:
var connection = new Npgsql.NpgsqlConnection(connectionString.ConnectionString);
connection.Open();
var trans = connection.BeginTransaction();
var command = new Npgsql.NpgsqlCommand("testrefcursor1", connection);
command.CommandType = System.Data.CommandType.StoredProcedure;
var parameter = command.CreateParameter();
parameter.ParameterName = "xxx";
parameter.DbType = System.Data.DbType.String;
parameter.Value = "10";
command.Parameters.Add(parameter);
var da = new Npgsql.NpgsqlDataAdapter(command);
var ds = new System.Data.DataSet();
da.Fill(ds);
trans.Commit();
connection.Close();
I already tried declaring the parameter as CHARACTER, CHARACTER(10), CHARACTER VARYING and CHARACTER VARYING(10)...
EDIT: I don't get any error message, but instead of getting the expected result set, I get an empty result set with a single column that has the same name as the function I am trying to call.
You're passing a Unicode argument to an ASCII parameter.
Change this line:
parameter.DbType = System.Data.DbType.String;
To:
parameter.DbType = System.Data.DbType.AnsiString;
Generally, Postgres's varchar columns are in Unicode, provided that the Unicode option on the database is enabled (see here). My guess is that it's not, and your parameter is unable to convert itself into the correct type to be passed through the function.
Which Npgsql version are you using?
Also, can you specify the parameter type using NpgsqlDbType? Sometimes the mapping isn't exactly and Npgsql can't find the function you are trying to use and can't make it work.
Npgsql tries to find an exact match of function name and parameter types. DbString matches text parameter types. Would you mind to give it a try and change your parameter type to text?
I hope it helps.
Not sure, if this has to do with your problem, but yesterday I stumbled across the fact that PostgreSQL has a "single-byte internal type" char that is different from the type char(1). Maybe there is some confusion about these?
I tried with the below approach (which is similar to yours):
using (NpgsqlConnection connection = new NpgsqlConnection(< connectionString >))
{
DataSet ds = new DataSet();
DataTable dt = new DataTable();
connection.Open();
NpgsqlCommand cmd = new NpgsqlCommand(< name of your SP >, connection);
cmd.CommandType = CommandType.StoredProcedure;
var param = cmd.CreateParameter();
param.ParameterName = < exact parameterName you used in your SP>;
param.DbType = System.Data.DbType.AnsiString;
param.Value = < parameter value >;
cmd.Parameters.Add(param);
NpgsqlDataAdapter adapter = new NpgsqlDataAdapter(cmd);
adapter.Fill(ds);
dt = ds.Tables[0];
}
This is working fine for me and I'm getting proper DataTable.

Categories