2009-06-04 23 views
46

Wie oracle diff: how to compare two tables? außer in mysql.Vergleichen Sie Unterschiede zwischen zwei Tabellen in mysql

nehme an, ich habe zwei Tabellen, T1 und T2, die in das Layout identisch sind, aber unterschiedliche Daten enthalten.

Was ist der beste Weg, diese beiden Tabellen zu unterscheiden?

genauer zu sein, ich versuche, eine einfache SQL-Abfrage, um herauszufinden, die mir sagt, wenn Daten von einer Zeile in t1 aus den Daten der entsprechenden Zeile in t2 unterscheiden

Es I erscheint kann den Schnittpunkt oder das Minus nicht verwenden. Wenn ich versuche,

SELECT * FROM robot intersect SELECT * FROM tbd_robot 

Ich erhalte eine Fehlercode:

[Fehlercode: 1064, SQL-Status: 42000] Sie haben einen Fehler in Ihrer SQL-Syntax ; Sie in der Bedienungsanleitung ‚FROM tbd_robot SELECT *‘ at line 1

mache ich etwas syntaktisch falsch zu Ihrem MySQL-Server-Version für die richtige Syntax verwenden in der Nähe entspricht? Wenn nicht, gibt es eine andere Frage, die ich verwenden kann?

Edit: Auch ich frage durch eine kostenlose Version DbVisualizer. Nicht sicher, ob das ein Faktor sein könnte.

Antwort

65

INTERSECT Bedürfnisse in MySQL emuliert werden:

SELECT 'robot' AS `set`, r.* 
FROM robot r 
WHERE ROW(r.col1, r.col2, …) NOT IN 
     (
     SELECT * 
     FROM tbd_robot 
     ) 
UNION ALL 
SELECT 'tbd_robot' AS `set`, t.* 
FROM tbd_robot t 
WHERE ROW(t.col1, t.col2, …) NOT IN 
     (
     SELECT * 
     FROM robot 
     ) 

Edit: hat `um die Worte: set

+1

Super, danke! Anscheinend brauchte ich den "as set" -Teil nicht, aber es funktioniert jetzt – echoblaze

+0

Superb !. Das ist, was ich gesucht habe. Und ich lerne auch über ROW (...) IN (...) thing now kennen – Imdad

+2

Irgendeine Idee, wie man es macht, ohne jedes Feld schreiben zu müssen? – Veve

53

Sie können die Kreuzung manuell mit UNION erstellen. Es ist einfach, wenn Sie in beiden Tabellen ein eindeutiges Feld haben, z. ID:

SELECT * FROM T1 
WHERE ID NOT IN (SELECT ID FROM T2) 

UNION 

SELECT * FROM T2 
WHERE ID NOT IN (SELECT ID FROM T1) 

Wenn Sie nicht über einen eindeutigen Wert haben, können Sie immer noch den obigen Code erweitert für alle Felder, anstatt nur die ID zu überprüfen und verwenden und sie verbinden (zB ID NOT IN (. ..) und OTHER_FIELD NOT iN (...) usw.)

+2

ehrfürchtige Antwort. –

+1

elegante Lösung, @Roe Adler! – Chubaka

+0

Danke. Das ist gearbeitet. –

8

ich gefunden eine andere Lösung in diesem auf link

SELECT MIN (tbl_name) AS tbl_name, PK, column_list 
FROM 
(
    SELECT ' source_table ' as tbl_name, S.PK, S.column_list 
    FROM source_table AS S 
    UNION ALL 
    SELECT 'destination_table' as tbl_name, D.PK, D.column_list 
    FROM destination_table AS D 
) AS alias_table 
GROUP BY PK, column_list 
HAVING COUNT(*) = 1 
ORDER BY PK 
+1

Hallo, +1. Ich habe genau das Gleiche gesucht. – Hussain

+0

@ haim-evgi Ignorieren Duplikate..eine Tabelle haben eine Zeile und eine andere Tabelle haben solche zwei Zeilen, so wird es ignorieren. natürlich, wenn man bedenkt, dass in beiden Tabellen keine PK-Felder vorhanden sind. Wie würden wir in diesem Fall umgehen? –

+0

Ich musste '' COUNT (*) '' anstelle von '' COUNT (*) '' verwenden. – Rolf

2

Basierend Haim Antwort habe ich ein PHP-Code zu testen und alle Unterschiede zwischen zwei Datenbanken anzuzeigen. Dies wird auch angezeigt, wenn eine Tabelle in Quell- oder Testdatenbanken vorhanden ist. Sie müssen mit Ihren Details den Inhalt <> Variablen ändern.

<?php 

    $User = "<DatabaseUser>"; 
    $Pass = "<DatabasePassword>"; 
    $SourceDB = "<SourceDatabase>"; 
    $TestDB = "<DatabaseToTest>"; 

    $link = new mysqli("p:". "localhost", $User, $Pass, ""); 

    if (mysqli_connect_error()) { 

     die('Connect Error ('. mysqli_connect_errno() .') '. mysqli_connect_error()); 

    } 

    mysqli_set_charset($link, "utf8"); 
    mb_language("uni"); 
    mb_internal_encoding("UTF-8"); 

    $sQuery = 'SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA="'. $SourceDB .'";'; 

    $SourceDB_Content = query($link, $sQuery); 

    if (!is_array($SourceDB_Content)) { 

     echo "Table $SourceDB cannot be accessed"; 
     exit(0); 

    } 

    $sQuery = 'SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA="'. $TestDB .'";'; 

    $TestDB_Content = query($link, $sQuery); 

    if (!is_array($TestDB_Content)) { 

     echo "Table $TestDB cannot be accessed"; 
     exit(0); 

    } 

    $SourceDB_Tables = array(); 
    foreach($SourceDB_Content as $item) { 
     $SourceDB_Tables[] = $item["TABLE_NAME"]; 
    } 

    $TestDB_Tables = array(); 
    foreach($TestDB_Content as $item) { 
     $TestDB_Tables[] = $item["TABLE_NAME"]; 
    } 
    //var_dump($SourceDB_Tables, $TestDB_Tables); 
    $LookupTables = array_merge($SourceDB_Tables, $TestDB_Tables); 
    $NoOfDiscrepancies = 0; 
    echo " 

    <table border='1' width='100%'> 
    <tr> 
     <td>Table</td> 
     <td>Found in $SourceDB (". count($SourceDB_Tables) .")</td> 
     <td>Found in $TestDB (". count($TestDB_Tables) .")</td> 
     <td>Test result</td> 
    <tr> 

    "; 

    foreach($LookupTables as $table) { 

     $FoundInSourceDB = in_array($table, $SourceDB_Tables) ? 1 : 0; 
     $FoundInTestDB = in_array($table, $TestDB_Tables) ? 1 : 0; 
     echo " 

    <tr> 
     <td>$table</td> 
     <td><input type='checkbox' ". ($FoundInSourceDB == 1 ? "checked" : "") ."></td> 
     <td><input type='checkbox' ". ($FoundInTestDB == 1 ? "checked" : "") ."></td> 
     <td>". compareTables($SourceDB, $TestDB, $table) ."</td> 
    </tr> 
     "; 

    } 

    echo " 

    </table> 
    <br><br> 
    No of discrepancies found: $NoOfDiscrepancies 
    "; 


    function query($link, $q) { 

     $result = mysqli_query($link, $q); 

     $errors = mysqli_error($link); 
     if ($errors > "") { 

      echo $errors; 
      exit(0); 

     } 

     if($result == false) return false; 
     else if ($result === true) return true; 
     else { 

      $rset = array(); 

      while ($row = mysqli_fetch_assoc($result)) { 

       $rset[] = $row; 

      } 

      return $rset; 

     } 

    } 

    function compareTables($source, $test, $table) { 

     global $link; 
     global $NoOfDiscrepancies; 

     $sQuery = " 

    SELECT column_name,ordinal_position,data_type,column_type FROM 
    (
     SELECT 
      column_name,ordinal_position, 
      data_type,column_type,COUNT(1) rowcount 
     FROM information_schema.columns 
     WHERE 
     (
      (table_schema='$source' AND table_name='$table') OR 
      (table_schema='$test' AND table_name='$table') 
     ) 
     AND table_name IN ('$table') 
     GROUP BY 
      column_name,ordinal_position, 
      data_type,column_type 
     HAVING COUNT(1)=1 
    ) A;  

     "; 

     $result = query($link, $sQuery); 

     $data = ""; 
     if(is_array($result) && count($result) > 0) { 

      $NoOfDiscrepancies++; 
      $data = "<table><tr><td>column_name</td><td>ordinal_position</td><td>data_type</td><td>column_type</td></tr>"; 

      foreach($result as $item) { 

       $data .= "<tr><td>". $item["column_name"] ."</td><td>". $item["ordinal_position"] ."</td><td>". $item["data_type"] ."</td><td>". $item["column_type"] ."</td></tr>"; 

      } 

      $data .= "</table>"; 

      return $data; 

     } 
     else { 

      return "Checked but no discrepancies found!"; 

     } 

    } 

?> 
+0

Wenn Sie um +1 bitten, reduzieren Sie Ihre Chancen, es zu bekommen. Stack Overflow verfügt über eine Review-Warteschlange, in der die Leute aufgefordert werden, Fragen und Antworten abzustimmen. eine anständige Antwort kann eine oder zwei positive Stimmen bekommen. Es gibt ein Bronzeabzeichen für Antworten, die 10 upvotes ("nette Antwort"), 25 upvotes: "gute Antwort" (silbernes Abzeichen) und 100 upvotes "große Antwort" (Goldabzeichen). Upvotes werden normalerweise langsam eingezogen, abhängig von Frage, Antwort und Thema. Es kann Wochen, Monate oder Jahre dauern, um eine große Anzahl von Upvotes zu erhalten, da nicht viele Leute die Frage oder Ihre Antwort sehen oder konkurrierende Antworten, die die Show stehlen. – clearlight

+0

Ich empfehle die [2-Minuten-Tour] (http://stackoverflow.com/tour). Das wird dir mehr Informationen darüber geben, was hier passiert. Klingt nach der Herausforderung, lernt schnell und macht gute Arbeit. Du solltest in der Lage sein, deine Reputations- und Site-Privilegien schnell zu erweitern und an einigen Abzeichen zu arbeiten, um deine Beiträge zu zeigen. Viel Glück! Und willkommen. – clearlight

4
select t1.user_id,t2.user_id 
from t1 left join t2 ON t1.user_id = t2.user_id 
and t1.username=t2.username 
and t1.first_name=t2.first_name 
and t1.last_name=t2.last_name 

dies versuchen. Dies wird Ihre Tabelle vergleichen und alle übereinstimmenden Paare finden, wenn eine Nichtübereinstimmung NULL auf der linken Seite zurückgibt.

+0

Dies ist die beste und leistungsfähigste Antwort für die Frage! Vielen Dank! –

+0

stellen Sie sicher, dass Sie ifnull (t1.field_name, 1) = ifnull (t2.field_name, 1) verwenden, um sicherzustellen, dass Sie falsch positive Ergebnisse eliminieren. –

Verwandte Themen