I am trying to use the SqlCeCommandBuilder, and I am having an issue with it. My table, I am using has three columns. The first is set to primary key, and identity is on and set to increment by one. When I am creating my SqlCeCommand, I cannot get it to execute. I thought if I leave that column out, it will automatically add the value, but it returns an error stating the number of columns in the command have to match the number of columns in the table. So if I add the "BillerID" column to the command builder, it says I need to add a value for it. Then when I add a value, it says that the column "BillerID" cannot be modified. What am I doing wrong?
using (SqlCeConnection con = new SqlCeConnection(Properties.Settings.Default.BillsConnectionStringDefault))
{
con.Open();
try
{
using (SqlCeCommand command = new SqlCeCommand(
"INSERT INTO Billers VALUES(#BillerID, #Name, #Type)", con))
{
command.Parameters.Add(new SqlCeParameter("BillerID", 999999));
command.Parameters.Add(new SqlCeParameter("Name", billerName));
command.Parameters.Add(new SqlCeParameter("Type", "0"));
command.ExecuteNonQuery();
}
}
catch(Exception ex)
{
MessageBox.Show(string.Format(ex.Message.ToString()));
}
}
You can specify the columns you're inserting into, try changing the query to this:
"INSERT INTO Billers (Name, Type) VALUES(#Name, #Type)"
and leaving out the ID parameter entirely.
Related
This is the button for inserting those fileds into my database, the field names and db connection works for any other tasks but somehow this button keeps telling me the insert failed"
private void button1_Click(object sender, EventArgs e)
{
try {
int answer;
sql = "INSERT INTO Registration VALUES (#Student_ID,#Course_ID,#Section,#Start_Date,#End_Date,#Semester)";
connection.Open();
command = new SqlCommand(sql, connection);
command.Parameters.AddWithValue("#Student_ID", comboBox1.SelectedItem.ToString());
command.Parameters.AddWithValue("#Course_ID", lstcourse.SelectedItem.ToString());
command.Parameters.AddWithValue("#Section", txtsection.Text);
command.Parameters.AddWithValue("#Start_Date", txtstart.Text);
command.Parameters.AddWithValue("#End_Date", txtend.Text);
command.Parameters.AddWithValue("#Semester", txtsemester.Text);
answer = command.ExecuteNonQuery();
command.Dispose();
connection.Close();
MessageBox.Show("You're awesome and added " + answer + " row to your registration");
}
catch
{
MessageBox.Show("You screwed up");
}
/////////////////////////////////
}
This is the table:
Registration_ID float Checked
Student_ID float Checked
Course_ID float Checked
Section float Checked
Start_Date datetime Checked
End_Date datetime Checked
Semester nvarchar(255) Checked
Unchecked
Somehow this button keeps telling me the insert failed
It would of been helpful if you could have posted the actual error from the catch statement. If you debugged the routine and specifically inspected the error message, you'd notice what was wrong.
The primary issue of the error is because you didn't supply the columns to insert into. If you supplied all columns upfront the insert statement would be satisfied and work just fine.
Solution
Either make sure all columns are accounted for in the insert statement.
Specify the columns you are inserting into.
Your table according to your post has 7 columns, you are only supplying 6 of them. When you using the syntax of INSERT INTO TABLENAME VALUES() you have to supply values for all columns, not just a select few.
On the other hand if you used the syntax of INSERT INTO TABLENAME(columnName, columnName)VALUES(value, value) you are fulfilling the requirements by supplying two columns along with their values.
Side Note:
Look into using statements to ensure objects are disposed of.
Use SqlParameterCollection.Add method instead of AddWithValue, it has to infer the data types and this could cause unintended results.
When declaring your parameters, please specify/add the correct data type and length that matches the column data type and length on the table.
Either modify your SQL statement to include the missing column:
INSERT INTO Registration VALUES (#Registration_ID,#Student_ID,#Course_ID,#Section,#Start_Date,#End_Date,#Semester)
or specify the columns that will be populated in your new row (assuming your Registration_ID field is an auto-identifier)
INSERT INTO Registration (Student_ID, Course_ID, Section, Start_Date, End_Date, Semester) VALUES (#Student_ID,#Course_ID,#Section,#Start_Date,#End_Date,#Semester)
you can try this code
using(SqlConnection connection = new
SqlConnection(ConfigurationManager.ConnectionStrings["conString"].ConnectionString))
{
connection.Open();
string sql = "INSERT INTO Table(id,name,test)
VALUES(#param1,#param2,#param3)";
using(SqlCommand cmd = new SqlCommand(sql,connection))
{
cmd.Parameters.Add("#param1", SqlDbType.Int).value = val;
cmd.Parameters.Add("#param2", SqlDbType.Varchar, 50).value = Name;
cmd.Parameters.Add("#param3", SqlDbType.Varchar, 50).value = Test;
cmd.CommandType = CommandType.Text;
cmd.ExecuteNonQuery();
}
}
I am new to C#. I am trying to save the numbers into a SQL Server database table (locally) but I get an error:
Cannot insert the value NULL into column
My code:
private void SaveBtn_Click(object sender, EventArgs e)
{
try
{
SqlConnection conn = new SqlConnection(#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\fn1965\Desktop\Work\TESTDB\NumDB.mdf;Integrated Security=True;Connect Timeout=30");
conn.Open();
string insert_query = "INSERT into [NumericTable] (Num1, Num2, Total) VALUES (#Num1, #Num2, #Total)";
SqlCommand cmd = new SqlCommand(insert_query, conn);
cmd.Parameters.AddWithValue("#Num1", textBox1.Text);
cmd.Parameters.AddWithValue("#Num2", textBox2.Text);
cmd.Parameters.AddWithValue("#Total", textBox3.Text);
cmd.ExecuteNonQuery();
MessageBox.Show("Record saved");
conn.Close();
}
catch (Exception ex)
{
MessageBox.Show("EROR:"+ ex.ToString());
}
}
Table schema
You can see in the image that the column Id is the only one that does not support null values. Since the column is not identity and as you are not providing a value on your insert, then the INSERT fail with the given exception. This code will work (only if there isn't a record with Id = 1 already):
string insert_query = "INSERT into [NumericTable] (Num1,Num2,Total, Id) Values (#Num1,#Num2,#Total, #id)";
SqlCommand cmd = new SqlCommand(insert_query, conn);
cmd.Parameters.AddWithValue("#Num1", textBox1.Text);
cmd.Parameters.AddWithValue("#Num2", textBox2.Text);
cmd.Parameters.AddWithValue("#Total", textBox3.Text);
cmd.Parameters.AddWithValue("#Id", 1);
cmd.ExecuteNonQuery();
I assume that this is obviously not the desired fuctionality. What you should do is either set the Id column to identity = true or set a value on the insert.
I also encourage you to not use AddWithValue method since it can lead you to some undesired problems. You can read more here: https://blogs.msmvps.com/jcoehoorn/blog/2014/05/12/can-we-stop-using-addwithvalue-already/
That screenshot you took of your table columns design; get back to that, then click the id column, look in the Properties grid for Identity Specification (might need to expand it) and set it to Yes. Set other properties relevant to your needs and save the table.
Borrowed from another SO question:
There are ways to do this from script but they're generally longer/more awkward than using the UI in management studio.
This will (should) change th column so it auto inserts an incrementing number into itself when you insert values for other rows. Someone else has posted an answer as to how to insert values for it yourself but my recommendation to you as a learner is to use auto increment to save the additional needless complication of providing your own primary key values
I've just gotten started with creating a simple inventory extension for a web app and I've run into an issue where I'm having trouble updating the rows in a table for values that already exist in the Product column.
The method is pretty similar to the insert data method, which is working so I'm not exactly sure about what is going on. Here's the code that I have:
static void ReplaceInventory(string product, int qty)
{
using (SqlConnection con = new SqlConnection(
"Data Source=TestSQL;Initial Catalog=TestInv;User ID=tester;Password=passwordtest;"))
{
con.Open();
try
{
using (SqlCommand command = new SqlCommand(
"UPDATE Inventory SET Qty = #Qty WHERE Product = #Product", con))
{
command.Parameters.Add(new SqlParameter("#Qty", qty));
command.Parameters.Add(new SqlParameter("#Product", product));
command.ExecuteNonQuery();
}
}
catch
{
Console.WriteLine("Record not updated");
}
con.Close();
}
}
This works however:
static void AddInventory(string product, int qty)
{
using (SqlConnection con = new SqlConnection(
"Data Source=TestSQL;Initial Catalog=TestInv;User ID=tester;Password=passwordtest;"))
{
con.Open();
try
{
using (SqlCommand command = new SqlCommand(
"INSERT INTO Inventory VALUES(#Product, #Qty)", con))
{
command.Parameters.Add(new SqlParameter("Product", product));
command.Parameters.Add(new SqlParameter("Qty", qty));
command.ExecuteNonQuery();
}
}
catch
{
Console.WriteLine("Count not insert.");
}
con.Close();
}
}
Any help or pointers would be much appreciated!
Try setting the command type as Text, before executing the query:
command.CommandType = System.Data.CommandType.Text
Have you debugged your code and checked if the values are passed properly?
Try including the SqlDbType and size.
command.Parameters.Add("#Product",SqlDbType.NVarChar, 20,product);
For implicit conversion, try AddWithValue
command.Parameters.AddWithValue(new SqlParameter("#Qty", qty));
command.Parameters.AddWithValue(new SqlParameter("#Product", product));
According to MSDN:
AddWithValue replaces the SqlParameterCollection.Add method that takes
a String and an Object. The overload of Add that takes a string and an
object was deprecated because of possible ambiguity with the
SqlParameterCollection.Add overload that takes a String and a
SqlDbType enumeration value where passing an integer with the string
could be interpreted as being either the parameter value or the
corresponding SqlDbType value. Use AddWithValue whenever you want to
add a parameter by specifying its name and value.
See this link for reference.
But using command.Parameters.Add is more reliable and safe because the type of the data is defined and the database doesn't need to identify and convert the data being sent.
Figured it out. The "Product" column in the table that I had created in my database was of a "text" data type, and so it wasn't recognizing the "=" as valid in the UPDATE expression. When I swapped the "=" sign out for LIKE the function worked as expected. Thanks for the feedback!
I have a table with CREATED and MODIFIED columns. I only want to insert the CREATED value once and have it be thereafter immutable. I know how to do this in a tedious way (write a "DoesRecordExist()" method and then alter the query and number of query parameters based on that), but surely there is a slicker way to accomplish this. After all, this has to be a common requirement (a "database pattern" if you will).
My code is this:
public void InsertUserSiteRecord(UserSite us)
{
using (SQLiteConnection conn = new SQLiteConnection(HHSUtils.GetDBConnection()))
{
conn.Open();
using (SQLiteCommand cmd = new SQLiteCommand(conn))
{
cmd.CommandText =
String.Format(
#"INSERT INTO UserSite (SiteNum, SerialNum, UserName, Created, Modified)
VALUES (#SiteNum, #SerialNum, #UserName, #Created, #Modified)");
cmd.Parameters.Add(new SQLiteParameter("SiteNum", us.SiteNum));
cmd.Parameters.Add(new SQLiteParameter("SerialNum", us.SerialNum));
cmd.Parameters.Add(new SQLiteParameter("UserName", us.UserName));
cmd.Parameters.Add(new SQLiteParameter("Created", us.Created));
cmd.Parameters.Add(new SQLiteParameter("Modified", us.Modified));
cmd.ExecuteNonQuery();
}
conn.Close();
}
}
...and I want to avoid having to do something like this:
public void InsertUserSiteRecord(UserSite us)
{
using (SQLiteConnection conn = new SQLiteConnection(HHSUtils.GetDBConnection()))
{
conn.Open();
using (SQLiteCommand cmd = new SQLiteCommand(conn))
{
if (!RecordExists(us.SiteNum, us.SerialNum, us.UserName))
{
cmd.CommandText =
String.Format(
#"INSERT INTO UserSite (SiteNum, SerialNum, UserName, Created, Modified)
VALUES (#SiteNum, #SerialNum, #UserName, #Created, #Modified)");
else
{
cmd.CommandText =
String.Format(
#"INSERT INTO UserSite (SiteNum, SerialNum, UserName, Modified)
VALUES (#SiteNum, #SerialNum, #UserName, #Modified)");
}
cmd.Parameters.Add(new SQLiteParameter("SiteNum", us.SiteNum));
cmd.Parameters.Add(new SQLiteParameter("SerialNum", us.SerialNum));
cmd.Parameters.Add(new SQLiteParameter("UserName", us.UserName));
if (!RecordExists(us.SiteNum, us.SerialNum, us.UserName))
{
cmd.Parameters.Add(new SQLiteParameter("Created", us.Created));
}
cmd.Parameters.Add(new SQLiteParameter("Modified", us.Modified));
cmd.ExecuteNonQuery();
}
conn.Close();
}
}
private bool RecordExists(String SiteNum, String SerialNum, String UserId)
{
// query the table to see if those three values exist in any record
}
Is there a SQL[ite] construct that is something like:
cmd.Parameters.AddOnlyIfColumnIsEmpty(new SQLiteParameter("Created", us.Created));
? Or how can this be best tackled?
You need to check for existance of the record; then do an UPDATE if it exists (not changing your Created value), and an INSERT if it doesn't.
Your original code will give a duplicate key error, assuming you have a PK on the table.
You may be able to accomplish this using a trigger. See the SQLite documentation on triggers here: https://www.sqlite.org/lang_createtrigger.html
Basically, you would create an INSTEAD OF trigger, then set up your query accordingly. From the documentation:
For an example of an INSTEAD OF trigger, consider the following schema:
CREATE TABLE customer(
cust_id INTEGER PRIMARY KEY,
cust_name TEXT,
cust_addr TEXT
);
CREATE VIEW customer_address AS
SELECT cust_id, cust_addr FROM customer;
CREATE TRIGGER cust_addr_chng
INSTEAD OF UPDATE OF cust_addr ON customer_address
BEGIN
UPDATE customer SET cust_addr=NEW.cust_addr
WHERE cust_id=NEW.cust_id;
END;
With the schema above, a statement of the form:
UPDATE customer_address SET cust_addr=$new_address WHERE cust_id=$cust_id;
Causes the customer.cust_addr field to be updated for a specific customer entry that has customer.cust_id equal to the $cust_id parameter. Note how the values assigned to the view are made available as field in the special "NEW" table within the trigger body.
What you would want to do is just set up the trigger to not update that column even if the original query passes in that column to be updated.
How can I know whether the table in database is affected after these instructions? I try to show the query result in console but it doesn't show anything.
static void Main(string[] args)
{
DateTime date = new DateTime(2013, 3, 4);
try
{
SqlConnection connection = new SqlConnection("Data Source=ExchangeRatesByDate/TestApplication/Rates_DB.sdf");
Console.WriteLine("Connection is created");
connection.Open();
Console.WriteLine("Connection is opened");
SqlCommand insertCommand = connection.CreateCommand();
insertCommand.CommandText = "INSERT INTO Rates_Table(ISO, Amount, Rate, Date) VALUES (USD, 1, 417.5, date)";
insertCommand.ExecuteNonQuery();
SqlDataAdapter adapter = new SqlDataAdapter("SELECT * FROM Rates_Table", connection);
DataTable data = new DataTable();
adapter.Fill(data);
Console.WriteLine(adapter);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
ExecuteNonQuery() returns an integer showing number of affected rows. ExecuteNonQuery
You can use the ExecuteNonQuery to perform catalog operations (for
example, querying the structure of a database or creating database
objects such as tables), or to change the data in a database without
using a DataSet by executing UPDATE, INSERT, or DELETE statements.
Although the ExecuteNonQuery returns no rows, any output parameters or
return values mapped to parameters are populated with data.
For UPDATE, INSERT, and DELETE statements, the return value is the
number of rows affected by the command. When a trigger exists on a
table being inserted or updated, the return value includes the number
of rows affected by both the insert or update operation and the number
of rows affected by the trigger or triggers. For all other types of
statements, the return value is -1. If a rollback occurs, the return
value is also -1.
try like this
int updatedRows = insertCommand.ExecuteNonQuery();
if(updatedRows>0)
{
//do something
}
i think u are showing SqlDataAdapter object show to datatable ,and also use parameter for the insert string like 'USD'
the ExecuteNonQuery() returns an integer for the number of affected records.
int _affected = insertCommand.ExecuteNonQuery();
ExecuteNonQuery()
follow-up question
INSERT INTO Rates_Table(ISO, Amount, Rate, Date) VALUES (USD, 1, 417.5, date)
in the statement above, are values USD and date are real values because if so, it pretty sure it will thrown an exception. It should be wrap with single quotes like this:
INSERT INTO Rates_Table(ISO, Amount, Rate, Date) VALUES ('USD', 1, 417.5, '')
because they are string literals. But it's not the proper way to insert data with real values in the INSERT statement. The values should be parameterized to avoid sql injection.
string sqlStatement = "INSERT INTO Rates_Table(ISO, Amount, Rate, Date) VALUES (#iso, #Amount, #rate, #date)";
using (SqlConnection conn = new SqlConnection(connStr))
{
using(SqlCommand comm = new SqlCommand())
{
comm.Connection = conn;
comm.CommandText = sqlStatement;
comm.CommandType = CommandType.Text;
comm.Parameters.AddWithValue("#iso", '-- value --');
comm.Parameters.AddWithValue("#Amount", '-- value --');
comm.Parameters.AddWithValue("#rate", '-- value --');
comm.Parameters.AddWithValue("#date", '-- value --');
try
{
conn.Open();
int _affected = comm.ExecuteNonQuery();
}
catch(SqlException e)
{
// do something with the exception
// do not hide it
// e.Message.ToString()
}
}
}
For proper coding
use using statement for propr object disposal
use try-catch block to properly handle objects