sql >> Database teknologi >  >> RDS >> Mysql

Opdatering af MySQL returnerer berørte rækker, men opdaterer faktisk ikke databasen

Den enkleste måde, du måske ønsker at se nærmere på, kan være at TRUNCATE destinationstabellen og derefter blot gemme XML-importen til den (med AI slået fra, så den bruger det importerede ID, hvis det er nødvendigt). Det eneste problem kan være med rettighederne til at gøre det. Ellers...

Det, du forsøger at gøre, kan næsten håndteres ved hjælp af Merge metode. Den kan/vil dog ikke vide om slettede rækker. Da metoden virker på DataTables , hvis en række blev slettet i masterdatabasen, vil den simpelthen ikke eksistere i XML-uddraget (versus en RowState af Deleted ). Disse kan luges ud med en løkke.

Ligeledes kan alle nye rækker få en anden PK for en AI int. For at forhindre det skal du blot bruge en simpel ikke-AI PK i destinationsdatabasen, så den kan acceptere et hvilket som helst nummer.

XML-indlæsningen:

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

Fletningskoden:

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

Uanset årsagen, rowsChanged rapporterer altid lige så mange ændringer, som der er samlede rækker. Men ændringer fra Master/XML-datatabellen går igennem til den anden/destinationstabel.

Slettekoden får en liste over eksisterende id'er og bestemmer derefter, hvilke rækker der skal slettes fra destinationsdatatabellen ved, om den nye XML-tabel har en række med dette id eller ej. Alle de manglende rækker slettes, hvorefter tabellerne slås sammen.

Nøglen er dtSample.Merge(dtMaster,false, MissingSchemaAction.Add); som fletter dataene fra dtMaster med dtSample . false param er det, der tillader de indkommende XML-ændringer at overskrive værdier i den anden tabel (og til sidst gemmes i db).

Jeg aner ikke, om nogle af problemerne som ikke-matchende AI PK'er er en big deal eller ej, men dette ser ud til at håndtere alt, hvad jeg kunne finde. I virkeligheden er det, du forsøger at gøre, Databasesynkronisering . Selvom med én tabel og kun et par rækker, burde ovenstående fungere.




  1. Anbefalet metode til at importere en .csv-fil til Microsoft SQL Server 2008 R2?

  2. Simpel Postgresql-erklæring - kolonnenavn findes ikke

  3. Mysql-forespørgsel for at udtrække domæner fra webadresser

  4. Få en liste over databaser fra SQL Server