Mysql
 sql >> база данни >  >> RDS >> Mysql

Актуализирането на MySQL връща засегнатите редове, но всъщност не актуализира базата данни

Най-простият начин, който може да искате да разгледате, може да бъде да ОТРЕЖЕТЕ целевата таблица, след което просто да запишете импортирания XML в нея (с изключен AI, така че да използва импортирания идентификатор, ако е необходимо). Единственият проблем може да е с правата за това. В противен случай...

Това, което се опитвате да направите, можепочти се обработва с помощта на Merge метод. Той обаче не може/не иска да знае за изтрити редове. Тъй като методът действа върху DataTables , ако ред е бил изтрит в основната база данни, той просто няма да съществува в XML извлечението (срещу RowState от Deleted ). Те могат да бъдат премахнати с примка.

По същия начин всички нови редове може да получат различен PK за AI int. За да предотвратите това, просто използвайте прост не-AI PK в целевата база данни, така че да може да приема произволен номер.

Зареждането на XML:

private DataTable LoadXMLToDT(string filename)
{
    DataTable dt = new DataTable();
    dt.ReadXml(filename);
    return dt;
}

Кодът за сливане:

DataTable dtMaster = LoadXMLToDT(@"C:\Temp\dtsample.xml");
// just a debug monitor
var changes = dtMaster.GetChanges();

string SQL = "SELECT * FROM Destination";
using (MySqlConnection dbCon = new MySqlConnection(MySQLOtherDB))
{
    dtSample = new DataTable();
    daSample = new MySqlDataAdapter(SQL, dbCon);

    MySqlCommandBuilder cb = new MySqlCommandBuilder(daSample);
    daSample.UpdateCommand = cb.GetUpdateCommand();
    daSample.DeleteCommand = cb.GetDeleteCommand();
    daSample.InsertCommand = cb.GetInsertCommand();
    daSample.FillSchema(dtSample, SchemaType.Source);
    dbCon.Open();

    // the destination table
    daSample.Fill(dtSample);

    // handle deleted rows
    var drExisting = dtMaster.AsEnumerable()
                .Select(x => x.Field<int>("Id"));
    var drMasterDeleted = dtSample.AsEnumerable()
                .Where( q => !drExisting.Contains(q.Field<int>("Id")));

    // delete based on missing ID
    foreach (DataRow dr in drMasterDeleted)
        dr.Delete();

    // merge the XML into the tbl read
    dtSample.Merge(dtMaster,false, MissingSchemaAction.Add);

    int rowsChanged = daSample.Update(dtSample);
}

По някаква причина, rowsChanged винаги отчита толкова промени, колкото има общо редове. Но промените от Master/XML DataTable преминават към другата/целевата таблица.

Кодът за изтриване получава списък със съществуващи идентификатори, след което определя кои редове трябва да бъдат изтрити от целевата DataTable според това дали новата XML таблица има ред с този идентификатор или не. Всички липсващи редове се изтриват, след което таблиците се обединяват.

Ключът е dtSample.Merge(dtMaster,false, MissingSchemaAction.Add); който обединява данните от dtMaster с dtSample . false param е това, което позволява на входящите XML промени да презаписват стойности в другата таблица (и в крайна сметка да бъдат записани в db).

Нямам представа дали някои от проблемите, като несъответстващи AI PK, са голяма работа или не, но това изглежда се справя с всичко, което успях да намеря. В действителност това, което се опитвате да направите, е Синхронизиране на база данни . Въпреки че с една таблица и само няколко реда, горното трябва да работи.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Пространствен индекс в MySQL - ГРЕШКА - Не може да се получи геометричен обект от данните, които изпращате в полето GEOMETRY

  2. Как да изградите неограничено ниво на меню чрез PHP и mysql

  3. Нов драйвер за MySQL причинява java.sql.SQLNonTransientConnectionException:изисква се CLIENT_PLUGIN_AUTH

  4. Mysql - повторно използване на изчислени стойности

  5. MySQL Regexp поддържа ли съвпадение на Unicode