I'm calling the code below.
On the line (IDataReader dr = cmd.ExecuteReader()) sql barfs with an Incorrect syntax near 'CompanyUpdate'.
using (SqlCommand cmd = new SqlCommand("CompanyUpdate"))
{
cmd.Parameters.Add("#CompanyID",SqlDbType.Int);
cmd.Parameters.Add("#Description",SqlDbType.VarChar,50);
cmd.Parameters["#CompanyID"].Value = companyid;
cmd.Parameters["#Description"].Value = description;
SqlConnection cn = new SqlConnection("Data Source=[datasource];Initial Catalog=dotNext;User ID=[user];Password=[password];Pooling=True;Application Name=dotNext");
cn.Open();
cmd.Connection = cn;
using (IDataReader dr = cmd.ExecuteReader())
{
if (dr.Read())
{
this.CompanyID = dr.GetInt32(0);
}
}
}
I had a look at sqlprofiler and noticed the following:
exec sp_executesql N'CompanyUpdate',N'#CompanyID int,#Description varchar(50)',#CompanyID=56,#Description='APC'
Its wrapping my command wit a sp_executesql. All my other sql commands are just executed with no issues.
So my question is two fold:
1. Why is it using sp_executesql?
2. What am I doing wrong?
Details: sql2005, c#, vs2005
I notice that you've not set the CommandType to StoredProcedure... I don't know if that's the cause of your problem or not:
cmd.CommandType = CommandType.StoredProcedure;
I've done this so many times myself I can't count.
Tip to trigger your memory when this throws exceptions next time:
Have SQL Query Profiler open while you're running your app. When each command executes, it shows the SQL generated and run on the server side. If the SQL generated begins with sp_executesql followed by your query then it's being run as a regular query - i.e. cmd.CommandType = CommandType.Text, if it starts with exec, chances are it's run as a stored proc. Make sure you're getting the correct SQL generated for the type of query you're trying to run.
Related
I'm trying to call a Stored Procedure in MySql that returns a list of rows and with OUT parameter. Code:
using (MySqlConnection conn = new MySqlConnection("server=***;database=***;uid=***;pwd=***;"))
{
conn.Open();
using var command = conn.CreateCommand();
command.CommandText = "CALL p_detail_get";
command.CommandType = CommandType.StoredProcedure;
command.Parameters.AddWithValue("#FilterJson", JsonConvert.SerializeObject(input));
command.Parameters.Add("#Output", MySqlDbType.Int32);
command.Parameters["#Output"].Direction = ParameterDirection.Output;
command.ExecuteNonQuery();
}
Error:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CALL p_detail_get('{"id":1}', #outParam1);SELECT '' AS '', #outParam1' at line 1
Can you give me an example of the code that can get both - return from procedure and OUT parameter?
when calling statement "SHOW PROCEDURE dbName.SP_Name;" on Teradata Database thorugh the code (.net) i get back empty result set.
but when i run this query on the SQL ASSISTANT with the same credentials, i do receive results...
please note that every other queries on the DB i do get it with no problem.
it came empty only on "SHOW PROCEDURE" command
this is the code:
using (TdConnection cn = new TdConnection(ConnectionString))
{
cn.Open();
TdCommand cmd = cn.CreateCommand();
cmd.CommandTimeout = CommandTimeoutWindow;
cmd.CommandText = query;
using (TdDataAdapter da = new TdDataAdapter(cmd))
{
da.Fill(dt);
}
}
can you suggest an idea..?
thank you
details:
Teradata DB version: 14.00.07.16
.NET Data Provider for Teradata: Teradata.Client.Provider, Version=16.10.0.0
Please give the command type as command type. Text
cmd.CommandText = query;
cmd.CommandType = CommandType.Text;
Also try with an extended connection time out.
When calling a stored procedure using either ExecuteResultSet or ExecuteReader
using (DB2Connection conn = new DB2Connection(connstr))
{
conn.Open();
DB2Command cmd = conn.CreateCommand();
cmd.Transaction = conn.BeginTransaction();
DB2Parameter db2param = new DB2Parameter("#ENTERPRISE_ID_PR091", DB2Type.Char, 15);
db2param.Direction = ParameterDirection.InputOutput;
db2param.Value = enterpriseID.ToCharArray();
cmd.Parameters.Add(db2param);
//... many parameters
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "XXISCHMA.XXIPW09D";
DB2ResultSet dr = cmd.ExecuteResultSet(DB2ResultSetOptions.Scrollable);
}
In Web API the Exceptionis thrown:
SQL0035N The file "C:\Users\documents\visual studio 2013\Projects\App\Web\msg\en_US\db2nmp.xml" cannot be opened
In other Applications an Exception is thrown:
ERROR [22023] [IBM][DB2] SQL0310N SQL statement contains too many
host variables.
I don't think the exception texts are correct...
Is this by design?
In COBOL the SQL code of -310 is returned, which is "DECIMAL HOST VARIABLE OR PARAMETER number CONTAINS NON-DECIMAL DATA".
Turns out the error -310 returned to the COBOL test program was the one to look at.
So we changed the DECIMAL TO NUMBER in the COBOL stored procedure and now we get back parameters instead of an exception.
Still don't know why this was a problem only when the select does not find any records. I only look at the c# side of the world. Oy veh!
Trying to improve my C# to SQL skills... Currently I am using this bit of code to pull data from our application server. I have two different DBA's telling me two other ways to write this, just trying to figure out if this should be improved on or changed. If so, I would really appreciate some kind of examples.
FYI: This code...
db.con(user.Authority)
...Is essentially a 'new sqlconnection' code.
DataTable dtInfo = new DataTable("SomeInfo");
using (SqlConnection con = db.con(user.Authority))
{
string command = "SOME SQL STATEMENT;";
using (SqlCommand cmd = new SqlCommand(command,con))
{
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue("#Param", sqlDbType).Value = Param;
con.Open();
cmd.ExecuteNonQuery();
**********
*** OR ***
**********
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue("#Param", sqlDbType).Value = Param;
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
{
da.Fill(dtInfo );
}
}
}
So, if I'm understanding the provided information, this is my best route?
using (SqlConnection con = db.con(user.Authority))
{
string command = "SELECT [TBL_EMPLOYEE].[ACTIVE_DIRECTORY] FROM [TBL_EMPLOYEE];";
using (SqlCommand cmd = new SqlCommand(command, con))
{
con.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
MessageBox.Show(reader["ACTIVE_DIRECTORY"].ToString());
}
}
}
And one last thing... This should prevent the need for
cmd.Dispose();
etc...
The code would depend on the specific query. If the query retrieves rows of data (as a SELECT does), then you would go the da.Fill() route. If it's a query that just makes a change to the database (such as INSERT, UPDATE, or DELETE), then you would use ExecuteNonQuery().
I would not use the SqlDataAdapter version. The version that uses the SqlCommand object and the SqlDataReader will perform better, and allows more insight into the actual data being returned.
// Assumes the following sql:
// SELECT foo, bar FROM baz
// error checking left out for simplicity
var list = new List<SomeClass>();
using(var reader = cmd.ExecuteReader()) {
while(reader.Read()) {
list.Add(new SomeClass {
// NOTE: you can see the columns that the c# is referencing
// and compare them to the sql statement being executed
Foo = (string)reader["foo"],
Bar = (string)reader["bar"]
});
}
}
Later as your level of experiance increases you will be able to use other features of the SqlCommand and SqlDataReader classes in order to ensure that the code executes as quickly as possible. If you start using the SqlDataAdapter route, you will eventually have to relearn how to do the exact same things you have already been doing because the SqlCommand and SqlDataReader have operations that do not exist elsewhere in .NET.
ExecuteNonQuery returns the number of rows effected.
A DataTable is not an efficient way to retrieve that number.
int rowsRet = cmd.ExecuteNonQuery();
SqlCommand.ExecuteNonQuery Method
I have an oracle package with a procedure that has a in out reference cursor. My understanding is that this is pretty standard.
What I didn't like is the fact that I had to write a ton of code to just see the output. So I asked this question and it turns out I can get what I want by creating a function that wraps the procedure.
Update: Looks like I don't need the function anymore but it may be worth knowing anyway for those curious see the original question and answer updates.
Here's the function
FUNCTION GetQuestionsForPrint (user in varchar2)
RETURN MYPACKAGE.refcur_question
AS
OUTPUT MYPACKAGE.refcur_question;
BEGIN
MYPACKAGE.GETQUESTIONS(p_OUTPUT => OUTPUT,
p_USER=> USER ) ;
RETURN OUTPUT;
END;
and here's what I do to execute it in SQL Developer
var r refcursor;
exec :r := mypackage.getquestionsForPrint('OMG Ponies');
print r;
So from now on I'm probably going to add the ForPrint functions to all my procedures.
This got me thinking, maybe functions are what I want and I don't need procedures.
To test this I tried executing the function from .NET, except I can't do it. Is this really the way it is.
using (OracleConnection cnn = new OracleConnection("Data Source=Test;User Id=Test;Password=Test;"))
{
cnn.Open();
OracleCommand cmd = new OracleCommand("mypackage.getquestionsForPrint");
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.Add ( "p_USER", "OMG Ponies");
cmd.Connection = cnn;
OracleDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
Console.WriteLine(rdr.GetOracleValue(0));
}
Console.ReadLine();
}
So I get the error.
getquestionsForPrint is not a procedure or is undefined
I tried ExecuteScalar as well with the same result.
EDIT Taking Slider345's advice I've also tried setting the command type to text and using the following statement and I get
invalid SQL statement
mypackage.getquestionsForPrint('OMG Poinies');
and
var r refcursor; exec :r := mypackage.getquestionsForPrint('OMG Poinies');
Using Abhi's variation for the command text
select mypackage.getquestionsForPrint('OMG Poinies') from dual
resulted in
The instruction at "0x61c4aca5"
referenced memory at "0x00000ce1". The
memory could not be "read".
Am I just barking up the wrong tree?
Update
Attempting to add an output parameter doesn't help.
cmd.Parameters.Add(null, OracleDbType.RefCursor, ParameterDirection.Output);
Not sure what the name should be since its the return value of a function (I've tried null, empty string, mypackage.getquestionsForPrint) but in all cases it just results in
ORA-06550: line 1, column 7:
PLS-00306: wrong number or types of
arguments in call to
'getquestionsForPrint'
Final Edit (hopefully)
Apparently Guddie asked a similar question 3 months after I did. He got the answer which is to
Set your command text to an anonymous block
Bind a parameter to the ref cursor setting the direction to output
Call Execute non reader.
Then use your parameter
using (OracleConnection cnn = new OracleConnection("Data Source=Test;User Id=Test;Password=Test;"))
{
cnn.Open();
OracleCommand cmd = new OracleCommand("mypackage.getquestionsForPrint");
cmd.CommandType = CommandType.Text;
cmd.CommandText = "begin " +
" :refcursor1 := mypackage.getquestionsForPrint('OMG Ponies') ;" +
"end;";
cmd.Connection = cnn;
OracleDataAdapter da = new OracleDataAdapter(cmd);
cmd.ExecuteNonQuery();
Oracle.DataAccess.Types.OracleRefCursor t = (Oracle.DataAccess.Types.OracleRefCursor)cmd.Parameters[0].Value;
OracleDataReader rdr = t.GetDataReader();
while(rdr.Read())
Console.WriteLine(rdr.GetOracleValue(0));
Console.ReadLine();
}
I have not tested this with a function, but for my stored procedures. I specify the out parameter for the refCursor.
command.Parameters.Add(new OracleParameter("refcur_questions", OracleDbType.RefCursor, ParameterDirection.Output));
If you are able to get the function to work with the CommandType.Text. I wonder if you can try adding the parameter above except with the direction as:
ParameterDirection.ReturnValue
I am using Oracle.DataAccess version 2.111.6.0
I had to go up and down between the question and answers to figure out the full code that works. So I am giving the full code here that worked for me for others -
var sql = #"BEGIN :refcursor1 := mypackage.myfunction(:param1) ; end;";
using(OracleConnection con = new OracleConnection("<connection string>"))
using(OracleCommand com = new OracleCommand())
{
com.Connection = con;
con.Open();
com.Parameters.Add(":refcursor1", OracleDbType.RefCursor, ParameterDirection.Output);
com.Parameters.Add(":param1", "param");
com.CommandText = sql;
com.CommandType = CommandType.Text;
com.ExecuteNonQuery();
OracleRefCursor curr = (OracleRefCursor)com.Parameters[0].Value;
using(OracleDataReader dr = curr.GetDataReader())
{
if(dr.Read())
{
var value1 = dr.GetString(0);
var value2 = dr.GetString(1);
}
}
}
Hope it helps.
I know this is quite an old post, but since it took me so long to figure out all of the minutia involved in getting .NET to "fight nice" with Oracle, I figured I'd put this advice out there for anyone else in this sticky situation.
I frequently call Oracle stored procedures that return a REF_CURSOR in our environment (.NET 3.5 against Oracle 11g). For a function, you can indeed name the parameter anything you'd like, but then you need to set its System.Data.ParameterDirection = ParameterDirection.ReturnValue then ExecuteNonQuery against the OracleCommand object. At that point the value of that parameter will be the ref_cursor that the Oracle function returned. Just cast the value as an OracleDataReader and loop through the OracleDataReader.
I'd post the full code, but I wrote the data access layer in VB.NET years ago, and the bulk of the code consuming the data access layer (our corporate intranet) is in C#. I figured mixing languages in a single response would be the larger faux pas.