Suppose I this method from my MySQLOperations class:
public bool checkIfRowExists(string tableName, string columnToLookIn, string dataToLookFor)
{
string myConnectionString = "Server = " + server + "; Database = " + dbName + "; UID = " + user + "; Password = " + password + ";";
int isExisting = 0;
using (MySqlConnection myConnection = new MySqlConnection(myConnectionString))
{
using (MySqlCommand myCommand = new MySqlCommand("SELECT EXISTS (SELECT 1 FROM #tablename WHERE #columnname = #data);", myConnection))
{
myCommand.Parameters.AddWithValue("#tablename", tableName);
myCommand.Parameters.AddWithValue("#columnname", columnToLookIn);
myCommand.Parameters.AddWithValue("#data", dataToLookFor);
try
{
myConnection.Open();
isExisting = (int)myCommand.ExecuteScalar();
myConnection.Close();
}
catch (Exception ex)
{
myConnection.Close();
MessageBox.Show(ex.Message, "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
return (isExisting == 1);
}
}
}
And in another class, I created a MySQLOperations object.
I called on this method within an if statement: if(objSQLOperations.checkIfRowExists("tblInventory", "ItemID", txtItemID.Text)). Let us assume that txtItemID contains a valid 10-digit number. And that in my database, I have a table named tblInventory with a column ItemID.
My problem is that the statements within my catch block executes, saying there was an error with my SQL syntax. "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''tblInventory' WHERE 'ItemID' = '11111111111'' at line 1." is popped at a MessageBox when my txtItemID contains the text "1111111111".
I believe my SELECT EXISTS statement is correct.
No you can't use parameters for table or column names. You'll have to build up the SQL string dynamically by concatenation.
Like:
var sql = "SELECT EXISTS(SELECT 1 FROM " + tablename +
" WHERE " + columnNameToLookIn + " = #data);"
using (MySqlCommand myCommand = new MySqlCommand(sql, myConnection))
This of course opens you up to SQL injection if tableName and columnNameToLookIn can be user entered. However if the tableName and columnNameToLookIn are only set in code as it appears in your example then it is not a problem.
Related:
use a variable for table name in mysql sproc
Dynamic table names in stored procedure function
Related
I am trying to update a column contains below value:
\\localhost\db\kkk\086018\ss\DocA\1_216925.jpg
with
\\localhost\db\kkk\086018\dd\DocA\1_216925.jpg
by using below C# code:
string str = "update my_document " +
"set path = replace (path,'" + fromFolder + "','" + toFolder + "')" +
"where doc_id in( select doc_id from patient_document where folder_id='" + id + "')";
str.Replace("\\", "\\\\");
Console.WriteLine(str);
using (MySqlConnection conn = new MySqlConnection(ECModel.Instance.ConnString))
{
using (MySqlCommand cmd = new MySqlCommand(str, conn))
{
try
{
conn.Open();
cmd.ExecuteNonQuery();
}
}
what I observe that path submitting correctly to mysql but it wont reflect since between C# application and mysql, all the \\ convert to \ .
Would you mind advice me how to solve my issue?
I used # in front of my str also but that solution also didn't work.
** also I notice when I run my update statement with \\\\ it is working fine.
To try to keep this simple, I think the problem you're having is you effectively need both the "#" and the escape values. Try something like this. It worked for me. I made some assumptions on the data structures, and tested this on SQL Server, not MySQL, but I think the concept is sound and I reverted the code back to the MySQL client for you.
class Program
{
static void Main(string[] args)
{
Program program = new Program();
program.updateTable("1", #"\\share\from\path", #"\\share\to\path");
Console.ReadLine();
}
private void updateTable(string id, string fromFolder, string toFolder)
{
string str = #"update my_document " +
"set path = replace (path,'" + fromFolder + "','" + toFolder + "')" +
"where doc_id in( select doc_id from patient_document where folder_id='" + id + "')";
str.Replace("\\", "\\\\");
Console.WriteLine(str);
using (MySqlConnection conn = new MySqlConnection(ECModel.Instance.ConnString))
{
using (MySqlCommand cmd = new MySqlCommand(str, conn))
{
try
{
conn.Open();
cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
}
I'm a student programmer and I'm writing this software for a small school, it's my first program, the code below is giving me the error
syntax error in insert into statement
I know the connection string is not the problem because I use it for inserting into two other tables with the same insert into format.
I am using an access database.
The offending code is
connection.Open();
OleDbCommand command = new OleDbCommand();
command.Connection = connection;
command.CommandText = "insert into studentBillRecords (StudentName, Department, Level, AccomodationStatus, SemesterBill, PreviousBalance, TotalBill) values ('"+ txtSRstudentName.Text + "', '" + cmbSRDepartment.Text + "', '" + cmbSRLevel.Text + "', '" + cmbSRAccomodationStatus.Text + "', '" + txtSRSemesterBill.Text + "', '" + txtSRPreviousBalance.Text + "', '" + txtSRTotalBill.Text + "')";
MessageBox.Show(command.CommandText);
command.ExecuteNonQuery();
connection.Close();
This same code with different table names, column names and input works with another table in the same database but won't work with this one.
Level is a reserved keyword in access.
Also use Parameters instead of concatinating string. Try this code out, it makes it safer and easier to read:
Note: I changed the name of the column Level to StudentLevel which, I assume, doesn't exist yet in your table.
try
{
using (OleDbConnection connection = new OleDbConnection("my connection string"))
{
//Open connection
connection.Open();
//Create new command
OleDbCommand cmd = new OleDbCommand();
cmd.Connection = connection;
//Create command text
cmd.CommandText =
"INSERT INTO studentBillRecords " +
"(StudentName, Department, StudentLevel, AccomodationStatus, SemesterBill, PreviousBalance, TotalBill) VALUES " +
"(#StudentName, #Department, #StudentLevel, #AccomodationStatus, #SemesterBill, #PreviousBalance, #TotalBill)";
// Add names paremeters
cmd.Parameters.AddRange(new OleDbParameter[]
{
new OleDbParameter("#StudentName", txtSRstudentName.Text),
new OleDbParameter("#Department", cmbSRDepartment.Text),
new OleDbParameter("#StudentLevel", cmbSRLevel.Text),
new OleDbParameter("#AccomodationStatus", cmbSRAccomodationStatus.Text),
new OleDbParameter("#SemesterBill", txtSRSemesterBill.Text),
new OleDbParameter("#PreviousBalance", txtSRPreviousBalance.Text),
new OleDbParameter("#TotalBill", txtSRTotalBill.Text)
});
//Execute Query
cmd.ExecuteNonQuery();
//No need to close because we are using "using"
}
}
catch (OleDbException ex)
{
//If an exception occurs let's print it out to console
Console.WriteLine("ERROR: " + ex.ToString());
throw;
}
For information on how to change the column name read this:
https://msdn.microsoft.com/en-us/library/bb177883(v=office.12).aspx
"Level" is a keyword in MS Access, may be that is why this issue occurs try quoting it like [Level]
List Of MS Access Keywords
I have faced a problem to update a row in SQL Serve 2008 via C#. NET application.
During runtime, the application tries to update the database but with no success. However, there is no exception, error, NOTHING. Checking the SQL Profile, the update command was sent, but not committed.
If I run the application debugging it step-by-step (via 'F11') the row is updated successfully (!?!?!?!?!)
I have copied the SQL update command and ran it on SQL Management Studio and also worked fine.
General Information:
- The only problem is in runtime mode.
- The user used is 'sa' with all granted permission
- I have ran the SAME METHODS for other tables (the only thing that changes is the table name) and it works fine.
The method responsible for it is:
public void Save(FormaResult obj)
{
try
{
bool insert = GetById(obj.SLABID) == null;
IList<string> colResult = GetColumns(TABLE);
List<string> colList = colResult.Where(TableColumns.Contains).ToList();
if (insert)
{
string col = string.Join(",", colList.Select(i => i).ToArray());
string colParam = string.Join(", ", colList.Select(i => "#" + i).ToArray());
QueryString = "INSERT INTO " + TABLE + " (" + col + ") VALUES(" + colParam + ");";
}
else
{
string colSet = string.Join(", ", colList.Select(i => i + " = #" + i).ToArray());
QueryString = "UPDATE " + TABLE + " SET " + colSet + " WHERE SLABID = #Id1;";
}
DbCommand = Conn.CreateCommand();
DbCommand.Connection = Conn;
DbCommand.CommandText = QueryString;
ListDbParameters = new List<DbParameter>
{
this.CriarParametro<DateTime>("GT_TIME", obj.GT_TIME),
this.CriarParametro<long?>("SLABID", obj.SLABID),
this.CriarParametro<short?>("STATUS", obj.STATUS)
};
if (!insert)
{
ListDbParameters.Add(this.CriarParametro<long>("Id1", obj.SLABID));
}
foreach (DbParameter param in ListDbParameters)
{
DbCommand.Parameters.Add(param);
}
Conn.Open();
DbCommand.ExecuteNonQuery();
}
catch (Exception ex)
{
TrkCGManagedModuleService.Logger.Error(ex.Message);
throw;
}
finally
{
Conn.Close();
}
}
I have also used this method:
public void OkEvt()
{
try
{
this.QueryString = "UPDATE " + TABLE + " SET STATUS = 1 " +
"FROM (SELECT TOP(1) * FROM " + TABLE + " WHERE STATUS=0 ORDER BY GT_TIME ASC) I " +
"WHERE " + TABLE + ".SLABID = I.SLABID AND " + TABLE + ".STATUS=0 AND " + TABLE + ".GT_TIME = I.GT_TIME;";
this.DbCommand = this.Conn.CreateCommand();
this.DbCommand.Connection = this.Conn;
this.DbCommand.CommandText = this.QueryString;
this.Conn.Open();
this.DbCommand.ExecuteNonQuery();
}
catch (Exception ex)
{
TrkCGManagedModuleService.Logger.Error(ex.Message);
throw;
}
finally
{
this.Conn.Close();
}
}
Both methods have the same aim, update the column 'STATUS' to '1'.
I would say the same thing as Soner Gonul about the SQL injection. I understand what your trying to do, but from my experience your leaving open a security door that is easily closed. Just requires a bit more time writing your CRUD statements for each table.
Here is a code sample that I use for my update queries you might find useful. If you are going to use this method, remember to create a user that has deny reader and deny writer. Then run a command to grant them execute permissions on all stored procedures.
this.o_ConnectionString is a private variable set inside my class constructor since i put my data layer in a separate project than my web applications.
public int UpdateThisTable(int TableUID, string SomeField)
{
string StoredProcedure = "usp_SomeStoredProcedure";
SqlConnection conn = new SqlConnection(enteryourconnectionstring);
SqlCommand cmd = new SqlCommand(StoredProcedure, conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#TableUID", TableUID);
cmd.Parameters.AddWithValue("#SomeField", SomeField);
conn.Open();
int rowsaffected = cmd.ExecuteNonQuery();
conn.Close();
return rowsaffected;
}
I m using the following function to create an access table:
public static void createtable(string path, string tablename, string[] columnnames)
{
try
{
string connectionstring = creadteconnectionstring(path);
OleDbConnection myConnection = new OleDbConnection(connectionstring);
myConnection.Open();
OleDbCommand myCommand = new OleDbCommand();
myCommand.Connection = myConnection;
string columnam = "[" + columnnames[0] + "] Text";
for (int i = 1; i < columnnames.Length; i++)
{
columnam = columnam + ", [" + columnnames[i] + "] Text";
}
myCommand.CommandText = "CREATE TABLE [" + tablename + "](" + columnam + ")";
myCommand.ExecuteNonQuery();
myCommand.Connection.Close();
Console.WriteLine("Access table " + tablename + " created.");
}
catch
{
Console.WriteLine("Access table " + tablename + " already exists.");
return;
}
}
However if I open the access table in MS access the data type is Memo, not Text. Other data types link specified by MS dont seem to work at all.
Any ideas are welcome? Thanks!
The Access DDL TEXT data type behaves differently depending on the context where you execute your statement.
From DAO in Access, this creates bar as a text field. But from ADO in Access, bar will be memo type.
CREATE TABLE tblFoo (bar TEXT)
Executing that statement from an OleDb connection produces the same result as with ADO in Access.
If you want bar to be an actual text field, include a field length <= 255.
CREATE TABLE tblFoo (bar TEXT(255))
I am using VS2005 C# and SQL Server 2005.
I have a a few SQL queries which I am converting them from using parameters instead concatenations for SQL injection prevention.
Below is a SELECT query which is parameter-ed:
string loggedinuser = (User.Identity.Name);
SqlDataSource1.SelectCommand = "SELECT * FROM [UserTable] where [" + DropDownList1.Text + "] like #searchtb AND [LoggedInUser] LIKE #userlog";
SqlDataSource1.SelectParameters.Add("searchtb", "%" + searchTB.Text + "%");
SqlDataSource1.SelectParameters.Add("userlog", "%" + loggedinuser+ "%");
The above sql query searches for records base on the user's input in a search textbox and return results which matches the search input and username in the database.
I have another SQL query which is also a SELECT statement. However, this time it does not use SqlDataSource, but using cmd instead. Thus I need some help in converting the SQL statement below to parameter form:
string loggedinuser = (User.Identity.Name);
string stmt = "SET ROWCOUNT 1 SELECT COUNT(*) FROM MP.dbo.UserTable where [" + DropDownList1.Text + "] like '%" + searchTB.Text + "%' AND [LoggedInUser] LIKE '%"+loggedinuser +"%'";
int count = 0;
using (SqlCommand cmdCount = new SqlCommand(stmt, thisConnection))
{
thisConnection.Open();
count = (int)cmdCount.ExecuteScalar();
thisConnection.Close();
}
This SQL query searches for number of records that the user is trying to search base on his search input and username. And if countuser returns a 0 value, I will prompt the user after that.
I need help in converting the 2nd SQL statement into parameter form.
Thank you.
Try,
string stmt = "SELECT COUNT(*) FROM MP.dbo.UserTable where [" + DropDownList1.Text + "]
like #searchTb AND [LoggedInUser] LIKE #loggedinuser";
int count = 0;
using (SqlCommand cmdCount = new SqlCommand(stmt, thisConnection))
{
cmdCount.Parameters.Add("#searchTb",SqlDbType.VarChar,40).Value="%" + searchTB.Text + "%";
cmdCount.Parameters.Add("#loggedinuser",SqlDbType.VarChar,40).Value="%" + loggedinuser + "%";
thisConnection.Open();
count = (int)cmdCount.ExecuteScalar();
thisConnection.Close();
}
Using stored procedures is your best bet, but if you cannot use them, this code should work:
SqlDataAdapter myCommand = new SqlDataAdapter(
"SELECT au_lname, au_fname FROM Authors WHERE au_id = #au_id", conn);
SQLParameter parm = myCommand.SelectCommand.Parameters.Add("#au_id",
SqlDbType.VarChar, 11);
Parm.Value = Login.Text;
This is from the MSDN article on SQL injection.
http://msdn.microsoft.com/en-us/library/ms161953.aspx