2009-06-04 71 views
46

Igual que oracle diff: how to compare two tables? excepto en mysql.compare las diferencias entre dos tablas en mysql

Supongamos que tengo dos tablas, t1 y t2 que son idénticas en el diseño pero que pueden contener datos diferentes.

¿Cuál es la mejor manera de diferenciar estas dos tablas?

Para ser más precisos, estoy tratando de encontrar una consulta SQL simple que me dice que si los datos de una fila en T1 es diferente de los datos de la fila correspondiente en t2

Parece que no puede usar la intersección ni menos. Cuando intento

SELECT * FROM robot intersect SELECT * FROM tbd_robot 

consigo un código de error:

[Código de error: 1064, SQL Estado: 42000] Usted tiene un error en su sintaxis SQL ; compruebe el manual que corresponde a su versión del servidor MySQL para el sintaxis derecho al uso cerca de 'SELECT * FROM tbd_robot' at line 1

Estoy haciendo algo sintácticamente mal? Si no, ¿hay otra consulta que pueda usar?

Editar: Además, estoy consultando a través de una versión gratuita DbVisualizer. No estoy seguro de si eso podría ser un factor.

Respuesta

65

INTERSECT debe ser emulado en MySQL:

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 
     ) 

Editar: `añadió alrededor de las palabras: Conjunto

+1

¡Increíble, gracias! Aparentemente, no necesitaba la parte "tal como está configurada", pero ahora funciona – echoblaze

+0

¡Excelente! Esto es lo que estaba buscando. Y también sé acerca de FILA (...) EN (...) cosa ahora – Imdad

+2

¿Alguna idea de cómo hacerlo sin tener que escribir todos los campos? – Veve

53

Puede construir la intersección manualmente usando UNION. Es fácil si tiene algún campo único en ambas tablas, p. ID:

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

UNION 

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

Si usted no tiene un valor único, todavía se puede ampliar el código anterior para comprobar todos los campos en lugar de sólo la identificación, y usar AND para conectarlas (por ejemplo ID NO EN (. ..) Y NO eN OTHER_FIELD (...), etc)

+2

respuesta impresionante. –

+1

solución elegante, @Roee Adler! – Chubaka

+0

Gracias. Esto está trabajado. –

8

encontré otra solución en este 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

hola, +1. Estaba buscando exactamente lo mismo. – Hussain

+0

@ haim-evgi ignora los duplicados. Supongamos que una tabla tiene una fila y otra tabla tiene esas dos filas, por lo que ignorará esto. of-course, Considerando que no hay campos PK en ambas tablas. ¿Cómo lo manejaríamos en este caso? –

+0

Tuve que usar '' COUNT (*) '' en lugar de '' COUNT (*) ''. – Rolf

2

Sobre la base de la respuesta de Haim I creó un código PHP para probar y mostrar todas las diferencias entre dos bases de datos. Esto también se mostrará si hay una tabla presente en las bases de datos de origen o de prueba. Tiene que cambiar con sus detalles el contenido <> variables.

<?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

Pedir +1 reduce sus posibilidades de obtenerlo. Stack Overflow tiene una cola de revisión, se anima a las personas a votar las preguntas y respuestas que quieran. una respuesta decente puede obtener un voto positivo o dos. Hay una insignia de bronce para las respuestas que 10 votaciones ascendentes ("buena respuesta"), 25 votaciones ascendentes: "buena respuesta" (insignia de plata) y 100 votaciones ascendentes "gran respuesta" (insignia de oro). las votaciones por lo general generalmente se modifican lentamente, dependiendo de la pregunta, respuesta y tema. Puede llevar semanas, meses o años obtener una gran cantidad de votos favorables, ya que no muchas personas pueden ver la pregunta o su respuesta, o pueden ser respuestas competitivas que roban el programa. – clearlight

+0

Recomiendo el [2-Minute Tour] (http://stackoverflow.com/tour). Eso te dará más información sobre lo que sucede aquí. Parece que estás listo para el desafío, aprende rápido y haz un buen trabajo. Debería poder hacer crecer rápidamente su reputación y privilegios de sitio, y trabajar en algunas insignias para mostrar sus contribuciones también. ¡Buena suerte! Y bienvenido. – 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 

probar esto. Esto comparará su tabla y encontrará todos los pares que coincidan, si no coinciden, devuelva NULL a la izquierda.

+0

¡Esta es la mejor y más eficaz respuesta para la pregunta! ¡Gracias! –

+0

asegúrese de usar ifnull (t1.field_name, 1) = ifnull (t2.field_name, 1) para asegurarse de eliminar los falsos positivos. –

Cuestiones relacionadas