Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Aktualizacja MySQL zwraca wiersze, których dotyczy problem, ale w rzeczywistości nie aktualizuje bazy danych

Najprostszym sposobem, który możesz chcieć, może być OBCIĄŻENIE tabeli docelowej, a następnie po prostu zapisanie w niej importu XML (z wyłączoną AI, aby w razie potrzeby używała zaimportowanego identyfikatora). Jedynym problemem mogą być prawa do tego. W przeciwnym razie...

To, co próbujesz zrobić, może prawie być obsługiwane za pomocą Merge metoda. Jednak nie może/nie będzie wiedzieć o usuniętych wierszach. Ponieważ metoda działa na DataTables , jeśli wiersz został usunięty z głównej bazy danych, po prostu nie będzie istniał w wyciągu XML (w przeciwieństwie do RowState z Deleted ). Można je usunąć za pomocą pętli.

Podobnie, każdy nowy wiersz może otrzymać inne PK dla int AI. Aby temu zapobiec, po prostu użyj prostego pliku PK innego niż AI w docelowej bazie danych, aby mógł zaakceptować dowolną liczbę.

Ładowanie XML:

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

Kod scalający:

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 jakiegoś powodu rowsChanged zawsze zgłasza tyle zmian, ile jest wszystkich wierszy. Ale zmiany z Master/XML DataTable przechodzą do innej/docelowej tabeli.

Kod usuwania pobiera listę istniejących identyfikatorów, a następnie określa, które wiersze należy usunąć z docelowej tabeli DataTable, określając, czy nowa tabela XML ma wiersz z tym identyfikatorem, czy nie. Wszystkie brakujące wiersze są usuwane, a następnie tabele są scalane.

Klucz to dtSample.Merge(dtMaster,false, MissingSchemaAction.Add); która łączy dane z dtMaster z dtSample . false parametr jest tym, co pozwala nadchodzącym zmianom XML nadpisać wartości w innej tabeli (i ostatecznie zapisać w bazie danych).

Nie mam pojęcia, czy niektóre problemy, takie jak niepasujące AI PK, to wielka sprawa, czy nie, ale wydaje się, że to wszystko, co udało mi się znaleźć. W rzeczywistości to, co próbujesz zrobić, to Synchronizacja bazy danych . Chociaż z jedną tabelą i tylko kilkoma rzędami, powyższe powinno działać.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Czy mogę na ślepo zastąpić wszystkie funkcje mysql_ mysqli_?

  2. MYSQL Wybierz 5 rekordów dla ostatnich 5 odrębnych rekordów

  3. MySQL group_concat z klauzulą ​​where

  4. MySQL - Konwertuj zduplikowaną wartość na unikatową z konkatenacją przyrostową

  5. używasz Dokumentów Google jako bazy danych?