sql >> Databáze >  >> RDS >> Mysql

Aktualizace MySQL vrátí dotčené řádky, ale ve skutečnosti neaktualizuje databázi

Nejjednodušší způsob, kterým se možná budete chtít podívat, je ZKRÁTIT cílovou tabulku a poté do ní jednoduše uložit import XML (s vypnutou AI, aby v případě potřeby použila importované ID). Jediný problém může být s právy k tomu. Jinak...

To, o co se snažíte, může téměř lze zpracovat pomocí Merge metoda. Nemůže/nebude však vědět o smazaných řádcích. Protože metoda funguje na DataTables , pokud byl řádek smazán v hlavní databázi, nebude jednoduše existovat v XML extraktu (oproti RowState z Deleted ). Ty lze odplevelit smyčkou.

Podobně mohou jakékoli nové řádky získat jinou PK pro AI int. Abyste tomu zabránili, stačí v cílové databázi použít jednoduchý PK bez AI, aby mohl přijímat libovolné číslo.

Načítání XML:

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

Slučovací kód:

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);
}

Z jakéhokoli důvodu rowsChanged vždy hlásí tolik změn, kolik je celkem řádků. Změny z Master/XML DataTable však procházejí do jiné/cílové tabulky.

Odstraňovací kód získá seznam existujících ID a poté určí, které řádky je třeba odstranit z cílové tabulky DataTable podle toho, zda nová tabulka XML obsahuje řádek s tímto ID nebo ne. Všechny chybějící řádky jsou odstraněny a tabulky jsou sloučeny.

Klíč je dtSample.Merge(dtMaster,false, MissingSchemaAction.Add); který sloučí data z dtMaster pomocí dtSample . false param je to, co umožňuje příchozím změnám XML přepsat hodnoty v jiné tabulce (a případně je uložit do db).

Nemám ponětí, zda jsou některé problémy, jako jsou neodpovídající AI PK, velký problém nebo ne, ale zdá se, že to zvládne vše, co jsem našel. Ve skutečnosti se snažíte udělat Synchronizace databáze . Ačkoli s jednou tabulkou a jen několika řádky by výše uvedené mělo fungovat.




  1. Řešení pro:Příkaz Store update, insert nebo delete ovlivnil neočekávaný počet řádků (0)

  2. Jak mohu vybrat 10., 20., 30. ... řádek výsledku jiného výběrového dotazu

  3. Nelze najít MySQL v NodeJS pomocí AWS Lambda

  4. Migrace django db se nezdařila s postgres