As the code Shows below, I want to insert a row into a database table (oracle 11) and return a String-Value of the inserted row.
using (OracleCommand cmd = con.CreateCommand()) {
cmd.CommandText = "insert into foo values('foo','bar') returning idString into :lastIdParam";
cmd.Parameters.Add(new OracleParameter("lastIdParam", OracleDbType.Varchar2), ParameterDirection.ReturnValue);
cmd.ExecuteNonQuery(); // returning 1 (insert row successfully)
var result = cmd.Parameters["lastIdParam"].Value.ToString(); // == String.Empty
}
Debugging shows that lastIdParam.Value's value = Empty.String:
My Problem is, that I'm not getting the return string into my return-parameter but it will work when returning an integer value (like sequence no of inserted id). Cast Problem? ...?
The idString is filled if running the Statement directly (or if I just do something like returning 'ABC' into :myOutputParameter
Any ideas how to retrieve a string after inserting row?
Have you tried setting a size for the parameter? The default size is 0.
new OracleParameter("lastIdParam", OracleDbType.Varchar2, 128)
The idString is an expression which has no value in your context, unless it is a column name in your table. Therefore, it is epected to be empty. You may change your query like the example below and see what happens.
cmd.CommandText = "insert into foo values('foo','bar') returning hereYouHaveToUseAColumnFromTheFooTable into :lastIdParam";
Related
I'm trying to get the last row of a table using C# but it doesn't seem to be working, this is my code:
MySqlConnection cnnGetID = new MySqlConnection(Global.connectionString);
cmd = "SELECT ContactID FROM Contacten ORDER BY ContactID DESC LIMIT 1";
MySqlCommand cmdGetID = new MySqlCommand(cmd, cnnGetID);
cnnGetID.Open();
string contactID = cmdGetID.ExecuteNonQuery().ToString();
MessageBox.Show(contactID);
cnnGetID.Close();
The value this returns is -1 while it should be returning 59.
The strange thing is is that when I run this command in phpmyadmin I DO get 59.
Any ideas on why C# is not returning the correct value but phpmyadmin is?
EDIT: problem solved, should've uses ExecuteScalar(). Looks like I've been staring at my monitor for a bit too long...
You need to use ExecuteScalar instead of ExecuteNonQuery.
MySqlConnection cnnGetID = new MySqlConnection(Global.connectionString);
cmd = "SELECT ContactID FROM Contacten ORDER BY ContactID DESC LIMIT 1";
MySqlCommand cmdGetID = new MySqlCommand(cmd, cnnGetID);
cnnGetID.Open();
string contactID = cmdGetID.ExecuteScalar().ToString();
MessageBox.Show(contactID);
cnnGetID.Close();
This should resolve your issue.
The value this returns is -1 while it should be returning 59.
No, it's behaving exactly as documented by IDbCommand.ExecuteNonQuery:
For UPDATE, INSERT, and DELETE statements, the return value is the number of rows affected by the command. For all other types of statements, the return value is -1.
You're using a SELECT statement - a query. So instead of executing ExecuteNonQuery, you should be using ExecuteQuery and iterating over the results, or ExecuteScalar, given that you know you'll have a single result:
string contactID = cmdGetID.ExecuteScalar().ToString();
you should use ExecuteScalar because you are returning value ExecuteNonQuery returns the number of rows affected by update delete or insert opeation
you can check this for more info
ExecuteNonQuery
Returns the number of rows affected.
ExecuteScalar
Executes the query, and returns the first column of the first row in
the result set returned by the query. Additional columns or rows are
ignored.
for more information you can check this The MySqlCommand Object
you can use query like this
MySqlConnection cnnGetID = new MySqlConnection(Global.connectionString);
cmd = "SELECT TOP 1 ContactID FROM Contacten ORDER BY ContactID";
MySqlCommand cmdGetID = new MySqlCommand(cmd, cnnGetID);
cnnGetID.Open();
string contactID = cmdGetID.ExecuteNonQuery().ToString();
MessageBox.Show(contactID);
cnnGetID.Close();
I have a problem with the value returned from SqlCommand, I have this code:
string sqlSelect = "Select TOP 1 Quotation.SentToSupp as SentToSupp FROM Quotation JOIN Notifications ON Quotation.QuotationId = QuotationID ";
SqlCommand Comm = new SqlCommand(sqlSelect, this.Connection);
sqlSelect query selects the first DateTime value. When I call to SqlCommand I want to get this value (just one value). I add the query and my connection fine.
But I don't know how to get my DateTime value... Must to use something like ExecuteReader?
Thank you in advance!!
ExecuteReader works but more objects and more code are required - (An SqlDataReader, call to Read and Extract value). Instead you could simply use the ExecuteScalar method of the SqlCommand object (It returns just the first column of the first row of the resultset)
string sqlSelect = "Select TOP 1 Quotation.SentToSupp as SentToSupp FROM ....";
SqlCommand Comm = new SqlCommand(sqlSelect, this.Connection);
object result = Comm.ExecuteScalar();
if(result != null)
DateTime dtResult = Convert.ToDateTime(result);
Just pay attention to the fact that ExecuteScalar could return a null value if, for some reason, there is no record in the result returned
Use SqlCommand.ExecuteScalar method - Executes the query, and returns the first column of the first row in the result set returned by the query. Additional columns or rows are ignored.
I have a multi-statement SQL query that takes place within a SqlTransaction as follows:
string sName = "";
string sNumber = "";
string sFirstName = "";
string sqlQuery1 = #"INSERT INTO myTable(Name, Number) VALUES (#_Name, #_Number)";
string sqlQuery2 = #"INSERT INTO myOtherTable( ID, FirstName) VALUES ( #_ID, #_First )";
SqlConnection conn = new SqlConn(***);
conn.Open();
SqlTransaction transaction;
SqlCommand command1 = new SqlCommand(sqlQuery1, conn, transaction);
SqlCommand command2 = new SqlCommand(sqlQuery2, conn, transaction);
command1.Parameters.Add("#_Name", SqlDbType.NVarChar, 255).Value = sName;
command1.Parameters.Add("#_Number", SqlDbType.NVarChar, 255).Value = sNumber;
int? returnedID = (int?)command1.ExecuteScalar();
command2.Parameters.Add("#_ID", SqlDbType.Int).Value = (int)returnedID; <--- Error
command2.Parameters.Add("#_First", SqlDbType.NVarChar, 255).Value = sFirstName;
command2.ExecuteNonQuery();
transaction.Commit();
At the line I marked as an error, I get an error during execution about "The parameterized query expects the parameter #_ID which was not supplied.
Now, assuming I have no typos while simplifying my code to this example, why am I receiving a null value in returnedID for a properly executed statement? When I just run the statement on its own in a query, I get no errors and it returns successful. Why null when running it in this transaction? Thanks!
Edit: I purposely left off a try{} catch from this as it wasn't relevant to the question I had. Otherwise, I just forgot about the IDENTITY_SCOPE() that I needed in the Insert query since there would otherwise be no return value.
ExecuteScalar returns the first column of the first row in the result set returned by the query (MSDN). Your statement is an insert, it does not return any result set.
The easiest way to fix your example is to run all queries in one command and use SCOPE_IDENTITY to get the inserted id.
string sqlQuery =
#"INSERT INTO myTable(Name, Number) VALUES (#_Name, #_Number);
INSERT INTO myOtherTable( ID, FirstName) VALUES ( SCOPE_IDENTITY(), #_First )";
Since insert statements don't return a value, ExecuteScalar() can't return the identity as you want. You can combine the insert with a select scope_identity() as in the example on the ExecuteScalar() documentation to get the functionality I think you're expecting.
You seem to assume that INSERT INTO myTable(Name, Number) VALUES (#_Name, #_Number) is going to return the ID of the inserted row; why would you think that? The assumption is incorrect, which is why you're getting a null value back from ExecuteScalar.
ExecuteScalar returns null if the command's result set is empty, and the result set of an INSERT statement is in fact empty, unless you include an OUTPUT clause.
I tried milions of methods to make scope identity work. It is just returns __Page !!
Query = "INSERT INTO seekers(name,sname,lname,status,gender,dob,major,experince,email,password,phone,valid,city) values(#name,#sname,#lname,#status,#gender,#dob,#major,#exp,#email,#password,#phone,0,#city);SELECT SCOPE_IDENTITY();";
// setting up command definition
Command = new SqlCommand(Query, Connection);
// setting up command parameters
Command.Parameters.AddWithValue("email", txt_email.Text);
Command.Parameters.AddWithValue("gender", lst_gender.SelectedValue);
Command.Parameters.AddWithValue("status", lst_status.SelectedValue);
Command.Parameters.AddWithValue("phone", long.Parse("968" + txt_phone.Text));
Command.Parameters.AddWithValue("password", txt_password.Text);
Command.Parameters.AddWithValue("exp", lst_exp.SelectedValue);
Command.Parameters.AddWithValue("city", lst_exp.SelectedValue);
Command.Parameters.AddWithValue("major", lst_major.SelectedValue);
Command.Parameters.AddWithValue("name", txt_name.Text);
Command.Parameters.AddWithValue("sname", txt_sname.Text);
Command.Parameters.AddWithValue("lname", txt_lname.Text);
Command.Parameters.AddWithValue("dob", cld_birth.SelectedDate);
int ID = (int)Command.ExecuteScalar();
Try Out Parameter as follow...
Query = "INSERT INTO seekers(name,sname,lname,status,gender,dob,major,experince,email,password,phone,valid,city) values(#name,#sname,#lname,#status,#gender,#dob,#major,#exp,#email,#password,#phone,0,#city);SET #ID=SCOPE_IDENTITY();"
//Your Parameters..
SqlParameter ID=new SqlParameter();
ID.Name="#ID";
ID.Direction=ParameterDirection.Output;
Command.Parameters.Add(ID);
Command.ExecuteNonQuery();
int id=(int)ID.Value;
or
Tryb to Cast Output as follow...
Query = "INSERT INTO seekers(name,sname,lname,status,gender,dob,major,experince,email,password,phone,valid,city) values(#name,#sname,#lname,#status,#gender,#dob,#major,#exp,#email,#password,#phone,0,#city);SELECT CAST(scope_identity() AS int);"
int id= (Int32)Command.ExecuteScalar();
use set nocount off and try
As First execute statement is insert the returned value is number of records effected
SCOPE_IDENTITY will return a decimal, try:
int ID = (int) (decimal) Command.ExecuteScalar();
It's not very clear what you mean by:
It is just returns __Page !!
Presumably the posted code is throwing an exception, and that's resulting in some higher level code doing whatever it is you mean by "... returns __Page".
If you look at the exception details, you'll find more about what happened: which I suspect is an InvalidCastException because you're trying to cast the object returned by Command.ExecuteScalar (a boxed decimal) to an int.
I've done some research before posting this question and I'm aware of the fact that when there's no data returned, ExecuteScalar will throw a System.NullReferenceException. That is why I modified my stored proc to "return 1" so there's guaranteed a return value. However, I'm still getting the NULL reference exception.
So I tried to use the SqlCommand to query a table that has data:
SqlCommand sqlCommand = new SqlCommand("SELECT * FROM ATableThatHasValues", conn)
When I ran execute scalar I was able to pick up a value so I know I have permission to query the database. I'm suspecting that this is some specific storeed proc permission setting that I missed?
I'd really appreciate any comment/suggestions as I've been stuck on this for a day now. :(
My code looks like this:
using (SqlConnection sqlConnection = new SqlConnection(connectionString))
{
sqlConnection.Open();
using (SqlCommand sqlCommand = new SqlCommand("GetSomeValue", sqlConnection))
{
sqlCommand.CommandType = CommandType.StoredProcedure;
//sqlCommand.Parameters.Add(new SqlParameter("#Id", this.ID));
//sqlCommand.Parameters.Add(new SqlParameter("#State", 1 /* active */));
byte retValue = (byte)sqlCommand.ExecuteScalar();
return retValue;
}
}
THANKS!
I'm just going to elaborate on what #gbn said. When you execute SQL code you can return information in three different ways, OUTPUT parameters, tabular data and/or a single RETURN value. Like #gbn said, RETURN values are essentially specialized OUTPUT parameters. ExecuteScalar only sees information from tabular data, namely the first column of the first row. If no tabular data is received when you call ExecuteScalar a null value is returned instead. If you try to do something with this null value then obviously you'll get a NRE.
Random guess
You are using RETURN so there is no dataset to read column 1, row 1 for ExecuteScalar
Use SELECT or OUTPUT parameters
Edit: Actually, not so random
RETURN 1 is not a result set: it's a "special" parameter
sqlCmd.Parameters.Add(New SqlParameter("RETURN_VALUE", SqlDbType.Int)).Direction = ParameterDirection.ReturnValue