How to insert values into SQL field with a key connection - c#

I've got a table called Devices
Devices has a key field called Names.
As well there are fields; DeviceIP, DoesBackup, DeviceType, and LastBackup
Field LastBackup currently has no knowledge of a devices last backup, the app I am writing will SSH the FTP to find that information.
Now I'm using splits and arrays to break the SSH responses into device name and lastbackup, turning them each into a variable.
Now I need to insert LastBackup into the empty field in my SQL while maintaining pairing to each device based on it's key Name.
I am not sure how to accomplish this as I've read you cannot use a WHERE clause with INSERT.

To insert or update a record (insert if not exists, update if exists) you need a query like this.
First you build the connection object and the command object, then set the commandtext to an sql insert operation with the clause that if the record with the primary key exists (the device name) you want an update instead of an insert.
Finally you add the parameters required by the command (the #xxxx strings) and call ExecuteNonQuery.
using(MySqlConnection cnn = new MySqlConnection(..put a connstring here...))
using(MySqlCommand cmd = cnn.CreateCommand())
{
cnn.Open();
cmd.CommandText = #"INSERT INTO devices
(Names, DeviceIP, DoesBackup, DeviceType, LastBackup)
VALUES (#name, #ip, #backs, #type, #last)
ON DUPLICATE KEY UPDATE LastBackup=#last";
cmd.Parameters.AddWithValue("#name", variableWithDeviceNameValue);
cmd.Parameters.AddWithValue("#ip", variableWithIPValue);
cmd.Parameters.AddWithValue("#backs", variableWithDoesBackupValue);
cmd.Parameters.AddWithValue("#type", variableWithDeviceTypeValue);
cmd.Parameters.AddWithValue("#last", variableWithLastBackupValue);
cmd.ExecuteNonQuery();
}

Related

What's causing this syntax error? oledb INSERT statement

I posted about a different issue I had earlier, and with some help resolved that.
I am now receiving a syntax error centered around the following code:
importConnection.Open();
Console.WriteLine("Foxpro connection open");
OleDbCommand deleteOleDbCommand = new OleDbCommand(#"TRUNCATE TABLE CLIENT",
importConnection);
Console.WriteLine("writing to table");
Console.ReadKey();
using (OleDbCommand importCommand = new OleDbCommand(
string.Format("INSERT INTO CLIENT (Title,Fname,Sname)" + "VALUES ({0},{1},{2})",
exportReader.GetValue(0), exportReader.GetValue(1), exportReader.GetValue(2))))
importCommand.ExecuteReader();
With this being the output:
Output Text
using break points I have determined that the export reader calls are receiving data. I've narrowed it down to an issue with:
"VALUES ({0},{1},{2})",
exportReader.GetValue(0), exportReader.GetValue(1), exportReader.GetValue(2))))
I have confirmed that data can be inserted by doing the following:
using (OleDbCommand importCommand =
new OleDbCommand(string.Format(
"INSERT INTO CLIENT (Title,Fname,Sname)" + "VALUES (Mr,Joshua,Cameron-Mackintosh)",
importConnection)))
This causes no problems, so I know the issue does not lie with the underlying connection or command.
Others correctly comment about SQL-Injection, however VFP is less impacted to SQL-Injection, it can be just the same. Main reason, VFP doesn't really work with multiple queries the same way other sql engines allow by a ";" identifying break between statements. However, with mismatched quotes, it CAN and WILL break your sql-statements from actually running.
Having said that, VFP OleDb provider does allow parameterizing, but does so without "named" parameters. It does it with "?" as a place-holder for where the value would be inserted by the .net framework, and you don't have to convert the data type as long as it is in the same expected format (ex: string, numeric, date)
change your OleDbCommand to
"INSERT INTO CLIENT (Title, Fname, Sname ) values ( ?, ?, ? )"
Then, set your parameters via
importCommand.Parameters.Add( "parmForTitle", exportReader.GetValue(0));
importCommand.Parameters.Add( "parmForFName", exportReader.GetValue(1));
importCommand.Parameters.Add( "parmForSName", exportReader.GetValue(2));
Also, the parameters must be added in the exact same sequential order as they appear in the query. So, I prefixed them with "parmFor" to indicate it is the parameter placement for the corresponding field being inserted (or updated, or used in select, insert or delete too). The command objects work the same for all the commands. Even if you write a select statement and have values in a WHERE, JOIN or whatever other position.
THEN, ExecuteNonQuery()
It is saying "foxpro connection string" there. If it is done against
a VFP database, then "Truncate table client" wouldn't work in the
first place. That command does not exist in VFP. Instead you could
try using "Delete From Client" which marks the records for deletion.
Or you can use "zap" command with ExecSript that would correspond to
"truncate table" but then the connection needs to use the table
exclusively.
You should quote the string values. Better yet, for any SQL operation you should use parameters. When you use parameters, you should do that in a correct way for the connection you use. Here you are using an OLEDB connection, then you should use ? as a parameter place holder.
A revised version of your code would then be:
importConnection.Open();
Console.WriteLine("Foxpro connection open");
OleDbCommand deleteOleDbCommand = new OleDbCommand(#"Delete from CLIENT",
importConnection);
Console.WriteLine("writing to table");
Console.ReadKey();
using (OleDbCommand importCommand = new OleDbCommand(
#"INSERT INTO CLIENT (Title,Fname,Sname) VALUES (?,?,?)",
importConnection))
{
importCommand.Parameters.AddWithValue("title","");
importCommand.Parameters.AddWithValue("fname","");
importCommand.Parameters.AddWithValue("sname","");
// maybe in a loop here
importCommand.Parameters["title"].Value = exportReader.GetValue(0);
importCommand.Parameters["fname"].Value = exportReader.GetValue(1);
importCommand.Parameters["sname"].Value = exportReader.GetValue(2);
importCommand.ExecuteNonQuery();
// ...
}
PS: You could directly feed the values on the Parameters.AddWithValue instead of creating a separate .Parameters["..."].Value = ... but then you would only be able to do that for a single insertion (not something related to VFP, it is the case for OleDb or Sql or whatever).
You don't need ExecuteReader for an insert statement. Just use ExecuteNonQuery.
In your case, if your columns are character typed, you need to use single quotes with them for example;
VALUES ('{0}', '{1}', '{2}')
Also use white space (not have to but as a good practice) before VALUES part.
"INSERT INTO CLIENT (Title,Fname,Sname)" + " VALUES (Mr,Joshua,Cameron-Mackintosh)",
// ^^^ here
But more important;
You should always use parameterized queries. Prepared statements automatically handle for escape characters for example and this kind of string concatenations are open for SQL Injection attacks.
You must give space to your concatenated strings.
"INSERT INTO CLIENT (Title,Fname,Sname)" + "[space here]VALUES (Mr,Joshua,Cameron-Mackintosh)"
however, it should look like this:
"INSERT INTO CLIENT (Title,Fname,Sname) VALUES (?,?,?)"
Always make use of parametrized queries. Please refer to:
http://blogs.technet.com/b/neilcar/archive/2008/05/21/sql-injection-mitigation-using-parameterized-queries.aspx

update SQL and get error

hi i have many problem with update sql database from c# form
fisrt: i use this code for a button called "Update" that get values directly from text boxes and fill main sql server database.
SqlConnection cnt = new SqlConnection("Data Source=.;Initial Catalog=db3;Integrated Security=True");
SqlCommand cmd = new SqlCommand("update phone set name=#name,lastname=#lastname,Phone=#Phone,Mobile=#Mobile,Area=#Area,date=#date", cnt);
cnt.Open();
cmd.Parameters.AddWithValue("#name", namebox.Text);
cmd.Parameters.AddWithValue("#lastname", lastbox.Text);
cmd.Parameters.AddWithValue("#Phone", phonebox.Text);
cmd.Parameters.AddWithValue("#Mobile", mobilebox.Text);
cmd.Parameters.AddWithValue("#Area", areabox.Text);
cmd.Parameters.AddWithValue("#date", datestring);
cmd.ExecuteNonQuery();
cnt.Close();
but it get error in mobile column :
Violation of UNIQUE KEY constraint 'UQ__phone__5C7E359EA73D3013'. Cannot insert duplicate key in object 'dbo.phone'. The duplicate key value is (4802615).
Note 2: I am using this code for select and view selected row ready for edit
1-Problem Solved the SQL column was Unique index so i removed that.
2- there wasn't a "where condition" so i fixed that too
Where clause is not used so all the rows in the table are getting updated and hence the error is getting generated.
Add a "WHERE Phone=#phone" and it's associated parameter command. As the other person pointed out, you're updating but you haven't told the database to specifically focus on an individual record, so your command updates them all.
This is fine for the first record, as soon as it tries updating the second, it blows up because phone has a unique constraint on it, preventing any other record having the same data. That's your error message.
You need to change your update statement to target the exact record you want to update.
I think you should set the PK or you update all the rows in the phone table.
for example: UPDATE tablename SET columName WHERE ....
I hope this will be useful

Why inserting DateTime to MySQL in C# is getting an error?

I Try to insert to MySQL database in C#, but what i got is this error
"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 "insert (NoNota, Nama, Tanggal, Tipe, Keterangan) VALUES ('1111',
'Kickass', '201" at line 1
i think the problem is the DateTime, in my database datatype i set it to DATETIME, Here is my code
string sqlQuery;
sqlQuery = "INSERT INTO insert (id, Name, Date, Type, Notes) VALUES ('1111', 'Kickass', '2013-09-09', 'Cash', 'Nothing')";
if (this.OpenConnection() == true)
{
cmd = new MySqlCommand(sqlQuery, connect);
cmd.ExecuteNonQuery();
CloseConnection();
MessageBox.Show("Operation INSERT is SUCCESS!!");
}
What's wrong with it? i try excute my SQL Queries it work very FINE in MySQL Workbench, it automatically convert the DateTime and insert it into the table. Any clue?
insert is a reserved word (INSERT INTO insert). Rename the table or escape with backticks. I'd highly recommend renaming.
You need to escape reserved words in MySQL like INSERT with backticks
INSERT INTO `insert` (id, Name, ...
^------^---------------------here
But it would be way better to rename your table. insert does not say anything about your data. Try to think of its content. When you have hundreds of tables in a database you need to name every one very carefully to keep track what it contains.
When you name your column, name it after the single word that finishes this sentance:
The data of my table holds ...

Querying a database for username and password

I'm totally new to C#. I am validating username and password with case-sensitive
from database sql server 2008. Here is my login code; what should I do?
SqlConnection conn = new SqlConnection(#"Data Source=.\SQLEXPRESS;Initial Catalog=db_WiBo;Integrated Security=True");
SqlCommand cmd = new SqlCommand("SELECT * from tb_Account where Username= '"+textBox1.Text+"' AND Password= '"+textBox2.Text+"' ", conn);
conn.Open();
SqlDataReader reader = cmd.ExecuteReader()
if (reader.HasRows)
{
reader.Close();
this.Hide();
}
Thanks in advance
1) you should be using stored procedures or parameterised query instead of SQL Concatenation. you are presenting a huge SQL Server injection security flaw in your code already.
what is the problem you are having? code looks fine - are you sure the inputs match the data in the database if there are no records being retrieved?
the code simply executes the query and if found, closes the reader and hides the form.
you should also not store raw passwords in the DB - another security flaw. instead, hash them/encrypt them and check that value against the hashed/encrypted value from the input.
for case sensitivity, you could use Collation
http://technet.microsoft.com/en-us/library/ms184391.aspx
http://blog.sqlauthority.com/2007/04/30/case-sensitive-sql-query-search/
A few things:
You are missing a ';' at the end of SqlDataReader reader = cmd.ExecuteReader().
As was already mentioned, use a Stored Procedure for what you are doing.
As was also mentioned, use parameterized queries since you are accepting input from textboxes.
Use a using statement to manage your connection and command objects.
Don't forget to .Close() your connection when you are done.
Oh, and I almost forgot, hash your passwords!
Here is an example of the above:
using (SqlConnection conn = new SqlConnection(#"Data Source=.\SQLEXPRESS;Initial Catalog=db_WiBo;Integrated Security=True"))
{
using (SqlCommand cmd = new SqlCommand(#"SELECT * from tb_Account where Username= '#username' AND Password= '#password' ", conn))
{
cmd.Parameters.Add("#username", textBox1.Text);
cmd.Parameters.Add("#password", textBox2.Text);
conn.Open();
SqlDataReader reader = cmd.ExecuteReader();
if (reader.HasRows)
{
reader.Close();
this.Hide();
}
conn.Close();
}
}
Other than your SQL injection issues, you need to use a collation or cast to binary. I found another SO question that has a bunch of helpful things:
How to do a case sensitive search in WHERE clause (I'm using SQL Server)?
First of all: Do not use string concat for that. This can easily be used for code injection.
You can use stored procedures instead, or LinQ to SQL or even use the built-in membershipprovider
Notwithstanding the design issues already pointed out with respect to security, if your SQL Server instance's default collation is case-insensitive, you'll need to select a suitable collation. The default collation for a SQL Server installation is [usually, depending on the server locale] SQL_Latin1_General_Cp1_CI_AS, meaning Latin-1 code page, case-insensitive, accent-sensitive.
When you create a database, you can specify a default collation for that database. And when you create a table, you may specify the collation to be used for each char, varchar, nchar or nvarchar column.
You may also change these via appropriate DDL statements. Note that altering the collatino may affect data integrity, causing things like primary keys and unique indices to be broken.
Create a table with and specifying the collation for its columns is easy:
create table account
(
id int not null identity(1,1) primary key clustered ,
user_id varchar(32) collate SQL_Latin1_General_Cp1_CS_AS not null unique ,
password varchar(32) collate SQL_Latin1_General_Cp1_CS_AS not null unique ,
...
)
You may use alter table and alter database to change the collations as well.
Supported collations can be found at http://technet.microsoft.com/en-us/library/ms180175.aspx and http://technet.microsoft.com/en-us/library/ms188046.aspx
You should
Note that mixed collations can cause problems when comparing 2 columns, and
Heed the security issues raised by others.

OLEDB and C# bulk insert for Excel spreadsheet creation

I am using C# to read a SQL stored procedure, put the results of the stored procedure into a C# data table and then reading the data table row by row to build up my "Insert into....values "etc. This creates my Excel spreadsheet with the correct data. However, instead of inserting row by row, is there a way of doing a bulk insert?
Failing that I was thinking of getting the stored procedure to write the results to a permanent table and therefore is there a way of doing an "Insert into ....select from ". When I have tried this in C# the code is unable to find the SQL table name specified "Microsoft database access engine cannot find the object ", what is the correct syntax and where do you specify where/how to access the SQL table?
Thanks
Hi, that link looks like it's using Microsoft.Office.Interop.Excel;
I'm using OLEDB (which i'm now beginning to regret!). So basically i have a C# class that is called from another component. This C# class reads a sql stored procedure, puts the results into a data table. I then set up the table definition using the OLEDBcommand "Insert into ( []) values ("?"). I then define the parameters e.g. cmd.Parameters.Add(columnHeading, OleDbType.VarChar, size) etc. Then for each row i find in the data table i set the cmd.Parameters[i].value = row[i], where parameters[i] is incremented for each column in that row. I then loop round for each data row and set cmd.Parameters[i].value appropriately. As I have to set the cmd.Parameters[i].Value for each row i find in my dataset and then cmd.ExecuteNonQuery();
, this is quite time consuming. So is there a way to bulk insert the data from the data table into the OLEDB command, if not, can i insert the data by referencing a SQL table directly and doing a "insert into..select from"?
You can separate your insert statements with a semicolon and run just 1 command. For instance ...
string sql = "insert into table (col1,col2) values ('row1','row1');"
sql += "insert into table (col1,col2) values ('row2','row2');"
sql += "insert into table (col1,col2) values ('row3','row3');"
SqlConnection conn = new SqlConnection("some connection string");
SqlCommand cmd = new SqlCommand(sql, conn);
conn.Open();
conn.ExecuteNonQuery();
conn.Dispose();
cmd.Dispose();
Or something similar. You are executing all 3 queries with 1 command. This might not work with databases other than SQL Server, but will definitely work with SQL Server.

Categories