I'm getting a SqlException in my code:
Incorrect syntax near 'MatricNO'
Here is the code:
public static StudentDetail GetStudent(string MatricNO)
{
//Calling on the connection class and get connection method
SqlConnection connection = ConnectionClass.GetConnection();
//Sql select statement that reads from the database
string selectStatement = "SELECT MatricNO,Faculty,Department,Course,FirstName,MiddleName,LastName" +
"FROM StudentInfo" +
"WHERE MatricNO=#MatricNO";
SqlCommand selectCommand=new SqlCommand(selectStatement,connection);
selectCommand.Parameters.AddWithValue("#MatricNO", MatricNO);
try
{
connection.Open();
SqlDataReader reader = selectCommand.ExecuteReader(CommandBehavior.SingleRow);
if(reader.Read())
{
//Read the database information into the StudentDetail Class
StudentDetail studentDetail=new StudentDetail();
studentDetail.Studentmatricno = reader["MatricNO"].ToString();
studentDetail.Faculty = reader["Faculty"].ToString();
studentDetail.Dept = reader["Department"].ToString();
studentDetail.Course = reader["Course"].ToString();
studentDetail.Firstname = reader["FirstName"].ToString();
studentDetail.Middlename = reader["MiddleName"].ToString();
studentDetail.Surname = reader["LastName"].ToString();
return studentDetail; //return all that has been read to the student detail class
}
else
{
// return null if queried record does not exist
return null;
}
}
catch (SqlException ex)
{
throw ex;
}
finally
{
connection.Close();
}
}
Can anyone help me resolve this issue?
You need spaces between FROM and SELECT, and FROM and WHERE clause
string selectStatement = "SELECT MatricNO,Faculty,Department,Course,FirstName,MiddleName,LastName" +
" FROM StudentInfo" +
" WHERE MatricNO=#MatricNO";
Its always better to look at the generated SQL from string concatenation and trying it directly on DB.
Your SQL query needs spaces after the field list and table name:
string selectStatement =
"SELECT MatricNO,Faculty,Department,Course,FirstName,MiddleName,LastName " +
"FROM StudentInfo " +
"WHERE MatricNO=#MatricNO";
You could also use a verbatim string literal:
string selectStatement =
#"SELECT MatricNO,Faculty,Department,Course,FirstName,MiddleName,LastName
FROM StudentInfo
WHERE MatricNO=#MatricNO";
Related
I want to pass an user input to a where clause in a method.
The method has sql query and it uses parameter, but it seems like the parameter is not passed to the query. (I debugged and saw it does not go into the while loop.
My code is below:
Console.WriteLine("Enter your name: ");
string name = Console.ReadLine();
string prm = "\"" + name + "\""; // Doublequote a string
//execute method
CheckCustomer(prm);
private static string CheckCustomer(string cusName)
{
string cust = "null";
try
{
Console.WriteLine("\nChecking custoemr...\n");
// Sql Select Query
string sql = "SELECT * FROM Customer WHERE CustomerName = #CusName";
SqlCommand cmd = new SqlCommand(sql, sqlConnection);
cmd.Parameters.AddWithValue("#CusName", cusName);
SqlDataReader dr;
dr = cmd.ExecuteReader();
string strCusname = "Customer Name Found";
Console.WriteLine("{0}", strCusname.PadRight(25));
Console.WriteLine("==============================");
while (dr.Read())
{
////reading from the datareader
cust = dr["CustomerName"].ToString();
}
dr.Close();
return cust;
}
catch (SqlException ex)
{
// Display error
Console.WriteLine("Error: " + ex.ToString());
return null;
}
}
When I execute CheckCustomer() without the where clause, it works perfect.
However, once I add a parameter, does not go inside while loop; it goes to dr.Close(); directly.
What is wrong with this code?
To check for nulls in SQL server you use "is null" instead of "where field = null"
if you tried the query in sql server management studio u will not get any result
since string cust = "null"; that means ur code checks for customerName = null, but as i stated that this is not the right way to check for null and this query will not return any result, and since there is no result that means dr.Read() will evaluate to false and the while loop won't be executed
You don't need to wrap the string value in quote. You can remove this line, since SqlParameter will handle that for you.
string prm = "\"" + name + "\""; // Doublequote a string
Also, if you want your query to support optional null values (i.e. where NULL implies that you DO NOT want to filter on customer name then you can simpy do:
SELECT * FROM Customer WHERE CustomerName = ISNULL(#CusName, CustomerName)
In your parameter section you can do something like:
cmd.Parameters.AddWithValue("#CusName", string.IsNullOrWhiteSpace(cusName) ? DbNull.Value: cusName);
If you don't want to allow nulls then you can leave the SQL query as-is as a throw a new ArgumentNullException at the top of your query method (i.e. add a guard clause):
if (string.IsNullOrWhiteSpace(CustomerName)) throw new ArgumentNullException(nameof(CustomerName));
Your query appears to be searching for the first customer with matching name. In that case you should probably add a "TOP 1" to avoid needless overhead:
SELECT TOP 1 * FROM Customer WHERE CustomerName = ISNULL(#CusName, CustomerName)
Console.WriteLine("Enter your name: ");
string name = Console.ReadLine();
string prm = "\"" + name + "\""; // Doublequote a string
//execute method
CheckCustomer(prm);
private static string CheckCustomer(string cusName)
{
string cust = "null";
try
{
Console.WriteLine("\nChecking custoemr...\n");
// Sql Select Query
string sql = "SELECT * FROM Customer WHERE CustomerName = #CusName";
SqlCommand cmd = new SqlCommand(sql, sqlConnection);
cmd.Parameters.AddWithValue("#CusName", cusName);
SqlDataReader dr;
dr = cmd.ExecuteReader();
string strCusname = "Customer Name Found";
Console.WriteLine("{0}", strCusname.PadRight(25));
Console.WriteLine("==============================");
while (dr.Read())
{
////reading from the datareader
cust = dr["CustomerName"].ToString();
}
dr.Close();
return cust;
}
catch (SqlException ex)
{
// Display error
Console.WriteLine("Error: " + ex.ToString());
return null;
}
}
try this.
When I run the code the result will be of 'Type' instead of the SUM of Name.
Tried also do the SUM inside the Reader[("Types")] and it displays SUM(Types). It should display the amount of that particular name
Code inside c#:
public void DisplayName()
{
try
{
string Connection = #"Data Source=local;Initial Catalog=Project;Integrated Security=True";
SqlConnection Connect = new SqlConnection(Connection);
string Name;
Console.WriteLine("\nShowing Name\n");
Console.WriteLine("Enter name type: \n");
country = Console.ReadLine();
ConnectingDatabase.Open();
string Query = "SELECT SUM(Types) FROM PersonName WHERE Name = #Name";
SqlCommand Commands = new SqlCommand(Query, ConnectingDatabase, ConnectingDatabase.BeginTransaction());
Commands.Parameters.Add(new SqlParameter("#Name", country));
SqlDataReader Reader = ParaComm.ExecuteReader();
if (Reader.Read())
{
Console.WriteLine("Your name is " + name + " with sum of {0}\n", Reader[("Types")]);
}
Reader.Close();
ParaComm.Transaction.Commit();
Connect.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
You should use Group By when use aggregeate function in sql. Try this Sql-Command
string Query = "SELECT SUM(Types) FROM main.Stats Group by column_name WHERE
Name = #Name";
As you learned, you can always reference a column by the column number. i.e 0 in this case.
However, the easiest way to deal with this moving forward, and avoid issues with changes to a query that cause column numbers to change, is to provide an alias for the column.
If you add an alias to your query, changing it to
SELECT SUM(Types) as TypeSum FROM PersonName WHERE Name = #Name you should find that you can access the value using Reader["TypeSum"] syntax.
I'm relatively new but I've been researching this issue for over 2 days, so I think I've done my due diligence ... however if this has already been answered before I apologize.
My basic issue is I'm trying to create some dependent combo boxes. The wrinkle is the displayed value is typically not the lookup value for the next query/Combo box (I'm using an OLEDB compliant data base)
For example: Table1 (T1) contains ID (int) & NM (string), Table2 (T2) contains ID (int) & STATUS (string). I run Query1 (Q1) to display T1.NM in Combobox1 (CB1), when selected I run Query1a to lookup/get the selected Table1.ID to pass to Query2 that populates Combobox2. The connection string and Q1 work fine, CB1 displays properly, but once I select this error is thrown:
"OleDbException .. SQL Passthru expression ... using equals (=) has components that are of different data types"
// ** Initial connection & populate CB1 - This works fine **
public void comboboxLoad()
{
string conn3str = <Connection String >;
string query1 = "select NM from Table1 where REFVALUE=1 ; ";
OleDbConnection conn3 = new OleDbConnection(conn3str);
OleDbCommand tblRow1 = new OleDbCommand(query1, conn3);
OleDbDataReader rdRow1;
try
{
conn3.Open();
lblConnState.Text = "Connection Successful";
rdRow1 = tblRow1.ExecuteReader();
while (rdRow1.Read())
{
int colindx1 = rdRow1.GetOrdinal("NM");
string sItbl = rdRow1.GetString(colindx1);
CB1.Items.Add(sItbl);
}
}
catch (Exception ex)
{
MessageBox.Show("Error " + ex);
}
}
// ** Get value from CB1, create query to populate CB2 **
private void CB1_SelectedIndexChanged(object sender, EventArgs e)
{
string conn3str = <Connection String >;
OleDbConnection conn3 = new OleDbConnection(conn3str);
conn3.Open();
// Pass the selected value from CB1 (string) equal to Table1.NM (string)
string query1a = "select ID from Table1 where NM = '" + CB1.Text + "' ; ";
OleDbCommand TabID = new OleDbCommand(query1a, conn3);
int TabId2 = Convert.ToInt32(TabID.ExecuteScalar());
// Pass the variable TabId2 (int) equal to Table2.ID (int)
string query2 = "select STATUS from Table2 where ID = '" + TabId2 + "'; ";
OleDbCommand tblRow2 = new OleDbCommand(query2, conn3);
// OleDbDataReader rdTabID;
// OleDbDataReader rdRow2;
try
{
OleDbDataReader rdRow2 = TabID.ExecuteReader();
OleDbDataReader rdTabID = tblRow2.ExecuteReader(); // ** Error points to this line **
while (rdRow2.Read())
{
int TabIdidx = rdTabID.GetOrdinal("ID");
string TabIDVal = rdTabID.GetString(TabIdidx);
// Pass reference ID to label on form
lblBTableID.Text = TabId2.ToString();
int colindx1 = rdRow2.GetOrdinal("STATUS");
string sIntVal = rdRow2.GetString(colindx1);
cmbLowLvl.Items.Add(sIntVal);
}
}
catch (Exception ex)
{
MessageBox.Show("Error " + ex);
}
}
Are you positive you're getting a value back on this line int TabId2 = Convert.ToInt32(TabID.ExecuteScalar());?
Convert.ToInt32 doesn't throw a ArgumentNullException like int.Parse does so it's possible that the variable is not getting set.
Also you may want to consider changing your queries to use parameterized SQL rather than concatenation for security purposes.
https://msdn.microsoft.com/en-us/library/system.data.oledb.oledbcommand.parameters(v=vs.110).aspx
I've been able to figure out the problem. I'm really not sure why it didn't work originally, but I think it was a reader mismatch, since I was only looking for a single value back from the query ExecuteScalar() seemed to do the trick and I didn't need the 'while' loop. The working code is below.
Next I'll need to pass this return value (ID) in my next query to populate CB2. Thanks #
private void CB1_SelectedIndexChanged(object sender, EventArgs e)
{
string conn3str = <Connection String >;
OleDbConnection conn3 = new OleDbConnection(conn3str);
// Pass the selected value from CB1 (string) equal to Table1.NM (string) but return the int ID.
OleDbCommand tblRow2 = new OleDbCommand("select ID from Table1 where NM= '"+ CB1.Text +"' ;" , conn3);
try
{
conn3.Open();
string r2 = Convert.ToString(tblRow2.ExecuteScalar());
MessageBox.Show(r2);
lblBTableID.Text = "ID Code= " + r2;
conn3.Close();
}
catch (Exception ex)
{
MessageBox.Show("Error " + ex);
}
}
Having problem reading a value from my table in mysql, is the index value i cant read the value back no matter what. all i get is the initialized value of 0 i dont get any error because it return 0, if i run the query in the database it get the correct value. i tried to use executeScalar() but with the same result .
MySqlConnection conn = new MySqlConnection(MyConString);
ulong ukey=0;
try
{
string sql_users2 = "SELECT `key` FROM `permuser` WHERE `user` = '" + myuser + "' AND `code` = '" + mycode + "'";
MySqlCommand cmdSel2 = new MySqlCommand(sql_users2, conn);
conn.Open();
MySqlDataReader dr2 = cmdSel2.ExecuteReader();
dr2.Read();
ukey = dr2.GetUInt64(dr2.GetOrdinal("key"));
// MessageBox.Show("Sorry " + myuser + " already have access to " + mycode + ",\nIf this is an extension, search for the user which key is " + ukey + " and edit the end date.", "Duplicate User Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
dr2.Close();
dr2.Dispose();
}
catch (MySqlException ex) //catch 2
{
MessageBox.Show("catch ukey\nCan't connect to database\n" + ex.ToString());
}
conn.Close();
conn.Dispose();
You are returning a single value from your query, so you could use directly ExecuteScalar instead of ExecuteReader. (the link point to the description for SqlServer, but it is the same for MySql)
An important question to never forget is the usage of parameters instead of string concatenation.
What happen if your myuser or mycode variables contain a single quote? You get wrong results or syntax errors.
Of course, the main problem is the Sql Injection attack to never understimate.
using(MySqlConnection conn = new MySqlConnection(MyConString))
{
ulong ukey=0;
try
{
string sql_users2 = "SELECT `key` FROM `permuser` WHERE `user` = #usr AND `code` = #code";
MySqlCommand cmdSel2 = new MySqlCommand(sql_users2, conn);
conn.Open();
cmdSel2.Parameters.AddWithValue("#usr", myuser);
cmdSel2.Parameters.AddWithValue("#code", mycode);
object result = cmdSel2.ExecuteScalar();
if(result != null)
ukey = Convert.ToUInt64(result);
}
catch (MySqlException ex) //catch 2
{
MessageBox.Show("catch ukey\nCan't connect to database\n" + ex.ToString());
}
}
also I am a bit perplexed about your usage of UInt64. What kind of datatype is stored in the key column?
way is many simply:
ukey = (uint)dr2[0];
I am creating a method to select the id from any table by passing a search field.
private int SelectId(string tabela, string campo, string valor)
{
int id = 0;
using (command = new MySqlCommand())
{
command.Connection = conn;
command.Parameters.Add("#tabela", MySqlDbType.).Value = tabela;
command.Parameters.Add("#campo", MySqlDbType.Text).Value = campo;
command.Parameters.Add("#valor", MySqlDbType.VarChar).Value = valor;
command.CommandText = "SELECT `id` FROM #tabela WHERE #campo=#valor;";
try
{
id = (int)command.ExecuteScalar();
}
catch (MySqlException ex)
{
MessageBox.Show(ex.Number + " : " + ex.Message + command.CommandText);
}
catch (Exception)
{
throw;
}
}
return id;
}
But I get an MySqlException about syntax error. When i look at the Exception message, it shows me the query with the quoted table!
How do I pass the table as parameter without quotes?
Most databases won't let you specify table or column names via parameters. Parameters are meant to be for values. If you really, really need this to be dynamic, you should validate the input (it should be a known table name, with known column names within that table) and then include that in the SQL.
I agree with Jon. Here is a sample of your code with the table name inserted directly into the script, instead of as a parameter. Notice that you'll still want to validate the table and column name to prevent SQL injection. I have not included that here, but I have put in comment stubs for you.
private int SelectId(string tabela, string campo, string valor)
{
int id = 0;
using (command = new MySqlCommand())
{
command.Connection = conn;
command.Parameters.Add("#campo", MySqlDbType.Text).Value = campo;
command.Parameters.Add("#valor", MySqlDbType.VarChar).Value = valor;
// TODO: Validate table name for parameter 'tabela' to prevent SQL injection
// TODO: Validate column name for parameter 'campo' to prevent SQL injection
command.CommandText = "SELECT `id` FROM " + tabela + " WHERE #campo=#valor;";
try
{
id = (int)command.ExecuteScalar();
}
catch (MySqlException ex)
{
MessageBox.Show(ex.Number + " : " + ex.Message + command.CommandText);
}
catch (Exception)
{
throw;
}
}
return id;
}