I am trying to input data from four text boxes into a Firebird database. Every time I click the button that executes the following code, I get an "SQL Error = -804 Count of read-write columns does not equal count of values."
I'm not sure what this error means. The code I have is:
private void button1_Click(object sender, EventArgs e)
{
string ConnectionString = "User ID=sysdba;Password=masterkey;" +
"Database=localhost:G:\\nael.FDB; " +
"DataSource=localhost;Charset=NONE;";
FbConnection addDetailsConnection = new FbConnection(ConnectionString);
addDetailsConnection.Open();
FbTransaction addDetailsTransaction =
addDetailsConnection.BeginTransaction();
string SQLCommandText = " INSERT into Invoice_Name Values" +
"('" + textBox1.Text + "',' "
+ textBox2.Text + "',' "
+ int.Parse(textBox3.Text) + "',' "
+ textBox4.Text + "',' "
+ "')";
FbCommand addDetailsCommand = new FbCommand(SQLCommandText,
addDetailsConnection, addDetailsTransaction);
addDetailsCommand.ExecuteNonQuery();
addDetailsTransaction.Commit();
MessageBox.Show(" Details Added");
}
I bet one of your TextBox.Text values has a comma in it... Otherwise: Did you check to see if you are specifying the right amount of columns?
Basically, the SQL engine is complaining that you gave it a list of parameters and it is trying to fill those into the table Invoice_Name, except, it has too many values for the count of columns in that table. Try printing SQLCommandText to the output window (Debug.WriteLine(SQLCommandText)) and see if that is what you expect it to be...
You should also not be doing it this way... check this post here: Inserting into DB with parameters safe from SQL injection?
Related
I'm going to execute SQL query directly on database.
I've define connection to my database using:
System.Data.Entity.DbContext rawDbContext = new DbContext(connectionString);
I don't want to insert parameters directly to query string to avoid SQL Injection so I want to set parametrized values for my SQL query this way:
string sqlCommandString =
"IF EXISTS(select* from #MappingTableName where " + Environment.NewLine +
"BranchID= #PrimaryKeyID and " + Environment.NewLine +
"BranchNo = #BranchNo and " + Environment.NewLine +
"TableName = #TableName and " + Environment.NewLine +
"BranchSchema = #SchemaNameInBranch and " + Environment.NewLine +
"TableID = #TableID) " + Environment.NewLine +
" select 1" + Environment.NewLine +
"ELSE " + Environment.NewLine +
"select 0 " + Environment.NewLine;
SqlParameter parameterMappingTableName = new SqlParameter("#MappingTableName", vipMappingTableName);
SqlParameter parameterSchemaNameInBranch = new SqlParameter("#SchemaNameInBranch", schemaName);
SqlParameter parameterPrimaryKeyInBranch = new SqlParameter("#PrimaryKeyID", primaryNodeId);
SqlParameter parameterBranchNo = new SqlParameter("#BranchNo", branchNo);
SqlParameter parameterTableId = new SqlParameter("#TableID", tableId);
SqlParameter parameterTableName = new SqlParameter("#TableName", tableName);
DbRawSqlQuery<int> result = rawDbContext.Database.SqlQuery<int>(sqlCommandString,
new[] {
parameterMappingTableName,
parameterSchemaNameInBranch,
parameterPrimaryKeyInBranch,
parameterBranchNo,
parameterTableId,
parameterTableName
});
int finalResult = result.Single();
Running this query leads to excpetion "Must declare the table variable \"#MappingTableName\"."
How can I fix this?
Check this from Microsoft forums
Database objects (tables, stored procedures or any other objects)
cannot be passed as parameters. Only actual values for columns or
variables can be parameters. You need to build your SQL statement
dynamically in this case
Which basically means that you have to provide and/or build the table name, under the danger that this can be compromised.
How to mitigate the risk. Declare a set of probable table name and do an exact match.
Then build your query with text concatenation. This is something that can't be done with parameters cause you can't expect the possible values, but can be done with tables because they are only so many. Be carefull to use Equals instead of Contains in your list of names.
I have the following code:
private void dataGridView1_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
{
string age = dataGridView1.Rows[e.RowIndex].Cells["dataGridViewTextBoxColumn43"].Value.ToString();
dataGridView1.Rows[e.RowIndex].Cells["dataGridViewTextBoxColumn43"].Value = (age == "1") ? "Муж" : "Жен";
}
When I run program it gives fatal message:
In database field gender is as integer type. This value should be added to column name: dataGridViewTextBoxColumn43.
Query to database:
public DataTable select(SQLiteDatabase db)
{
return db.GetDataTable("SELECT " +
"Pacients.id, " +
"unique_code," +
"status_pass, " +
"payment, " +
"profession," +
"office_address, " +
"factory_name, " +
"factory_edrpou, " +
"factory_departament," +
"name, " +
"secondname, " +
"lastname, " +
"datebirth, " +
"taxcode, " +
"gender, " +
"Pacients.created_at, " +
"file, " +
"PacientsOrder.kind_work, " +
"PacientsOrder.status " +
"FROM Pacients LEFT JOIN PacientsOrder ON PacientsOrder.pacient_id = Pacients.id LEFT JOIN Transactions ON Transactions.pacient_id = Pacients.id ORDER BY Pacients.id DESC");
}
If the column ValueType is numeric, you can change the number format in the designer to Муж;;Жен
dataGridView1.Columns["dataGridViewTextBoxColumn43"].DefaultCellStyle.Format = "Муж;;Жен";
If I understand you correctly, you are trying to add a text value to a column, based on an integer value which is currently in the same column (ie you are switching column value types)?
Please do not do it this way, as it will not work for several reasons. Apart from your error, the most important being that this event is fired when you set the DataSource of your DataGridView for every row created, but the e.RowIndex is not always the RowIndex of the new row. For full details read here.
Normally you would only use RowsAdded when the user has inserted a new row from the interface.
What you should do instead, is to provide this conversion in your SELECT statement that reads the data from the database. That way you do not need to convert the data when it hits the DataGridView. So your SELECT needs to be something like:
SELECT .... CASE WHEN gender = 1 THEN 'МУЖ' ELSE 'ЖЕН' END AS gender ...
Edit
Try changing your SELECT statement so it reads as follows:
public DataTable select(SQLiteDatabase db) {
return db.GetDataTable("SELECT " +
"Pacients.id, " +
"unique_code," +
"status_pass, " +
"payment, " +
"profession," +
"office_address, " +
"factory_name, " +
"factory_edrpou, " +
"factory_departament," +
"name, " +
"secondname, " +
"lastname, " +
"datebirth, " +
"taxcode, " +
"CASE WHEN gender = 1 THEN 'МУЖ' ELSE 'ЖЕН' END AS gender, " +
"Pacients.created_at, " +
"file, " +
"PacientsOrder.kind_work, " +
"PacientsOrder.status " +
"FROM Pacients LEFT JOIN PacientsOrder ON PacientsOrder.pacient_id = Pacients.id LEFT JOIN Transactions ON Transactions.pacient_id = Pacients.id ORDER BY Pacients.id DESC");
}
Now you can get rid of the add rows event completely, as the database has done the work for you, before it hits the datagridview.
The problem was the folowing, it is obvios, but not clear at once:
The gender field is stored in database as integer type.
So, when I bind DataGridView with existing database table It allocates memory for building table with defination all properties of table, including cell types.
Therefore, when it happends at the first time, the datagridview expects to get integer data type as value, but I modify the value cell to string value and try to overwrite value.
It involkes an fatal error.
Solution was to change all data types that have got integer to string type.
Thanks for answers, it will be accepted!
I'm currently attempting to introduce an update option for my form project. I can successfully save entries to the database, but I want to be able to update these entries if the user gets information in the future that needs to be updated within the database...
Currently my error is, "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'"lossID=8, 25 Oct, 00:00, 25 Oct, 23:59,","" at line 1.
I thought this would be from perhaps the set syntax but I get the same error if I remove it or change anything there. I'm not sure if its because I am using parameters for my insert function, and perhaps just missing something?
My code for this is,
if (start_time.Text == end_time.Text)
{
MessageBox.Show("Please input a different ending time for the loss event");
}
else
{
string constring = "datasource=localhost;port=3306;username=root;password=1234; ";
string query = "update lossdatabase.losstable set (lossID= '" + this.textBox1.Text + "', #Start, #Start_Time, #End, #End_Time, #Equipment, #Event, #Responsibility, #Cause, #Reason, Capacity_Loss='" + capacity + "', Planned= '" + Planned + "', Scheduled='" + Scheduled + "', Prepared='" + Prepared + "', #Primary_Rate, #Primary_Volume, #Primary_Percentage, #Secondary_Rate, #Secondary_Volume, #Secondary_Percentage, #Comment) where lossID= '" + this.textBox1.Text + "' ;";
//Defines the connection string to allow data to be deposited into the database, along with defining the variables and columns for the data to be added to
MySqlConnection conLossDB = new MySqlConnection(constring);
MySqlCommand cmdLossDB = new MySqlCommand(query, conLossDB);
cmdLossDB.Parameters.AddWithValue("#Start", start_date.Text);
cmdLossDB.Parameters.AddWithValue("#Start_Time", start_time.Text);
cmdLossDB.Parameters.AddWithValue("#End", end_date.Text);
cmdLossDB.Parameters.AddWithValue("#End_Time", end_time.Text);
cmdLossDB.Parameters.AddWithValue("#Equipment", comboBox1.Text);
cmdLossDB.Parameters.AddWithValue("#Event", comboBox2.Text);
cmdLossDB.Parameters.AddWithValue("#Responsibility", comboBox3.Text);
cmdLossDB.Parameters.AddWithValue("#Cause", richTextBox1.Text);
cmdLossDB.Parameters.AddWithValue("#Reason", richTextBox2.Text);
cmdLossDB.Parameters.AddWithValue("#Primary_Rate", Rate_box.Text);
cmdLossDB.Parameters.AddWithValue("#Primary_Volume", Volume_box.Text);
cmdLossDB.Parameters.AddWithValue("#Primary_Percentage", Percentage_box.Text);
cmdLossDB.Parameters.AddWithValue("#Secondary_Rate", Rate_2.Text);
cmdLossDB.Parameters.AddWithValue("#Secondary_Volume", Volume_2.Text);
cmdLossDB.Parameters.AddWithValue("#Secondary_Percentage", Percentage_2.Text);
cmdLossDB.Parameters.AddWithValue("#Comment", richTextBox3.Text);
//Defines which boxes to read in order to input the text from the defined boxes into the corresponding columns
MySqlDataReader myReader;
try
{
conLossDB.Open();
myReader = cmdLossDB.ExecuteReader();
MessageBox.Show("The loss entry has successfully been updated");
//Opens the database and carries out the defined command outlined in the code above
this.Close();
while (myReader.Read())
{
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
So I have the following code :
public static void WriteToDatabase(string sql,string value,int Amount, string URL)
{
int times = int.Parse(((dr)[dt.Columns[1]]).ToString()) + Amount;
sql = "UPDATE Words "+
" SET Amount = " + times +
" WHERE Word = " + value +
" AND Website = " + URL + ";";
myAdp = new OleDbDataAdapter();
myAdp.InsertCommand = new OleDbCommand(sql, myConn);
myAdp.InsertCommand.ExecuteNonQuery();
}
Which supposed to update a value in a pre-made Microsoft Access 2007 file,
and whenever I run the code they following OleDb exception occurs :
An unhandled exception of type 'System.Data.OleDb.OleDbException' occurred in System.Data.dll ,
Syntax error missing operator in query expression : 'Word = meta AND Website = http://www.twitch.tv/directory'."
"
So I've searched the web for common errors that could happen, and I couldn't find any,
I'll be glad if someone can find the mistake in the sql.
Thanks.
You absolutely should be using parameterized queries for this. That is the right way to pass values in.
Your problem is that your query is missing single quotes:
"UPDATE Words "+
" SET Amount = " + times +
" WHERE Word = '" + value + "'" +
" AND Website = '" + URL + "'"
But let me re-emphasize that although this should work, you should fix the code so it uses parameters
Assuming the Word field is a varchar, you have forgotten the necessary single quotes around the variable. " WHERE Word = '" + value + "'"
I am developing a program that uses a relational database. In one particular form I am trying to insert new products information into the database.
using System.Data.OleDb;
When I try to save a new product this code runs...
connection.Open();
OleDbCommand command = new OleDbCommand();
command.Connection = connection;
string query = "insert into Products (ProductName,ProductSKU,RP,WP,Stock,FPS,Ammo,MagazineCap,HopUp,Range,Brand,Colour,Action,Features) values('" + txt_ProductName.Text + "','" + txt_SKU.Text + "'," + txt_RP.Text + "," + txt_WP.Text + "," + numericUpDown_Inventory.Value + "," + cobo_FPS.Text + ",'" + cobo_Ammo.Text + "'," + cobo_MagazineCap.Text + ",'" + cobo_HopUp.Text + "'," + cobo_Range.Text + ",'" + cobo_Brand.Text + "','" + cobo_Colour.Text + "','" + cobo_Action.Text + "','" + txt_Features.Text + "')";
//Action field currently causes an error
MessageBox.Show(query);
command.CommandText = query;
command.ExecuteNonQuery();
connection.Close();
...and an error is thrown
"Error System.Data.OleDb.OleDbException (0x80040E14): Syntax error in
INSERT INTO statement."
(and then a bunch of stuff which I don't think is important)
Apologies for the HUGE SQL query. I am using the exact same method of using the insert SQL query in several other places in my program and they all work completely fine. This example however is causing this error. Through the tedious process of "commenting out" individual parts of my SQL query I found that the error lies with the "Action" field. I have checked that the data type in my database is correct and that I am using the '' punctuation to surround the text string that is being inserted into the database.
I think I've checked everything, so why am I still getting this error?
Many thanks in advance and if more information is required just let me know ;)
Action is a reserved keyword in OLE DB Provider. You need to use it with square brackets like [Action]. As a best practice, change it to non-reserved word.
But more impontant
You should always use parameterized queries. This kind of string concatenations are open for SQL Injection attacks.
Also use using statement to dispose your OleDbConnection and OleDbCommand automatically instead of calling .Close() method manually.