sql >> Databasteknik >  >> RDS >> Mysql

Uppdatering av MySQL returnerar påverkade rader, men uppdaterar faktiskt inte databasen

Det enklaste sättet som du kanske vill undersöka kan vara att TRUNCATE destinationstabellen och sedan helt enkelt spara XML-importen till den (med AI avstängd så att den använder det importerade ID:t om det behövs). Det enda problemet kan vara med rättigheterna att göra det. Annars...

Det du försöker göra kan nästan hanteras med Merge metod. Däremot kan/vil den inte veta om borttagna rader. Eftersom metoden verkar på DataTables , om en rad raderades i huvuddatabasen, kommer den helt enkelt inte att finnas i XML-extraktet (mot en RowState av Deleted ). Dessa kan såras bort med en slinga.

På samma sätt kan alla nya rader få en annan PK för en AI-int. För att förhindra det, använd bara en enkel icke-AI PK i destinationsdatabasen så att den kan acceptera vilket nummer som helst.

XML-laddningen:

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

Sammanfogningskoden:

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

Av någon anledning, rowsChanged rapporterar alltid lika många ändringar som det finns totalt antal rader. Men ändringar från Master/XML DataTable går igenom till den andra/destinationstabellen.

Raderingskoden får en lista över befintliga ID:n och bestämmer sedan vilka rader som måste tas bort från destinationsdatatabellen genom att den nya XML-tabellen har en rad med det ID:t eller inte. Alla rader som saknas tas bort, sedan slås tabellerna samman.

Nyckeln är dtSample.Merge(dtMaster,false, MissingSchemaAction.Add); som slår samman data från dtMaster med dtSample . false param är det som gör att de inkommande XML-ändringarna kan skriva över värden i den andra tabellen (och så småningom sparas i db).

Jag har ingen aning om om några av problemen som icke-matchande AI PK är en stor sak eller inte, men det här verkar hantera allt jag kan hitta. I verkligheten är det du försöker göra Databassynkronisering . Även om med en tabell och bara några rader borde ovanstående fungera.




  1. Är det säkert att använda ROWID för att hitta en rad/post i Oracle?

  2. Quickbooks ODBC-drivrutin

  3. MySQL-fråga, 3 tabeller, t1-t2 uppdatera sedan t3. Hur kan jag göra detta på det mest effektiva sättet?

  4. Uppdaterar kolumnen till standardvärdet med SQLAlchemy