Hello guys i m working with a school assignment which has a simple form and database.
there is students table in database.
Problem:
This program works when i Enter stu_ID as integer which is primary key like 1234,
problem arise when i enter stu_ID as non-integer.(assignment requirement).
Like BSCS-122.it gives following exception
'System.Data.SqlClient.SqlException' {"Invalid column name 'BSCS'."}
I m working with Visual studio 2015
SQL Server 2008 R2 express.
students
stu_Id varchar(50) PK
stu_Name varchar(50)
Stu_Age int
stu_Semester int
stu_City varchar(50)
+------------+-----------------+---------+--------------+-------------+
| stu_Id | stu_Name | Stu_Age | stu_Semester | stu_City |
+------------+-----------------+---------+--------------+-------------+
| BSCS-122 | Danish Kareem | 22 | 5 | Decya |
| MBA-233 | Kamran | 23 | 5 | JPT |
| .. .... | ............... | ..... ..| ....... .....| ...... .....|
+------------+-----------------+---------+--------------+-------------+
The c# code is bellow.
private void btnInsert_Click(object sender, EventArgs e)
{
SqlConnection objSqlConnection = new SqlConnection(#"Data Source=DESKTOP-VESS66M\SQLEXPRESS;Initial Catalog=Persons;Integrated Security=True");
try
{
//
objSqlConnection.Open();
string insertCommand = "INSERT INTO students VALUES (" +stu_ID.Text+ ",'" + stu_Name.Text + "','" + Convert.ToInt32(stu_Age.Text) + "','" + Convert.ToInt32(stu_Semester.Text) + "','" + stu_City.Text + "')";
SqlCommand objSqlCommand = new SqlCommand(insertCommand, objSqlConnection);
objSqlCommand.ExecuteNonQuery();
//
this.studentsTableAdapter.Fill(this.personsDataSet.students);
//
MessageBox.Show("Student " + txtName.Text + " had been added Successfully", "Added Succefull", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception)
{
throw;
}
finally
{
objSqlConnection.Close();
}
}
Short and quick fix is to add single quotes arount stu_ID but that's prone to SQL injection: "'"+stu_ID.Text+"'"
Better way is to add parameters to your query, to prevent SQL injection:
string insertCommand = "INSERT INTO students VALUES (#stuID, #stuName, #stuAge, #stuSemester, #stuCity)";
insertCommand.Parameters.Add(new SqlParameter("stuId", stu_ID.Text));
command.Parameters.Add(new SqlParameter("stuName", stu_Name.Text));
command.Parameters.Add(new SqlParameter("stuAge", Convert.ToInt32(stu_Age.Text)));
command.Parameters.Add(new SqlParameter("stuSemester", Convert.ToInt32(stu_Semester.Text)));
command.Parameters.Add(new SqlParameter("stuCity", stu_City.Text));
Your text field value needs to be surrounded by single quotes like:
"INSERT INTO students VALUES ('" + stu_ID.Text + "')"
However, this is still an extremely bad idea as you're leaving yourself open to SQL Injection. If you aren't going to use a framework (such as Entity Framework) for your data layer, you at least need to use an SQLParameter to inject your values.
Related
the code is below and the error starting from sqlCommand cmd the 13th line of this code
private void button2_Click(object sender, EventArgs e)
{
if (StudenUsn.Text == "" )
{
MessageBox.Show("Enter The Student Number");
} else {
Con.Open();
String query = "update Student_tbl set StdName='" + StudName.Text + "',where FatherName='" + FtName.Text + "',where MotherName='" + MtName.Text + "',where StdAddress='" + Address.Text + "',where Collage ='" + Collage.Text + "'set StdRoom = " + StRmNum.SelectedValue.ToString()+",StdStatus = '"+ StudSt.SelectedItem.ToString() + "' where StdUsn ='"+StudenUsn+ "')";
SqlCommand cmd = new SqlCommand(query, Con);
cmd.ExecuteNonQuery();
MessageBox.Show("Room Successfully Updates");
Con.Close();
FillStudentDGV();
}
}
Your code should look more like:
private void button2_Click(object sender, EventArgs e)
{
if (StudenUsn.Text == "" )
{
MessageBox.Show("Enter The Student Number");
} else {
var query = #"
update Student_tbl
set
StdName=#sn,
FatherName=#fn,
MotherName=#mn,
StdAddress=#sa,
Collage=#c,
StdRoom=#sr,
StdStatus=#ss
where
StdUsn=#su";
using var con = new SqlConnection(YOUR_CONN_STR_HERE);
using var cmd = new SqlCommand(query, con);
cmd.Parameters.AddWithValue(#sn, StudName.Text);
cmd.Parameters.AddWithValue(#fn, FtName.Text);
cmd.Parameters.AddWithValue(#mn, MtName.Text);
cmd.Parameters.AddWithValue(#sa, Address.Text);
cmd.Parameters.AddWithValue(#c, Collage.Text);
cmd.Parameters.AddWithValue(#sr, StRmNum.SelectedValue);
cmd.Parameters.AddWithValue(#ss, StudSt.SelectedItem);
cmd.Parameters.AddWithValue(#su, StudenUsn);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
MessageBox.Show("Room Successfully Updates");
FillStudentDGV();
}
}
There are good reasons to avoid using AddWithValue if you use SQLServer which you can get into at a later date if you want, but it's convenient for me (who doesn't know the types and widths of your columns) dealing with the current massive elephant in the room which is your SQL is massively vulnerable to a hacking technique known as sql injection (and to a lesser extent it would blow up with an error for any student whose name included an apostrophe) - using AddWithValue might make your query slightly slower, but better that than it be the cause of the next data breach; learn how to write SQLs right, right now
Never ever take data supplied by a user and concatenate it into an SQL string. Doing so essentially, in most cases, gives the user access to your database. So many big companies whose developers should know better, put up expensive firewalls and security and then let anyone in via this back door anyway; sql injection prone systems are one of the leading causes of hacks in the world today
Always use #parameter placeholders in the SQL for user data and add a parameter to the command's parameters collection, containing the data
Now on the topic of your actual error; the pattern for an update is
update table
set col1=#param1, col2=#param2 ...
where (some conditions)
You have one where and one set. If there is some conditional aspect to your set, like you only want to update the student name/address if it is currently null then you can do like:
update table
set
name=case when name is null then #n else name end,
address=case when address is null then #a else address end
where (some conditions)
Or more simply
update table
set
name=coalesce(name, #n)
address=coalesce(address, #a)
where (some conditions)
You can't mix n match and say "where this=that where this2=that2 set this3=that3" - that's a syntax error. Where is for picking the row you want to update and set is for starting a block of commas separated columns and values the row data is to be updated to.
Strive to write your sql nicely formatted inside an #string; it's a programming language all of its own, and will be easier to debug if it's laid out nicely
Can u try with it ?
String query = "update Student_tbl set StdName='" + StudName.Text + "',StdRoom = '" + StRmNum.SelectedValue.ToString()+"',StdStatus = '"+ StudSt.SelectedItem.ToString() + "' where FatherName='" + FtName.Text + "' and MotherName='" + MtName.Text + "' and StdAddress='" + Address.Text + "' and Collage ='" + Collage.Text + "' and StdUsn ='"+StudenUsn+ "'";
I have a query versus an SQL database in C#. From this query I get a List like:
List<List<string>>()
this list can be changed to any other table type if required..
In Microsoft Server Management Studio it looks like this:
In Microsoft SQL Server Management Studio you can simply output the result as text, which looks like this:
Now as I am automating some tasks I will use C# rather than manually using MSSQL. Due to a GXP environment it is important to have every datachange in the Database Documented separately with a text report attached to a "ticket".
For now my query with Table Text generation looks like this:
SqlCommand command = new SqlCommand("SELECT '" + description + "' AS '" + description + "', CPPS_Site,Study_Id,CustNo,CPPS_Job FROM CDS.dbo.Studies " +
"WHERE Study_Id = " + studyID, con);
List<string> overview = new List<string>();
overview.Add("|=========================================================|");
overview.Add("|"+description + "\t|CPPS_Site\t|Study_ID\t|CustNo\t|CPPS_Job|");
overview.Add("|---------------------------------------------------------|");
using (SqlDataReader resultQuery = command.ExecuteReader())
{
var schemaTable = resultQuery.GetSchemaTable();
while (resultQuery.Read())
{
string build = "|";
build += resultQuery.GetSqlValue(0) + "\t|"
+ resultQuery.GetSqlValue(1) + "\t\t|"
+ resultQuery.GetSqlValue(2) + "\t\t|"
+ resultQuery.GetSqlValue(3) + "\t|"
+ resultQuery.GetSqlValue(4);
build += "|";
overview.Add(build);
}
overview.Add("|=========================================================|");
return overview;
}
Result:
while this is technically working and would also be accepted, I am personally very unpleased with this ugly solution. For instance with strings of different length, the format will not fit anymore. Do you know a more clean solution?
Composite string formatting provides an aligment component that can be used to specify a field size and align values left or right. For example
String.Format("|{0,5}",5);
will produce
| 5|
Each line can be written as :
var linePattern="|{0,-7}|{1,-17}|{2,-11}|{3,-14}|{4,-8}|";
var line= String.Format(linePattern
resultQuery.GetSqlValue(0),
resultQuery.GetSqlValue(1),
resultQuery.GetSqlValue(2),
resultQuery.GetSqlValue(3),
resultQuery.GetSqlValue(4));
The header can be written using the same pattern:
var header=String.Format(linePattern,"Before","CPPS_Site","Study_ID","CustNo","CPPS_Job");
Writing both the header and line to the console will appear like this :
|Before |CPPS_Site |Study_ID |CustNo |CPPS_Job|
|Before |1 |2 |C50030 |999 |
If the strings are larger than the field values though, they won't be truncated and the format will appear broken, eg:
|Before |CPPS_Site |Study_ID |CustNo |CPPS_Job|
|Before123 |1 |2 |C50030 |999 |
I have this query:
string query = "SELECT afspraak_locatie FROM Afspraak WHERE date(datum) = '" + datum +"'";
The final query will look like this:
SELECT afspraak_locatie FROM Afspraak WHERE date(datum) = '2016-06-16'
When i execute the query in my PHPMYADMIN it returns the row. But when i do it in C# it says my MySqldatareader is empty
Here is the code i use for that:
MySqlCommand cmd1 = new MySqlCommand(query1, connection);
cmd1.CommandType = CommandType.Text;
using (MySqlDataReader reader1 = cmd1.ExecuteReader())
{
while (reader1.Read())
{
result1.Add(reader1.GetString(0));
}
reader1.Close();
}
cmd1.Cancel();
When this gets executed it will give a System.NullreferenceException on the while(reader1.read) part. Any solutions?
Schema and data loaded:
create table Afspraak
(
id int auto_increment primary key,
afspraak_locatie varchar(100) not null, -- just an example (we don't know your datatype)
datum datetime not null -- you said it was a datetime in a comment under your question
);
insert Afspraak (afspraak_locatie,datum) values
('Rome','2016-06-14 13:55:55'),
('London','2016-06-15 15:12:12'),
('Cairo','2016-06-16 07:00:33'),
('Boston','2016-06-17 01:30:00');
select * from afspraak;
+----+------------------+---------------------+
| id | afspraak_locatie | datum |
+----+------------------+---------------------+
| 1 | Rome | 2016-06-14 13:55:55 |
| 2 | London | 2016-06-15 15:12:12 |
| 3 | Cairo | 2016-06-16 07:00:33 |
| 4 | Boston | 2016-06-17 01:30:00 |
+----+------------------+---------------------+
GUI Layer:
private void button1_Click(object sender, EventArgs e)
{
myDB.FindThatRow("2016-06-16"); // get data
}
DB Layer:
public void FindThatRow(string theDate)
{ // or all those rows
//
using (MySqlConnection lconn = new MySqlConnection(connString))
{
lconn.Open();
using (MySqlCommand cmd = new MySqlCommand())
{ //
cmd.Connection = lconn;
cmd.CommandText = #"select id,afspraak_locatie FROM Afspraak WHERE date(datum) = #pTheDate";
cmd.Prepare();
cmd.Parameters.AddWithValue("#pTheDate", theDate);
using (MySqlDataReader rs = cmd.ExecuteReader())
{ //
while (rs.Read())
{
int qId = (int)rs.GetInt32("id");
string sViewIt = rs.GetString("afspraak_locatie");
}
}
}
}
}
It found the data:
Use the using blocks as recommended by everyone. Bind your parameters.
The reasons why one should steer toward data bindings, versus string concatenation as seen in your attempt, include losing the functionality of what binding offers as seen in Configuring Parameters and Parameter Data Types and other links near or off that topic. And, it turns querying into the mess seen in PHP with concatenation which steered their modern usage toward parameter data bindings too.
Imagine how difficult and debug-intensive the following query would be without bindings:
Sql Injection Attacks:
Parameter binding protects you from such attacks, unlike your method of concat. See the following question including this answer for stored procedure usage.
I have: Crew table with every field full of data except one single field, that is, Crew_status... it represents the availability of any crew, that whether he/she is available for next flight or not.
My problem: i want to insert "unavailable" in the crew_status of that specific crew who has been allocated to some flight. To do this, i will have to use where clause inorder to figure out whether flight_name is empty or has some data. if it is empty(which means crew has not been allocated yet), I want to insert available in its crew_status field.. and if it is not empty(which means crew has been allocated to any flight), I want to insert unavailable in its crew_status field....
.
how can i do that ? I am having error
syntax error near: "='unavailable' where flight_name='fl243'"
My Module is:
public void availability(string table_name, string field_name, string where_clause1, string where_clause2, string status)
{
con.Open();
MySqlCommand cmd = new MySqlCommand();
cmd.Connection = con;
cmd.CommandType = CommandType.Text;
cmd.CommandText = "update " + table_name + "set "+field_name+"='" + status + "' where " + where_clause1+"='"+where_clause2+"'";
cmd.ExecuteNonQuery();
con.Close(); }
NOTE: table_name="crew" , field_name="crew_status" Whereclause1="flight_name" , Whereclause2="fl243" , status="unavailable"
Give a space between table_name and set
"update " + table_name + " set "+field_name+"='" + status + "' where " + where_clause1+"='"+where_clause2+"'";
I'm working with MS Access and would like to how to update the data correctly..here is the code i use on my button click event with no luck
OleDbCommand cmd = new OleDbCommand("SELECT * FROM ItemTemp WHERE ITEM='" + txtItemname.Text + "'", GetConnection());
OleDbDataReader reader = cmd.ExecuteReader();
//check if this item exist on the table ItemTemp
if (reader.HasRows == true)
{
// item exists, do below action
OleDbCommand cmde = new OleDbCommand("UPDATE ItemTemp SET QUANTITY=QUANTITY + #QUANTITY, PRICE=PRICE + #PRICE WHERE ITEM='" + txtItemname.Text + "'", GetConnection());
cmde.Parameters.AddWithValue("#QUANTITY", txtItemquantity.Value); //numericupdown control
cmde.Parameters.AddWithValue("#PRICE", txtItemprice.Text); //textbox control
cmde.ExecuteNonQuery();
}
data on database BEFORE updating:
ID | ITEM | QUANTITY | PRICE
1 | ITEM1 | 1 | 400
data on database AFTER updating:
ID | ITEM | QUANTITY | PRICE
1 | ITEM1 | 11 | 400400
data on database which i want it to be AFTER updating:
ID | ITEM | QUANTITY | PRICE
1 | ITEM1 | 2 | 800
i do believe my command is correct if not my bad..there's no other than this code on my button click event. any ideas?
First you should be sure that the database fields Quantity and Price are oo numeric type. If they are Text then your query concatenate the string values passed as parameters with the string present in the database column.
Second, when you pass the parameters with AddWithValue the framework infers the datatype for you looking at the datatype of the passed value. In your case you pass a string and and the database engine sees a string that will be concatenated to the existing value. You need to convert before passing to an appropriate datatype
Finally, use allways parametrized query for every thing you pass to the database engine, especially if the value passed comes from an input textbox.
OleDbCommand cmd = new OleDbCommand("SELECT * FROM ItemTemp WHERE ITEM=#item", GetConnection());
cmd.Parameters.AddWithValue("#item", txtItemName.Text);
OleDbDataReader reader = cmd.ExecuteReader();
//check if this item exist on the table ItemTemp
if (reader.HasRows == true)
{
OleDbCommand cmde = new OleDbCommand("UPDATE ItemTemp SET QUANTITY=QUANTITY + #QUANTITY," +
"PRICE=PRICE + #PRICE WHERE ITEM=#item, GetConnection());
cmde.Parameters.AddWithValue("#QUANTITY", Convert.ToInt32(txtItemquantity.Value));
cmde.Parameters.AddWithValue("#PRICE", Convert.ToDecimal(txtItemprice.Text));
cmde.Parameters.AddWithValue("#item", txtItemName.Text);
cmde.ExecuteNonQuery();
}
ok, its seem to be done now. i just change
cmde.Parameters.AddWithValue("#QUANTITY", txtItemquantity.Value); //numericupdown control
cmde.Parameters.AddWithValue("#PRICE", txtItemprice.Text); //textbox control
to this
cmde.Parameters.AddWithValue("#QUANTITY", Convert.ToInt32(txtItemquantity.Value));
cmde.Parameters.AddWithValue("#PRICE", Convert.ToInt32(txtItemprice.Text));