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.
Related
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);
}
}
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";
I try to receive a nickname from an user from the database, but it always returns the value which is assigned to the string nickname variable.
public string GetEigenaarBlog(int gebruikerid)
{
string nickname = null;
try
{
connection.Open();
string sql = "SELECT Nickname FROM Gebruiker WHERE GebruikerID = :gebruikerid";
command = new OracleCommand(sql, connection);
command.Parameters.Add(new OracleParameter("gebruikerid", gebruikerid));
nickname = Convert.ToString(command.ExecuteReader());
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
connection.Close();
}
return nickname;
}
This is my code in the form:
private void listBoxBerichten_SelectedIndexChanged(object sender, EventArgs e)
{
ListBox lb = (ListBox)sender;
Blog blog = (Blog)lb.Items[lb.SelectedIndex];
int blogid = blog.BlogID;
geselecteerdeBlog = dk.GetGeselecteerdeBlog(blogid);
string blogeigenaar;
foreach (Blog b in geselecteerdeBlog)
{
blogeigenaar = dk.GetEigenaarBlog(b.GebruikerID); //This is the method where is the problem
tbGeblogd.Text = Convert.ToString(b.Datum);
tbTitel.Text = b.Titel;
tbDoor.Text = blogeigenaar;
tbBlogInhoud.Text = b.Inhoud;
}
}
The parameter works, it reads that parameter from the form.
When I change string nickname = null to string nickname = 'hello' then it returns nickname as hello. So it returns the assigned value. When I keep string nickname = null then it returns null
What am I doing wrong? the SQL-query is right, and the user exist in the database. I'm not getting any errors or warnings.
Thanks!
Your code needs to be changed in this way
public string GetEigenaarBlog(int gebruikerid)
{
string nickname = null;
try
{
connection.Open();
string sql = "SELECT Nickname FROM Gebruiker WHERE GebruikerID = :gebruikerid";
command = new OracleCommand(sql, connection);
command.Parameters.Add(new OracleParameter("gebruikerid", gebruikerid));
OracleDataReader reader = command.ExecuteReader();
// Now try to read from the reader (and position the reader on the first record returned)
if(reader.Read())
nickname = reader[0].ToString();
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
connection.Close();
}
return nickname;
The ExecuteReader method returns an OracleDataReader and this object needs to be positioned on the first record before trying to read from it. Thus you need to call the Read method, and if that method returns true you could read the string.
Said that however, when you have a query that returns just one row and one column then a very fast approach is through the ExecuteScalar method
connection.Open();
string sql = "SELECT Nickname FROM Gebruiker WHERE GebruikerID = :gebruikerid";
command = new OracleCommand(sql, connection);
command.Parameters.Add(new OracleParameter("gebruikerid", gebruikerid));
// ExecuteScalar returns the value of the first row/first column, or null if
// there is no record to return. Need to be carefull here
object result = command.ExecuteScalar();
if(result != null)
nickname = result.ToString();
As a side note, I can't see the full code, but it seems that you keep a global connection object.
This is considered a bad and needless practice because the Connection Pooling mechanism could do a better work to keep the connection objects ready to use
You cannot access a datareader this way. You will have to loop through the datareader and get the data. See http://msdn.microsoft.com/en-us/library/system.data.oracleclient.oracledatareader.aspx for more info.
Instead of
nickname = Convert.ToString(command.ExecuteReader());
try this
OracleDataReader reader = command.ExecuteReader();
nickname = "";
while (reader.Read())
{
nickname = Convert.ToString(reader[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;
}