Can someone let me know what is wrong with my SQL Statement and how I can improve it?
da = new SqlDataAdapter("SELECT * FROM Guests"+" WHERE Students.name='" +
byNametextBox.Text + "'", MyConn);
An EXISTS predicate is slightly more efficient than a JOIN if you want only columns from one of the tables. Additionaly - never inject strings into SQL statements like that - you're just begging for SQL Injection attacks, or related crashes errors (Yes, I know it's a Forms application, but the same holds true. If you're searching for a name like "O'Leary", you'll get a crash).
SqlCommand cmd = new SqlCommand("SELECT * FROM Guests WHERE EXISTS (SELECT Id FROM Students WHERE Guests.StudentId = Students.Id And Students.name= #name)", MyConn);
cmd.Parameters.Add("#name", SqlDbType.VarChar, 50).Value = byNametextBox.Text;
SqlDataAdapter adapt = new SqlDataAdapter(cmd);
Note: Some people may argue that "SELECT *" is bad, and that you should consider specifying individual column names
You need to worry about SQL Injection. Put simply, SQL Injection is when a user is able to put arbitrary SQL statements into your query. To get around this, either use a Stored Procedure or a Parametrized SQL Query. An Example of a Parametrized SQL query is below:
SqlConnection conn = null;
SqlDataReader reader = null;
//Connection string goes here
string studentName = byNametextBox.Text;
SqlCommand cmd = new SqlCommand(
"SELECT * FROM Guests "+" WHERE Students.name = #name", conn);
SqlParameter param = new SqlParameter("#name", SqlDbType.NVarChar, 50);
param.Value = studentName;
cmd.Parameters.Add(param);
reader = cmd.ExecuteReader();
//Do stuff with reader here
SqlDataAdapter("SELECT Guests.* FROM Guests,Students WHERE Guest.StudentId = Student.Id and Students.name='" + byNametextBox.Text + "'", MyConn);`
You need an Inner Join. I think it would be something like this:
SELECT Guests.* FROM Guests INNER JOIN Students ON Students.name = Guests.name WHERE Students.name = '" + byNametextBox.Text + "'"
Try it:
"SELECT g.*
FROM Guests g
INNER JOIN Students s ON g.StudentId = s.StudentId
WHERE Students.Name = '" + byNametextBox.Text + '"'
Assuming that the field wich relates both tables is StudentId.
Beware that SQL is not the same between different Servers. This statement will work on Sql Server, I don't know in others. Also, beware that you aren't protecting yourself on SQL Injection attacks. You should perform your query with parameters, instead of concatenating strings in the way you are doing it.
This is a simple query that you should know by yourself. You can search for tutorials on Google, but here is a generic introduction.
Related
I have an sql query that I need change to parameters so I can avoid sql injection.
adapter.SelectCommand.CommandText = #"SELECT c.*,(Select Initials FROM users WHERE User_ID = c.CreatedByUser) AS CreatedBy, (SELECT Initials FROM users WHERE User_ID = c.ModifiedByUser) AS ModifiedBy FROM currency c WHERE c.Company_ID = " + Company_ID + " AND c.CurrencyCode = '" + Code.Replace("'", "''") + "' ORDER BY c.Description
adapter.SelectCommand.Parameters.Add(new MySqlParameter("company_ID", Company_ID));
adapter.SelectCommand.Parameters.Add(new MySqlParameter("code", Code));
I know for Company_ID I need to change it to WHERE c.Company_ID = ?company_ID but I am not sure what to do for c.CurrencyCode = '" + Code.Replace("'", "''") + "'
I just don't know how to change the Code.Replace part, since its not a simple as company_ID
As per here
Try using (for odbc for example):
cmd.Parameters.Add("?CURRENCY", OdbcType.VarChar, Code.Replace("'", "''"))
Odbc approach
OdbcCommand cmd = sql.CreateCommand();
cmd.CommandText = "SELECT UNIQUE_ID FROM userdetails WHERE USER_ID IN (?, ?)";
cmd.Parameters.Add("?ID1", OdbcType.VarChar, 250).Value = email1;
cmd.Parameters.Add("?ID2", OdbcType.VarChar, 250).Value = email2;
For oracle:
//create SQL and insert parameters
OracleCommand cmd = new OracleCommand("insert into daily_cdr_logs (message) values (:_message)", con);
cmd.Parameters.Add(new OracleParameter("_message", msg));
For mysql:
cmd = new MySqlCommand("SELECT * FROM admin WHERE admin_username=#val1 AND admin_password=PASSWORD(#val2)", MySqlConn.conn);
cmd.Parameters.AddWithValue("#val1", tboxUserName.Text);
cmd.Parameters.AddWithValue("#val2", tboxPassword.Text);
cmd.Prepare();
So a parameterized query (to me at least) generally means that you have created a stored procedure on your database and then use your code to execute the stored procedure while passing in the relevant parameters.
This has a couple of benefits
DRY - you don't have to repeat the query in code, you can just call the execute method and pass in the appropriate parameters
Helps prevent SQL injection - You can only modify the parameters which hopefully will be sanitized before being passed to the query
Here is how to create a stored procedure according to MSDN
and
Here is how to execute a a stored procedure according to MSDN
If you are determined to do it via LINQ, MSDN has what you are looking for here
EDIT: It seems you are concerned about sql-injection (which is good!), here is an article (again from MSDN) that covers that topic pretty extensively
I have the answer. c.CurrencyCode = '" + Code.Replace("'", "''") + "' simply changes to c.CurrencyCode = ?code
Can anyone tell whats wrong with my code? I have tried a million different things and I cant seem to make it work. I need to make a select in my mysql database and use the id from the table with the specified name I take from a combobox.
I took that name from the combobox and put it into a variable named "nomeres", now I need to do a select with it and take the id from that name from the database. Everything I try to do results in a mysql syntax error in line 1, but I've tried alot of things and its always the same. The database is fine, I tried the select directly from it myself, no tables or columns names are incorrect. This is the code im using:
MySql.Data.MySqlClient.MySqlConnection dbConn = new MySql.Data.MySqlClient.MySqlConnection("Persist Security Info=False;server=localhost;database=notas;uid=root;password=" + dbpwd);
MySqlCommand cmd = dbConn.CreateCommand();
cmd.CommandText = "SELECT id from residentes WHERE nome ='" + nomeres;
try
{
dbConn.Open();
} catch (Exception erro) {
MessageBox.Show("Erro" + erro);
this.Close();
}
MySqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
idnumber = reader.ToString();
}
as others have already pointed you towards right direction,
i would like to suggest you to use parameterised queries to avoid SQL injection attacks.
Your query is open to SQL injection attacks so please read here
Try This: using parameterised SQL queries
cmd.CommandText = "SELECT id from residentes WHERE nome = #nome";
cmd.Parameters.AddWithValue("#nome",nomeres);
You need to terminate the string in the query:
"SELECT id from residentes WHERE nome ='" + nomeres + "'"
In general, when trying to debug this type of code, it helps to print out the query string after all substitutions have been made.
cmd.CommandText = "SELECT id from residentes WHERE nome ='" + nomeres + "';";
actually you misses the semicolon of the query that have to enter within the quotes. and the second semicolon is for the end of statement.
But I preffer wo write commands like
cmd.CommandText = "SELECT id from residentes WHERE nome = #nome";
cmd.Parameters.AddWithValues("#nome", variableName);
then execute the query and retrieve your results.
Missing single quote:
"SELECT id from residentes WHERE nome ='" + nomeres + "'";
^
What's the safest way of generating SQL queries in C#, including cleansing user input so it's safe from injection? I'm looking to use a simple solution that doesn't need external libraries.
Use Sql Parameters:
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlparameter(v=vs.80).aspx
Here's an example in C#
SqlCommand tCommand = new SqlCommand();
tCommand.Connection = new SqlConnection("YourConnectionString");
tCommand.CommandText = "UPDATE players SET name = #name, score = #score, active = #active WHERE jerseyNum = #jerseyNum";
tCommand.Parameters.Add(new SqlParameter("#name", System.Data.SqlDbType.VarChar).Value = "Smith, Steve");
tCommand.Parameters.Add(new SqlParameter("#score", System.Data.SqlDbType.Int).Value = "42");
tCommand.Parameters.Add(new SqlParameter("#active", System.Data.SqlDbType.Bit).Value = true);
tCommand.Parameters.Add(new SqlParameter("#jerseyNum", System.Data.SqlDbType.Int).Value = "99");
tCommand.ExecuteNonQuery();
In essence don't do this
SqlCommand command = new SqlCommand(MyConnection);
command.CommandText = "Select * From MyTable Where MyColumn = '" + TextBox1.Text + "'"
...
do
SqlCommand command = new SqlCommand(MyConnection);
command.CommandText = "Select * From MyTable Where MyColumn = #MyValue";
command.Parameters.AddWithValue("MyValue",TextBox1.Text);
...
Basically never build your sql command directly from user input.
If you use an ORM, such as EntityFrameworks / POCO all queries are done in the latter form.
The first rule of thumb is to make sure you use parameterized queries/commands. Basically don't dynamically build a sql string that includes something that the user has input into the page.
If you use on ORM (EF, L2S, Nhib), this is typically handled in most cases because most all of them run parameterized queries.
Parametrize your queries.
In case if you build some TSQL which builds some other dynamic TSQL - then use some described technique
What does "parametrizing means?
See, not use something like this:
sqlCommand.CommandText = "select * from mytable where id = "+someVariable;
use this:
sqlCommand.CommandText = "select * from mytable where id = #id";
sqlCommand.Parameters.AddWithValue("#id", someVariable);
Make use of Parametrized Queries.
Simple Example.
var sql = "SELECT * FROM MyTable WHERE MyColumn = #Param1";
using (var connection = new SqlConnection("..."))
using (var command = new SqlCommand(sql, connection))
{
command.Parameters.AddWithValue("#Param1", param1Value);
return command.ExecuteReader();
}
More Detailed Example.
protected void btnGoodAddShipper_Click(object sender, EventArgs e)
{
string connStr = c
"Server=(local);Database=Northwind;Integrated Security=SSPI";
// this is good because all input becomes a
// parameter and not part of the SQL statement
string cmdStr =
"insert into Shippers (CompanyName, Phone) values (" +
"#CompanyName, #Phone)";
using (SqlConnection conn = new SqlConnection(connStr))
using (SqlCommand cmd = new SqlCommand(cmdStr, conn))
{
// add parameters
cmd.Parameters.AddWithValue
("#CompanyName", txtCompanyName.Text);
cmd.Parameters.AddWithValue("#Phone", txtPhone.Text);
conn.Open();
cmd.ExecuteNonQuery();
}
}
Using DBML and LINQ to handle it for you. Many people have worked on those to ensure those issues are well mitigated.
And if not than at least parametrize your queries.
A proper name for DBML is linq2sql or an advanced version is called entity framework. These technologies are provided by Microsoft and well integrated with visual studio. Does not require additional libraries.
Pretty stable products..
ok thanks alot for all who help me ,but now i have another problem i want to get this statement correct also
if (byNametextBox.Text != null && byBuildingtextBox.Text !=null && seTextBoxPublic1.Text == null)
{
da = new SqlDataAdapter("SELECT * FROM Students WHERE name='" + byNametextBox.Text +"and [buil-id]='"+byBuildingtextBox.Text+ "'", MyConn);
}
i want to select from the same table with two condition
please
Please use parameters! If for some reason you're against them, this should work:
string strStatement = String.Format("SELECT * FROM Students WHERE [name] = '{0}' AND [buil-id] = '{1}'", byNametextBox.Text, byBuildingtextBox.Text);
da = new SqlDataAdapter(strStatement, MyConn);
Better for security if you use parameters in your SQL query.
I suppose you should create an SqlCommand with 2 parameters.
The code you posted here is not safe for SQL Injection attacks.
Please follow:
http://msdn.microsoft.com/en-us/library/ms161953.aspx
To answer your question, however, your code creates the SQL:
SELECT * FROM Students WHERE name='NAMEand [buil-id]='ID'
should be
SELECT * FROM Students WHERE name='NAME' and [buil-id]='ID'
Use parameterized query to prevent sql injection, also here some additional codes if you want to populate datatable.
SqlDataAdapter da = new SqlDataAdapter("SELECT * FROM Students WHERE name = #byName and [buil-id]= #byBuilding " , MyConn)
DataTable dt= new DataTable();
da.SelectCommand.Parameters.AddWithValue("#byName", byNametextBox.Text);
da.SelectCommand.Parameters.AddWithValue("#byBuilding", byBuildingtextBox.Text);
da.Fill(dt);
I'm creating an assembly in C# for MS SQL 2005. This assembly creates a stored procedure and runs a dynamic query based on parameters passed into the stored procedure.
Is there a simple function in C# to prevent SQL injection?
For example
string myQuery = "SELECT * FROM dbo.MyTable WHERE lastName = '" + injectionCheck(arg1) + "'";
This question was answered for the standard query... but in situations where there is no way around building a truely dynamic query what can I use in C# for injection checking?
For example, these probably wont work:
using #dbName;
SELECT * FROM #table
OPEN SYMMETRIC KEY #keyName
etc
Use bound parameters:
SqlCommand cmd = new SqlCommand(myQuery, conn);
cmd.Parameters.Add("#lastname", SqlDbType.NVarChar, 10, lastName);
Use parameters ....
(This has been posted often already)
string myQuery = "SELECT * FROM myTable WHERE lastname = #p_name";
SqlCommand cmd = new SqlCommand();
cmd.CommandText = myQuery;
cmd.Parameters.Add ("#p_name", SqlDbType.Varchar).Value = "melp";