I currently have a data table which adds new rows based on the Access table rows. In the data table, I change the value of certain columns and update them back to the database. I want to write a line of code that overwrites the data if the primary key already exists. I already looked into a query INSERT INTO table (id, name, age) VALUES(1, "A", 19) ON DUPLICATE KEY UPDATE name="A", age=19 but I can't find a way to implement this since i'm using a data adapter.
I have made the following code:
for (int i = 1; i < 19; i++)
{
Normen.Clear();
Normen.Add(-1);
for (int j = 9; j < 18; j++)
{
Normen.Add(Convert.ToInt32(NormDb.Rows[j].Field<double>(i)));
}
newRow[i] = Convert.ToInt32(GlobalMethods.LeftSegmentIndex(Normen, Convert.ToInt32(newRow[i + 18])));
}
schoolDb.Rows.Add(newRow);
Normen is in this case a list with integers i use to calculate test scores which are then inserted into the empty columns i fetched from the database table.
when this code runs, i have a datatable with rows and columns which are identical to the database columns. When this code is done, the other method is triggered to update the data into the datatable like this:
using (var dbcommand = new OleDbCommand(ZoekQuery, connection))
{
using (var SchoolAdapter = new OleDbDataAdapter(ZoekQuery, connection))
{
OleDbCommandBuilder cb = new OleDbCommandBuilder(SchoolAdapter);
cb.GetInsertCommand();
SchoolAdapter.FillSchema(schoolDb, SchemaType.Source);
SchoolAdapter.Fill(schoolDb);
Normeringen.Normeer(exportDb.Rows.Count, schoolDb, exportDb, NormDb, normcode);
SchoolAdapter.Update(schoolDb);
MessageBox.Show(Success);
}
}
But when the primary key already exists i want to overwrite the record because in this use case it is possible to grade a test with 2 different values. Is there any way i can implement this?
Related
I am using SQL Bulk copy to read data form Excel to SQL DB. In the Database, I have two tables into which I need to insert this data from Excel. Table A and Table B which uses the ID(primary Key IDENTITY) from Table A to insert corresponding row records into Table B.
I am able to insert into one table (Table A) using the following Code.
using (SqlConnection connection = new SqlConnection(strConnection)) {
connection.Open();
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connection)) {
bulkCopy.DestinationTableName = "dbo.[EMPLOYEEINFO]";
try {
// Write from the source to the destination.
SqlBulkCopyColumnMapping NameMap = new SqlBulkCopyColumnMapping(data.Columns[0].ColumnName, "EmployeeName");
SqlBulkCopyColumnMapping GMap = new SqlBulkCopyColumnMapping(data.Columns[1].ColumnName, "Gender");
SqlBulkCopyColumnMapping CMap = new SqlBulkCopyColumnMapping(data.Columns[2].ColumnName, "City");
SqlBulkCopyColumnMapping AMap = new SqlBulkCopyColumnMapping(data.Columns[3].ColumnName, "HomeAddress");
bulkCopy.ColumnMappings.Add(NameMap);
bulkCopy.ColumnMappings.Add(GMap);
bulkCopy.ColumnMappings.Add(CMap);
bulkCopy.ColumnMappings.Add(AMap);
bulkCopy.WriteToServer(data);
}
catch (Exception ex) {
Console.WriteLine(ex.Message);
}
}
}
But then I am not sure how to extend it for two tables which are bound by Foreign Key relationship.Especially, Table B uses the Identity value from Table A Any example would be great. I googled it and none of the threads on SO couldn't give a Working example.
AFAIK bulk copy can only be used to upload into a single table. In order to achieve a bulk upload into two tables, you will therefore need two bulk uploads. Your problem comes from using a foreign key which is an identity. You can work around this, however. I am pretty sure that bulk copy uploads sequentially, which means that if you upload 1,000 records and the last record gets an ID of 10,197, then the ID of the first record is 9,198! So my recommendation would be to upload your first table, check the max id after the upload, deduct the number of records and work from there!
Of course in a high use database, someone might insert after you, so you would need to get the top id by selecting the record which matches your last one by other details (assuming a combination of (upto) all fields would be guaranteed to be unique). Only you know if this is likely to be a problem.
The alternative is not to use an identity column in the first place, but I presume you have no control over the design? In my younger days, I made the mistake of using identities, I never do now. They always find a way of coming back to bite!
For example to add the second data:
DataTable secondTable = new DataTable("SecondTable");
secondTable.Columns.Add("ForeignKey", typeof(int));
secondTable.Columns.Add("DataField", typeof(yourDataType));
...
Add data to secondTable.
(Depends on format of second data)
int cnt = 0;
foreach (var d in mySecondData)
{
DataRow newRow = secondTable.NewRow();
newRow["ForeignKey"] = cnt;
newRow["DataField"] = d.YourData;
secondTable.Rows.Add(newRow);
}
Then after you found out the starting identity (int startID).
for (int i = 0; i < secondTable.Rows.Count; i++)
{
secondTable["ForeignKey"] = secondTable["ForeignKey"] + startID;
}
Finally:
bulkCopy.DestinationTableName = "YourSecondTable";
bulkCopy.WriteToServer(secondTable);
I'm trying to fetch data from multiple tables from an Oracle db and insert it into a sql db. The problem that I am running into is that I am fetching almost 50 columns of data all of different datatypes. I then proceed to insert these individual column values into a SQL statement which then inserts the data into the sql db. So the algo looks something like this:
Fetch row data{
create a variable for each individual column value ( int value = reader.getInt32(0); )
add a sqlparameter for it (command.Parameters.Add(new SqlParameter("value", value)); )
once all the 50 or so variables have been created make a sql statement
Insert into asdf values (value,........)
}
Doing it this way for a table with <10 columns seems ok but when it exceeds that length this process seems tedious and extraneous. I was wondering if there was a simpler way of doing this like fetch row data and automatically determine column data type and automatically create a varialbe and automatically insert into sql statement. I would appreciate it if anyone could direct me to the right way of doing this.
The data reader has a neutral GetValue method returning an object and the SqlCommand has an AddWithValue method that does not require to specify a parameter type.
for (int i = 0; i < reader.VisibleFieldCount; i++) {
object value = reader.GetValue(i);
command.Parameters.AddWithValue("#" + i, value);
}
You could also create the SQL command automatically
var columns = new StringBuilder();
var values = new StringBuilder();
for (int i = 0; i < reader.VisibleFieldCount; i++) {
values.Append("#").Append(i).Append(", ");
columns.Append("[").Append(reader.GetName(i)).Append("], ");
}
values.Length -= 2; // Remove last ", "
columns.Length -= 2;
string insert = String.Format("INSERT INTO myTable ({0}) VALUES ({1})",
columns.ToString(), values.ToString());
I need to insert data from two data table to table
my table
has three columns
(ID , wordId,docId,value)
my code
DataTable document = new DataTable();
dt = WTA.GetData();
document = AFS.GetTheDocument();
foreach (DataRow dr in dt.Rows)
{
for (int i = 0; i < document.Rows.Count; i++)
{
double TFij = VSM.getTF(document.Rows[i]["document"].ToString(),
dr["word"].ToString());
DITA.Insert(Convert.ToInt32(document.Rows[i]["id"]),
Convert.ToInt32(dr["id"]), TFij);
}
}
I get an error
:conflict FK ;
I know some problem with my loops .....
If you are getting a conflict with a foreign key then you are likely running into an issue with the database layout.
Perhaps you have a table where the wordid or the docid has to be registered first. Have a look at your database structure as you might need to insert the doc and word id's first and then add them to this table.
i have one column in my database by name PNUMSET (Primary Key) contains unique data.(approx 1L rows)
and in application i have one datatable with one column name NEWPNUM which contains data.
i want to check that no value is matching between existing database and current datatable values..
Note:- no of rows may or may not be same in database and datatable.
so far i tried.....
String query = "Select PNUMSET FROM DUMMYTABLE";
MySqlDataAdapter msda = new MySqlDataAdapter(query, connection);
msda.Fill(dt);
for (int k = 0; k < Class1.global_dataset.Tables[0].Rows.Count; k++)
{
if (dt.Rows.Contains(Class1.global_dataset.Tables[0].Rows[k][4].ToString()))
{
MessageBox.Show("Baj Gaya Ghanta!!!!");
}
}
You can use Linq-To-DataTable to join both tables on this column, for example:
var commonRows = from r1 in dt.AsEnumerable()
join r2 in Class1.global_dataset.Tables[0].AsEnumerable()
on r1.Field<int>(4) equals r2.Field<int>(4)
select r1;
if(commonRows.Any())
{
// do something with these rows
}
(assuming the 5th column and it's type int)
Note that although Enumerable.Join is quite efficient it might be better to compare this in the database instead of loading all into memory.
Regarding the Sqlite insert or replace command.
I am doing the insert if does not exist.
The inserted/updated values come from the datagridview bound to a datatable.
The datatable has a TID column which is the primary key. It also has other columns like Tname,TUtility....
For update statement TID has a value and works well. But for an insert statement I want the serial number(which is the TID column) to be automatically populated.
private void SaveData(DataGridView dgv)
{
using (SQLiteConnection conn = new SQLiteConnection(connString))
{
conn.Open();
dt = dt.GetChanges();
if (dt.Rows.Count > 0)
{
int dtlength = dt.Rows.Count;
DataRow[] arr = new DataRow[dtlength];
dt.Rows.CopyTo(arr, 0);
SQLiteCommand upCmd = new SQLiteCommand(
#"INSERT OR REPLACE
INTO
[Table1](
[TID],
[TName],
[TUtility],
[TType])values(#TID,#Tname,#TUtility,#TType),conn);
for (int i = 0; i < arr.Length; i++)
{
upCmd.Parameters.AddWithValue("#TID", Convert.ToInt32(arr[i]["SNo"]));
upCmd.Parameters.AddWithValue("#TName", arr[i]["Utility"].ToString());
upCmd.Parameters.AddWithValue("#TUtility", arr[i]["Plantname"].ToString());
upCmd.Parameters.AddWithValue("#TType", arr[i]["PlantType"].ToString())
da.UpdateCommand = upCmd;
this.da.UpdateCommand.ExecuteNonQuery();
}
How should I add this TID value in such a way that when the users inserts a new row, it should automatically put the serial number.
I mean: Suppose there are 4rows currently in the DGV. The DGV is in edit mode(*).I am adding a new row. Once the user tries to enter some data in the new row, there should be a serial number already populated.
Thank you
Sun
I am not sure if I understand your problem but why not just put NULL for TID when you do INSERT. Since TID is primary key, the sqlite will insert value automatically.
According to Sqlite FAQ it says this for primary key
whenever you insert a NULL into that column of the table, the NULL is
automatically converted into an integer which is one greater than the
largest value of that column over all other rows in the table, or 1 if
the table is empty.