Oracle data access error: ORA-00936: missing expression - c#

I am accessing an Oracle database in my asp.net application, and am getting this error:
ORA-00936: missing expression
My c# code is:
getInfoByPoNum =
"SELECT h.SYS_HEADER_ID,
h.FOLIO1 AS INV_NUMBER,
v.VENDOR_NAME,
CASE WHEN h.Comments LIKE '%CLOSED%' THEN 'CLOSED' ELSE NVL(h.Comments, 'OPEN') END AS CComments,
h.ORG_ID
FROM INV_HEADERS h, VENDORS v
WHERE h.LOOKUP_CODE in ('STANDARD', 'BLANKET')
AND h.VENDOR_ID = v.VENDOR_ID
AND h.FOLIO1 = #invNumber"
OracleCommand CMD = new OracleCommand();
OracleConnection CONN = new OracleConnection(constring.ConnectionString);
CMD.Connection = CONN;
CONN.Open();
CMD.Parameters.Clear();
CMD.Parameters.Add(new OracleParameter("#invNumber", INVNumber));
CMD.CommandText = getInfoByPoNum;
using (var reader = CMD.ExecuteReader())
{
while (reader.Read())
{
The error occurs at CMD.ExecuteReader().
Based on other posts on SO and on the web, the query is correct and runs in oracle sql-developer.
What is causing the syntax error?
Update: If I modify the oracle query and enter a valid invoice number value instead of #invNumber, the query executes fine in my application.
getInfoByPoNum =
"SELECT h.SYS_HEADER_ID,
h.FOLIO1 AS INV_NUMBER,
v.VENDOR_NAME,
CASE WHEN h.Comments LIKE '%CLOSED%' THEN 'CLOSED' ELSE NVL(h.Comments, 'OPEN') END AS CComments,
h.ORG_ID
FROM INV_HEADERS h, VENDORS v
WHERE h.LOOKUP_CODE in ('STANDARD', 'BLANKET')
AND h.VENDOR_ID = v.VENDOR_ID
AND h.FOLIO1 = 2241QSA"

I believe that for Oracle your parameter should be specified as :invNumber, not #invNumber in your query:
AND h.FOLIO1 = :invNumber"
And when setting your parameter, it should look like this (just remove the #):
CMD.Parameters.Add(new OracleParameter("invNumber", INVNumber));
EDIT
You may also need to enable parameter binding by name (I think it's positional by default):
CMD.BindByName = true;

Try putting all your query in the same line, it seems that only the first line of the string is being executed. Also check if there isnĀ“t any escape character or special character that you have to treat with a "\" character.

And this may also occur, in my experience, when attempting to execute SQL with a terminating semicolon in the Oracle managed driver for .NET/C#.
So in that situation, execute the SQL within a wrapper for consistency and
do not use
SELECT * FROM X;
use
SELECT * FROM X
in other words, strip it off.

Related

Invalid Column Name: "value" - Error Even though it works in another form.

I am stuck at one problem and I just can't solve this.
I get this Error:
Error Message
That's the relevant table
The Code:
SqlConnection connection = new SqlConnection(connectionString);
connection.Open();
string query = "UPDATE CAC SET nextMaintainance = #nextMaintainance WHERE department = " + #departmentCB.Text;
SqlCommand command = new SqlCommand(query, connection);
command.Parameters.AddWithValue("#nextMaintainance", nextMaintainanceDT.Value);
command.ExecuteNonQuery();
The weird thing I don't understand is that a similar code works just fine without any error in my project:
query = "UPDATE LDV SET received = #received, department = #department WHERE Id =" + #idTxt.Text;
command = new SqlCommand(query, connection);
command.Parameters.AddWithValue("#received", inDT.Value);
command.Parameters.AddWithValue("#department", departmentCb.Text);
command.ExecuteNonQuery();
MessageBox.Show("Lungenautomat wurde aktualisiert");
If relevant, my connection string:
connectionString = ConfigurationManager.ConnectionStrings["SCBA_Manager_0._1.Properties.Settings.SCBAmanagerConnectionString"].ConnectionString;
I really hope you can help me :(
Thank you!
The department column is a text column, so comparing it to a value means the value should be wrapped in quotes.
// This fix is not the recommended approach, see the explanation after this code block
string query = "UPDATE CAC SET nextMaintainance = #nextMaintainance WHERE department = '" + departmentCB.Text + "'";
// ^--------------------------^------ single quote added to wrap the value returned by departmentCB.Text
On the other hand, this error does not occur in your second example, because there you're correctly using the Parameters.AddWithValue() method to add the value for the #department parameter, and because id is a numeric column, so it doesn't require the value wrapped in quotes.
However, while the code shown above does the job, it is not the right way of doing the job. The correct way is to used parameters for all values to be injected into a query. The queries you've shown above are already correctly using parameters for some values (e.g. nextMaintenance in the first query, received and department in the second), but are incorrectly doing string concatenation for other values (e.g. department in the first query, id in the second).
Usage of Parameterized SQL
The benefit of using parameterized SQL is that it automatically takes care of adding quotes, prevents SQL injection, etc.
Therefore, its best to change your first code block to:
SqlConnection connection = new SqlConnection(connectionString);
connection.Open();
string query = "UPDATE CAC SET nextMaintainance = #nextMaintainance WHERE department = #department";
SqlCommand command = new SqlCommand(query, connection);
command.Parameters.AddWithValue("#department", departmentCb.Text);
command.Parameters.AddWithValue("#nextMaintainance", nextMaintainanceDT.Value);
command.ExecuteNonQuery();
Notice how the string query is a single string without any messy concatenation, and that it contains two parameters #nextMaintenance and #department? And how the values for those parameters are correctly injected using Parameters.AddWithValue() in the following lines?
Your second code block can be similarly improved by using a parameter for the Id column.
query = "UPDATE LDV SET received = #received, department = #department WHERE Id = #Id ";
command.Parameters.AddWithValue("#Id", idTxt.Text);
Further Information
Do read up about SQL injection ( https://technet.microsoft.com/en-us/library/ms161953(v=sql.105).aspx ) to see how using string concatenation like your original code can lead to various security issues, and why parameterized queries are the preferred way of injecting dynamic values into SQL queries.
You can read up more about parameterized queries here: https://msdn.microsoft.com/en-us/library/yy6y35y8(v=vs.110).aspx
In your first example, the WHERE clause evaluates to
WHERE department = Kasseedorf
wheras it should be
WHERE department = 'Kasseedorf'
So the line should be
string query = "UPDATE CAC SET nextMaintainance = #nextMaintainance WHERE department = '" + #departmentCB.Text +"'";
It works in the second example, because id is an integer and doesn't neet quotes.

not able to load odbcdatareader to a datatable

I am using an Informix db, and I am trying to get data for a specific item and store it in a datatable.
I checked the following:
1) connection string looks good
2) the connection is able to open
3) I used the same connection string from the web.config on a dataset creating a table adapter and it is able to retrieve the record.
This is the code I am using:
var connectionstring = ConfigurationManager.ConnectionStrings["TestDataTable"].ConnectionString;
OdbcConnection con = new OdbcConnection(connectionstring);
//con.ConnectionString = connectionstring;
if (TxtItem.Text != hold_item)
{
con.Open();
OdbcCommand cmd = new OdbcCommand(#"Select t_item,t_idsc,t_upct,
t_item_upc,t_ctyp,t_citg,
t_best,t_disp,t_mold,t_csel
from informix.tsckcm907
where t_item = " + stitem, con);
OdbcDataReader myReader = cmd.ExecuteReader();
DataTable testdt = new DataTable();
testdt.Load(myReader);
foreach (DataRow row in testdt.Rows)
{
lbldesc.Text = row["t_idsc"].ToString();
Spanish_Item();
{
DropDownList2.SelectedIndex = 1;
object stlanguage = 1;
hold_language = Convert.ToString(stlanguage);
TxtBestBefore.Text = row["t_best"].ToString();
holdbest = Convert.ToInt16(TxtBestBefore.Text);
}
}
myReader.Close();
myReader.Dispose();
cmd.Dispose();
con.Close();
con.Dispose();
}
in debug mode my error occurs at the OdbcDataReader line:
error message:
An exception of type 'System.Data.Odbc.OdbcException'
occurred in System.Data.dll but was not handled in user code
Additional information: ERROR [42000] [Informix]
[Informix ODBC Driver][Informix]A syntax error has
occurred.
If your Informix ODBC driver says: "A syntax error has occurred" then you have to check your SQL statement:
"Select t_item,... from informix.tsckcm907 where t_item = " + stitem
I think that something is wrong with stitem. We don't know what type and value it is, but if its type is some kind of string or date then it may be in the wrong form. Easiest way is to extract full SQL statement (simply print it before execution) and use it with some database editor (for example db_access from Informix). Then make it work in SQL editor and transform stitem variable into acceptable form (add quotes, escape internal quotes, escape special characters etc.)
I also recommend use of PreparedStatement that separates your query from data. This way you do not need to worry about stitem form. No quotes, no escaping, just place holder in query string and value added separately.
I don't use C# but I see that C# can work with preapred statements with unnamed parameters:
cmd.CommandText = "SELECT ... FROM ... WHERE t_item = ?";
cmd.Parameters.Add("#t_item", ObdcType.VarChar, 200).Value = t_item;
or with named parameters:
cmd.CommandText = "SELECT ... FROM ... WHERE t_item = #t_item";
cmd.Parameters.Add("#t_item", ObdcType.VarChar, 200).Value = t_item;
I use unnamed parameters from ODBC so Informix driver can work with such parameters but you will have to check it yourself with C#.

select query does not work with parameters using Parameters.AddWithValue

The following query in C# doesn't work, but I can't see the problem:
string Getquery = "select * from user_tbl where emp_id=#emp_id and birthdate=#birthdate";
cmdR.Parameters.AddWithValue("#emp_id", userValidate.emp_id);
cmdR.Parameters.AddWithValue("#birthdate", userValidate.birthdate);
OdbcCommand cmdR = new OdbcCommand(Getquery, conn);
OdbcDataReader Reader = cmdR.ExecuteReader();
Reader.HasRows returns no result but when I query it to my database I got data.
I'll assume your code is actually not quite as presented, given that it wouldn't currently compile - you're using cmdR before you declare it.
First, you're trying to use named parameters, and according to the documentation of OdbcCommand.Parameters, that isn't supported:
When CommandType is set to Text, the .NET Framework Data Provider for ODBC does not support passing named parameters to an SQL statement or to a stored procedure called by an OdbcCommand. In either of these cases, use the question mark (?) placeholder.
Additionally, I would personally avoid using AddWithValue anyway - I would use something like:
string sql = "select * from user_tbl where emp_id = ? and birthdate = ?";
using (var connection = new OdbcConnection(...))
{
connection.Open();
using (var command = new OdbcCommand(sql, connection))
{
command.Parameters.Add("#emp_id", OdbcType.Int).Value = userValidate.EmployeeId;
command.Parameters.Add("#birthdate", OdbcType.Date).Value = userValidate.BirthDate;
using (var reader = command.ExecuteReader())
{
// Use the reader here
}
}
}
This example uses names following .NET naming conventions, and demonstrates properly disposing of resources... as well as fixing the parameter issue.
I do think it's slightly unfortunate that you have to provide a name for the parameter when adding it to the command even though you can't use it in the query, but such is life.
Use like this:
string Getquery = "select * from user_tbl where emp_id=? and birthdate=?";
cmdR.Parameters.AddWithValue("#emp_id", userValidate.emp_id);
cmdR.Parameters.AddWithValue("#birthdate", userValidate.birthdate);
OdbcCommand cmdR = new OdbcCommand(Getquery, conn);
OdbcDataReader Reader = cmdR.ExecuteReader();
while(Reader.Read())
{
//Do something;
}
I know this thread is old, but I wanted to share my solution for anyone else coming up on this.
I was having issues with the typical method that Jon posted. I have used it before, but for some reason with this new string I had it was not wanting to actually place the parameter correctly and was causing the reader to not work.
I ended up doing something like this instead, since in the end we are just replacing parts of a string.
string sql = "select * from user_tbl where emp_id = "+ var1 +" and birthdate = "+
var2""
OdbcCommand command = new OdbcCommand(sql);
This was easier for me to get to work. Be warned though, I am not sure if it has any specific drawbacks when compare to using the command parameter method.

C# SQL string formatting

I am new to .net/C#. Coming from PHP and some Java, I am finding the new languages interesting and challenging.
I have an issue with a sql string
string query = #"select * from Users where role='member' and
SUBSTRinG(lname, 1, 1) = '"+querystring + "' ORDER BY lname ASC";
Which to me, looks fine. however when run my solution and output the query as it is not working, I get this as my output:
select * from Users where role='member' and SUBSTRinG(lname, 1, 1)
= ' O ' ORDER BY lname ASC
This is output into my Firebug console (the page that uses this query is accessed via AJAX).
Is their a reason my 's are being turned into their code version, ie '&#39'
Thanks
In C# you should be using SqlCommand to excute the query, and to prevent sql injection using the parameter collection.
Your query seems fine - The issue might be the way you are running it or the parameters being supplied. Update your question with more details on what you are expecting vs what is happening, include any error messages generated.
Below is a general guideline of how to get data from a sql table to a c# Data Table object.
SqlConnection conn = new SqlConnection("YourConnectionString");
SqlCommand cmd = new SqlCommand(#"select * from Users where role='member' and
SUBSTRinG(lname, 1, 1) = #query ORDER BY lname ASC");
cmd.Parameters.AddWithValue("#query", querystring);
DataTable resultTable = new DataTable();
try
{
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(resultTable);
} finally {
if (conn.State != ConnectionState.Closed) conn.Close();
}
Console.WriteLine(String.Format("Matched {0} Rows.", resultTable.Rows.Count));
For SQL injection protection:
You can provide escape sequence for single quotes by replacing them with two single quotes '' so that it will be treated as a single quote inside SQL strings. Otherwise it is considered as a start or end of the string value in SQL.
Replacing single quotes using ' in .net is also preferred but its better going with two single quotes.

Oracle - Getting Select Count(*) from ... as an output parameter in System.Data.OracleClient

Greetings all,
I have a question. I am trying to build a parametrized query to get me the number of rows from a table in Oracle. Rather simple. However I am an Oracle newbie..
I know in SQL Server you can do something like:
Select #outputVariable = count(*) from sometable where name = #SomeOtherVariable
and then you can set up an Output parameter in the System.Data.SqlClient to get the #outputVariable.
Thinking that one should be able to do this in Oracle as well, I have the following query
Select count(*) into :theCount from sometable where name = :SomeValue
I set up my oracle parameters (using System.Data.OracleClient - yes I know it will be deprecated in .Net 4 - but that's what I am working with for now) as follows
IDbCommand command = new OracleCommand();
command.CommandText = "Select count(*) into :theCount from sometable where name = :SomeValue";
command.CommandType = CommandType.Text;
OracleParameter parameterTheCount = new OracleParameter(":theCount", OracleType.Number);
parameterTheCount .Direction = ParameterDirection.Output;
command.Parameters.Add(parameterTheCount );
OracleParameter parameterSomeValue = new OracleParameter(":SomeValue", OracleType.VarChar, 40);
parameterSomeValue .Direction = ParameterDirection.Input;
parameterSomeValue .Value = "TheValueToLookFor";
command.Parameters.Add(parameterSomeValue );
command.Connection = myconnectionObject;
command.ExecuteNonQuery();
int theCount = (int)parameterTheCount.Value;
At which point I was hoping the count would be in the parameter parameterTheCount that I could readily access.
I keep getting the error ora-01036 which http://ora-01036.ora-code.com tells me to check my binding in the sql statement. Am I messing something up in the SQL statement? Am I missing something simple elsewhere?
I could just use command.ExecuteScaler() as I am only getting one item, and am probably going to end up using that, but at this point, curiosity has got the better of me. What if I had two parameters I wanted back from my query (ie: select max(ColA), min(ColB) into :max, :min.....)
Thanks..
Some versions of the ADO does not need the colon : configuring OracleParameter.
Instead of:
new OracleParameter(":theCount", OracleType.Number);
try
new OracleParameter("theCount", OracleType.Number);
Anyway, I think you have to use the ExecuteScalar() function of the IDbCommand and avoiding use of into (which I'm not sure it's valid on this context). I mean:
IDbCommand command = new OracleCommand();
command.CommandText = "Select count(*) from sometable where name = :SomeValue";
command.CommandType = CommandType.Text;
OracleParameter parameterSomeValue = new OracleParameter("SomeValue", OracleType.VarChar, 40);
parameterSomeValue .Direction = ParameterDirection.Input;
parameterSomeValue .Value = "TheValueToLookFor";
command.Parameters.Add(parameterSomeValue );
command.Connection = myconnectionObject;
int theCount = (int)command.ExecuteScalar();
Disclaimer: The code have not been compiled, and may be have any little error.
Update: If you take a look on the Oracle SELECT syntax, you will see that The SELECT INTO sentence is not recognized. But it's valid in PLSQL syntax as you can see here. You can try one of the following to see if it works (not tested):
command.CommandText = "begin Select count(*) into :someCount from sometable where name = :SomeValue; end;";
I think the problem is that you have a trailing space in the parameter name for parameterTheCount.
Edit
Now remove the colons from the parameter names in the constructor to OracleParameter.

Categories

Resources