I wonder if someone could help me with this SQL insert query? I've a nasty suspicion that I am staring at something very obvious, but I've been trying to figure it out for a while now, and I can't see what's wrong. At the moment it just drops through to the catch loop when I try and execute. I'm using Visual studio Community 2015. Incidentally, is there anywhere in VS where you can try out a SQL statement?
Here's the code
private void button1_Click(object sender, EventArgs e)
{
try
{
SqlConnection myConnection = new SqlConnection(#"Data Source = (LocalDB)\MSSQLLocalDB; AttachDbFilename = ""C:\Users\Nick\Documents\Investments 4.mdf""; Integrated Security = True; Connect Timeout = 30");
myConnection.Open();
if (myConnection.State == ConnectionState.Open)
{
MessageBox.Show("Connection Open");
}
SqlCommand myCommand3 = new SqlCommand();
myCommand3.CommandType = System.Data.CommandType.Text;
myCommand3.CommandText = "INSERT INTO Dbo.Values (Portfolio Name,Date,Daily Value,Daily Percent) VALUES ('Ascentric',#SQLTime,2000,0.01)";
//myCommand.Parameters.Add("#SQLPortName", System.Data.SqlDbType.NVarChar);
//myCommand.Parameters["#SQLPortName"].Value = "Eric";
myCommand3.Parameters.Add("#SQLTime", System.Data.SqlDbType.DateTime );
myCommand3.Parameters["#SQLTime"].Value = DateTime.Today;
myCommand3.ExecuteNonQuery();
myConnection.Close();
}
catch
{
MessageBox.Show("Nope. Didn't work");
}
}
And here's the table:
By the way, I do understand that I need to parameterise this, but I am just trying to get the basic statement to work at the moment.
Any help gratefully received!
You have to wrap your column names in brackets if they include spaces, or are a reserved keyword (such as Date):
myCommand3.CommandText = "INSERT INTO Dbo.Values ([Portfolio Name],[Date],[Daily Value],[Daily Percent]) VALUES ('Ascentric',#SQLTime,2000,0.01)";
As a best practice: Don't ever use spaces in SQL for objects (columns, SPROCS, etc). Use CamelCase or underscores_to_separate_words. Because you'll forget the brackets again one day.
Creating columns with Space is not the best practice to follow. First remove spaces and make your columns as single word. If you want to show spaces at the time of selection you may use alias instead.
myCommand3.CommandText = "INSERT INTO dbo.Values (PortfolioName,[Date],DailyValue,DailyPercent) VALUES ('Ascentric',#SQLTime,2000,0.01)";
myCommand3.Parameters.Add(new SqlParameter("#SQLTime",DateTime.Today.ToString());
Related
I am currently working on a dummy project in which I am making a login screen. I don't have any big intentions with the project, beside learning some C# and sql.
I am currently trying append a new user to the database which contains each username and their password, but I am for some reason getting an error message.
The entry written in the textbox should be stored in the database, but for some reason is this not happening..
I am getting an error stating I have a syntax error which I am not sure i understand.
private void create_user_username_box_Leave(object sender, EventArgs e)
{
// Add user/password to database when when someone leaves the area.
using (DbConnection connection = new SqlConnection(#"Server=localhost\SQLEXPRESS01;Database=master;Trusted_Connection=True;"))
{
connection.Open();
using (DbCommand command = new SqlCommand("INSERT INTO [dbo].[information] (id,password) VALUES ("+create_user_username_textbox.Text+","+create_user_password_textbox.Text+");"))
{
command.Connection = connection;
command.ExecuteNonQuery(); // System.Data.SqlClient.SqlException: 'Incorrect syntax near ')'.'
}
}
}
Do not do the following, ever
"INSERT INTO [dbo].[information] (id,password)
VALUES (" + someStringVariable + "," + someOtherStringVariable + ")"
Just think about what you're doing here - you're putting whatever text the user entered directly into your query string. This is the easiest way to have your database dropped or all the information it contains stolen.
Instead, use prepared statements
var commandText = "INSERT INTO [dbo].[information] (id,password) VALUES (#Username, #Password)"
using (var command = new SqlCommand(commandText, connection))
{
command.Parameters.Add("#Username", SqlDbType.VarChar).Value = create_user_username_textbox.Text
command.Parameters.Add("#Password", SqlDbType.VarChar).Value = create_user_password_textbox.Text
command.ExecuteNonQuery();
}
You should also strongly consider NOT storing passwords in plain text
Updated with suggestion to replace Parameters.AddWithValue - obviously if the column type on your database is different, set it accordingly
The values are strings so the resulting SQL command text should enclose them within single quotes.
VALUES ('"+create_user_username_textbox.Text+"','"...
However, you should really parameterise the query to prevent the potential for Sql injection attacks.
Change the string to:
VALUES (#id,#pw)"))
Add parameters to the command:
command.Parameters.Add(new SqlParameter("#id", create_user_username_textbox.Text));
command.Paramaters.Add(new SqlParameter("#pw", create_user_password_textbox.Text));
try this -
private void create_user_username_box_Leave(object sender, EventArgs e)
{
// Add user/password to database when when someone leaves the area.
using (SqlConnection connection = new SqlConnection(#"Server=localhost\SQLEXPRESS01;Database=master;Trusted_Connection=True;"))
{
connection.Open();
using (SqlCommand command = new SqlCommand("INSERT INTO [dbo].[information] (id,password) VALUES ("+create_user_username_textbox.Text+","+create_user_password_textbox.Text+");"))
{
command.Connection = connection;
command.ExecuteNonQuery(); // System.Data.SqlClient.SqlException: 'Incorrect syntax near ')'.'
}
}
}
My application with C#2010 and database in Access2003, I want to insert new recrord into my table by the it has an error:
"syntax error in insert into statement"
private void button3_Click(object sender, EventArgs e)
{
String ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + Application.StartupPath + "\\New.mdb";
OleDbConnection myconection = new OleDbConnection(ConnectionString);
try
{
OleDbCommand mycomand = new OleDbCommand();
mycomand.CommandText = "INSERT INTO Refugees Characteristic(Nr,First Name,Last Name,Birthday,Country,City,Insurance Nr,Gander,Marital status,Nr of Children,Address,Mother Tongue,Other Languages,Phone Nr,Enter to Austria,Education,Skills,Picture) VALUES (#p1,#p2,#p3,#p4,#p5,#p6,#p7,#p8,#p9,#p10,#p11,#p12,#p13,#p14,#p15,#p16,#p17,#p18)";
mycomand.Parameters.Clear();
mycomand.Parameters.AddWithValue("#p1", IdTxt.Text);
mycomand.Parameters.AddWithValue("#p2", FirstTxt.Text);
mycomand.Parameters.AddWithValue("#p3", LasttextBox.Text);
mycomand.Parameters.AddWithValue("#p4", BirthdayTxt.Text);
mycomand.Parameters.AddWithValue("#p5", CountryTxt.Text);
mycomand.Parameters.AddWithValue("#p6", CityTxt.Text);
mycomand.Parameters.AddWithValue("#p7", InsuranceTxt.Text);
mycomand.Parameters.AddWithValue("#p8", GanderBox.Text);
mycomand.Parameters.AddWithValue("#p9", marriedTxt.Text);
mycomand.Parameters.AddWithValue("#p10", ChildnumTxt.Text);
mycomand.Parameters.AddWithValue("#p11", AddressTxt.Text);
mycomand.Parameters.AddWithValue("#p12", MotherTongTxt.Text);
mycomand.Parameters.AddWithValue("#p13", OtherlanTxt.Text);
mycomand.Parameters.AddWithValue("#p14", phonNumberTxt.Text);
mycomand.Parameters.AddWithValue("#p15", EnterTxt.Text);
mycomand.Parameters.AddWithValue("#p16", EducationTxt.Text);
mycomand.Parameters.AddWithValue("#p17", SkillsTxt.Text);
mycomand.Parameters.AddWithValue("#p18", PicLocationtxt.Text);
// mycomand.Connection = null;
mycomand.Connection = myconection;
myconection.Open();
mycomand.ExecuteNonQuery();
MessageBox.Show("New Record is Added");
myconection.Close();
myconection.Dispose();
mycomand.Dispose();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
If your table names and column names are two words, you need to use them with square brackets like [Refugees Characteristic], [First Name], [Last Name], [Insurance Nr], [Marital status], [Nr of Children] etc. As a general purpose, if you have to use two words for your column names, you can write your works adjacent.
Also use using statement to dispose your OleDbConnection and OleDbCommand instead of calling their .Close() and .Dispose() methods manually.
using(var myconection = new OleDbConnection(ConnectionString))
using(var mycomand = myconection.CreateCommand())
{
//
}
And don't use AddWithValue method. It may generate upexpected results sometimes. Use .Add() overloads instead to specify your OleDbType and your parameter size.
As a final thing, Picture seems a form and report property in MS Access. That means it is a reserved word. You need to use it [Picture] as well.
Put your column names inside the square bracket.
[First Name],[Marital status],[Nr of Children],[Address],[Mother Tongue],[Other Languages],[Phone Nr]
So it would be like
mycomand.CommandText = #"INSERT INTO [Refugees Characteristic]([Nr],[First Name],[Last Name],[Birthday],[Country],[City],[Insurance Nr],[Gander],[Marital status],[Nr of Children],[Address],[Mother Tongue],[Other Languages],[Phone Nr],[Enter to Austria],[Education],[Skills],[Picture]) VALUES (#p1,#p2,#p3,#p4,#p5,#p6,#p7,#p8,#p9,#p10,#p11,#p12,#p13,#p14,#p15,#p16,#p17,#p18)";
I'm trying to do something I feel is quite simple in the grand scheme of things, however I'm clearly missing something. What I have is a simple database named 'localcollection'. What I would like to do is sum up the dollar amount of a column named 'purprice', and setting it as the text of a label (label4). I've been finding variants of code throughout the last couple days that suggest different ways of achieving this. The majority of my digging suggest that using ExecuteScalar is what I want to do. The code that I've been fumbling with follows.
SqlCeConnection myconn = new SqlCeConnection(Properties.Settings.Default.localbotdbConnectionString);
myconn.Open();
{
string result = "select sum(purprice) from localcollection";
SqlCeCommand showresult = new SqlCeCommand(result, myconn);
label4.Text = showresult.ExecuteScalar().ToString();
myconn.Close();
}
Others suggest using the SqlCeReader. I'm impartial to either of them, as long as one of them works, and I am clearly missing something (fault of my own). The reader rendition that I was trying to make work is:
SqlCeCommand cmd = new SqlCeCommand("select sum(purprice) from localcollection");
SqlCeDataReader reader = cmd.ExecuteReader();
while(reader.Read())
{
label4.Text = reader.GetString(0);
}
myconn.Close();
Constructive advice appreciated. Thank you
If you are only looking to return one value from a query, then ExecuteScalar is what you should be using, . The ExecuteReader is better for forward-only reads of multiple records, so it's overkill for your situation
Take a look here for a comparisson What is the difference between ExecuteScalar, ExecuteReader and ExecuteNonQuery?
I would do some modifications to your code because for one thing your are not properly disposing of your objects, also you stated that you have it in the button click method which I would get that out of there and make this its own function.
private string performSQL()
{
string result = "select sum(purprice) from localcollection";
using (SqlCeConnection myconn = new SqlCeConnection("ConnectionString"))
using (SqlCeCommand showresult = new SqlCeCommand(result, myconn))
{
try
{
myconn.Open();
return showresult.ExecuteScalar().ToString();
}catch(System.Exception ex)
{
MessageBox.Show(ex.ToString());
// or log exception how ever you prefer
}finally
{
//the finally ensures your connection gets closed
myconn.Close();
}
}
return "";
}
Best practice, use ExecuteScalar when you are returning 1 row and 1 column of data (which your query does.) As a result, go with ExecuteScalar.
Make sure the name of the column you are trying to add is purprice, and that it is a numeric type.
Also make sure it doesn't contain NULL values.
I think your code is ok, but you missed :
SqlCeCommand cmd = new SqlCeCommand("select sum(purprice) from localcollection",myconn);
that's all, hope it works
Just add AS after SUM() like the row below:
select sum(purprice) AS purprice from localcollection
And you are good to go.
What is wrong in the following code? im storing the date n time into datetime field in sql server.
private void button1_Click(object sender, EventArgs e)
{
string d = DateTime.Now.ToShortDateString();
cmd.CommandText = "insert into trans values("+label9.Text+",'d');";
cmd.Connection = con;
con.Open();
int x= cmd.ExecuteNonQuery();
MessageBox.Show("Attendance recorded succesfully");
It is a very bad approach, because it opened for sql-injections. You better use SqlParameter.
cmd.CommandText="insert into trans values(#label, #date)";
cmd.Parameters.AddWithValue("label", int.Parse(label9.Text));
cmd.Parameters.AddWithValue("date", DateTime.Now);
cmd.Connection = con;
con.Open();
int x= cmd.ExecuteNonQuery();
There is mistyping in CommandText string. Use this instead
cmd.CommandText="insert into trans values("+label9.Text+","+DateTime.Now.ToString()+");";
EDIT:
Full edited code will be like this. Note that using statements will care for disposing your updates, but this code is still bad and a house of sql-injections. You must use parameters instead if you want safe code.
private void button1_Click(object sender, EventArgs e)
{
using (System.Data.SqlClient.SqlConnection connection = new System.Data.SqlClient.SqlConnection("Data Source=localhost; Initial Datalog=myDatabase; Integrated Security=TRUE;"))
{
using (System.Data.SqlClient.SqlCommand command = new System.Data.SqlClient.SqlCommand("insert into trans values("+label9.Text+","+DateTime.Now.ToString()+");", connection))
{
connection.Open();
command.ExecuteNonQuery();
connection.Close();
}
}
}
Apart from the fact that you are using inline SQL, which is just bad. You should be using #param1 syntax in the query and then adding parameters to it instead (thus sidestepping this issue also). Even better - use an ORM like Linq to Sql or Entity Framework (or nHibernate or whatever).
SQL Server generally wants it's times in yyyymmdd format, and also you really should be checking the label's value is indeed an integer and only running the query if it is:
int labelValue = 0;
if(int.TryParse(label9.Text, out labelValue))
{
cmd.CommandText="insert into trans values("+ labelValue +
", '" + DateTime.Now.ToString("yyyyMMdd");"')";
cmd.Connection = con;
con.Open();
int x= cmd.ExecuteNonQuery();
MessageBox.Show("Attendance recorded succesfully");
}
I'd also say you really need to examine your usage of the connection/command - where do you Dispose? Judging by this code, I'm guessing you don't?
All in all, even with these fixes I'm not recommending you do things this way - do it the way that Harm suggests - the +5 (or more) there is deserved.
I am developing a windows mobile app. Right now I am just testing that it can correctly query the local SQL Server CE database. It works fine until I put a WHERE statement in.
Here is my code:
private void buttonStart_Click(object sender, EventArgs e)
{
System.Data.SqlServerCe.SqlCeConnection conn = new System.Data.SqlServerCe.SqlCeConnection(
("Data Source=" + (System.IO.Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase), "ElectricReading.sdf") + ";Max Database Size=2047")));
try
{
// Connect to the local database
conn.Open();
System.Data.SqlServerCe.SqlCeCommand cmd = conn.CreateCommand();
SqlCeParameter param = new SqlCeParameter();
param.ParameterName = "#Barcode";
param.Value = "%" + textBarcode.Text.Trim() + "%";
// Insert a row
cmd.CommandText = "SELECT * FROM Main2 WHERE Reading LIKE #Barcode";
cmd.Parameters.Add(param);
cmd.ExecuteNonQuery();
DataTable data = new DataTable();
using (SqlCeDataReader reader = cmd.ExecuteReader())
{
if (reader.Read())
{
data.Load(reader);
}
}
if (data != null)
{
this.dataGrid1.DataSource = data;
}
}
finally
{
conn.Close();
}
The database contains this data:
Okay so you can see I changed the WHERE statement to use the Reading column just for testing purposes. When I enter "111" into the textbox and run --> it returns only the row where reading ="1111" and not the row that contains "111".
If I enter "1111" it does not return any data.
If I enter "1" it will return both the "1111" row and the "111" row which is the correct behavior.
However if I enter "11" it once again only returns the "1111" row.
Any other data entry of 2's or 9's attempting to return those rows does not work.
I'm not sure what is going on? This does not make any sense. It is not behaving like I would expect in any way shape or form. I know this must be a little confusing to read. I hope it makes enough sense to get some answers. Please help!
NOTE: I added the "%" before and after the text in an attempt to get better results. This is not desired.
EDIT <<<-----------------------I did have Reading = #Barcode, I just accidently typed Location for this question, that is not the problem.
Firstly, some things to note:
1) As other commentators have noted, use the Reading column, not the Location column. I know you have mentioned you are testing, but swapping around column names and then changing code isn't the easiest way to troubleshoot these things. Try to only change one thing at a time.
2) If Reading is numeric, you are going to have to convert the column value first.
So your query becomes:
"SELECT * FROM Main2 WHERE CONVERT(varchar, Reading) LIKE #Barcode";
Also see How to use parameter with LIKE in Sql Server Compact Edition for more help with working with parameters in SqlServerCE.
3) Set a parameter type on your SqlCEParameter. I've linked to the appropriate page in the code example below.
4) You are using ExecuteNonQuery for no reason. Just get rid of it in this context. It's for when you want to make a change to the database (like an insert, update, delete) or execute something (like a stored proc that can also insert, update, delete etc) that returns no rows. You've probably cut and paste this code from another place in your app :-)
5) Use using on disposable objects (see example below). This will make managing your connection lifecycle much simpler. It's also more readable (IMO) and will take care of issues when exceptions occur.
6) Use the using statement to import the BCL (Base Class Libraries) into your current namespace:
Add the following using statements to the top of your class (.cs). This will make using all of the .Net classes a lot simpler (and is much easier to read and less wear on your keyboard ;-)
using System.Data.SqlServerCe;
using System.IO;
using System.Reflection;
A more complete example would look like the following
private void buttonStart_Click(object sender, EventArgs e)
{
using(SqlCeConnection conn = new SqlCeConnection(
("Data Source=" + (Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase), "ElectricReading.sdf") + ";Max Database Size=2047"))))
{
// Connect to the local database
conn.Open();
using(SqlCeCommand cmd = conn.CreateCommand())
{
SqlCeParameter param = new SqlCeParameter();
param.ParameterName = "#Barcode";
param.DBType = DBType.String; //Intellisense is your friend here but See http://msdn.microsoft.com/en-US/library/system.data.sqlserverce.sqlceparameter.dbtype(v=VS.80).aspx for supported types
param.Value = "%" + textBarcode.Text.Trim() + "%";
// SELECT rows
cmd.CommandText = "SELECT * FROM Main2 WHERE CONVERT(varchar, Reading) LIKE #Barcode";
cmd.Parameters.Add(param);
//cmd.ExecuteNonQuery(); //You don't need this line
DataTable data = new DataTable();
using (SqlCeDataReader reader = cmd.ExecuteReader())
{
data.Load(reader); //SqlCeDataReader does not support the HasRows property.
if(data.Rows.Count > 0)
{
this.dataGrid1.DataSource = data;
}
}
}
}
}
Intellisense should be able to clean up any errors with the above but feel free to ask for more help.
Finally, you also might be able to set the data source of the grid directly to a datareader, try it!
using (SqlCeDataReader reader = cmd.ExecuteReader())
{
dataGrid1.DataSource = reader;
}
You can then get rid of the DataTable.
Change the following line:
cmd.CommandText = "SELECT * FROM Main2 WHERE Location LIKE #Barcode";
to
cmd.CommandText = "SELECT * FROM Main2 WHERE Reading LIKE #Barcode";
You are comparing the wrong columns.