compare differences between two tables in mysql

后端 未结 6 1492
北荒
北荒 2020-11-30 17:07

Same as oracle diff: how to compare two tables? except in mysql.

Suppose I have two tables, t1 and t2 which are identical in layout but which may contain

相关标签:
6条回答
  • 2020-11-30 17:35
     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
    

    try this. This will compare your table and find all matching pairs, if any mismatch return NULL on left.

    0 讨论(0)
  • 2020-11-30 17:35

    Based on Haim's answer here's a simplified example if you're looking to compare values that exist in BOTH tables, otherwise if there's a row in one table but not the other it will also return it....

    Took me a couple of hours to figure out. Here's a fully tested simply query for comparing "tbl_a" and "tbl_b"

    SELECT ID, col
    FROM
    (
        SELECT
        tbl_a.ID, tbl_a.col FROM tbl_a
        UNION ALL
        SELECT
        tbl_b.ID, tbl_b.col FROM tbl_b
    ) t
    WHERE ID IN (select ID from tbl_a) AND ID IN (select ID from tbl_b)
    GROUP BY
    ID, col
    HAVING COUNT(*) = 1
     ORDER BY ID
    

    So you need to add the extra "where in" clause:

    WHERE ID IN (select ID from tbl_a) AND ID IN (select ID from tbl_b)


    Also:

    For ease of reading if you want to indicate the table names you can use the following:

    SELECT tbl, ID, col
    FROM
    (
        SELECT
        tbl_a.ID, tbl_a.col, "name_to_display1" as "tbl" FROM tbl_a
        UNION ALL
        SELECT
        tbl_b.ID, tbl_b.col, "name_to_display2" as "tbl" FROM tbl_b
    ) t
    WHERE ID IN (select ID from tbl_a) AND ID IN (select ID from tbl_b)
    GROUP BY
    ID, col
    HAVING COUNT(*) = 1
     ORDER BY ID
    
    0 讨论(0)
  • 2020-11-30 17:42

    Based on Haim's answer I created a PHP code to test and display all the differences between two databases. This will also display if a table is present in source or test databases. You have to change with your details the <> variables content.

    <?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 讨论(0)
  • 2020-11-30 17:49

    You can construct the intersection manually using UNION. It's easy if you have some unique field in both tables, e.g. ID:

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

    If you don't have a unique value, you can still expand the above code to check for all fields instead of just the ID, and use AND to connect them (e.g. ID NOT IN(...) AND OTHER_FIELD NOT IN(...) etc)

    0 讨论(0)
  • 2020-11-30 17:49

    I found another solution in this 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
    
    0 讨论(0)
  • 2020-11-30 17:54

    INTERSECT needs to be emulated in MySQL:

    SELECT  'robot' AS `set`, r.*
    FROM    robot r
    WHERE   ROW(r.col1, r.col2, …) NOT IN
            (
            SELECT  col1, col2, ...
            FROM    tbd_robot
            )
    UNION ALL
    SELECT  'tbd_robot' AS `set`, t.*
    FROM    tbd_robot t
    WHERE   ROW(t.col1, t.col2, …) NOT IN
            (
            SELECT  col1, col2, ...
            FROM    robot
            )
    
    0 讨论(0)
提交回复
热议问题