Подтвердить что ты не робот

Сравнить различия между двумя таблицами в mysql

То же, что oracle diff: как сравнить две таблицы?, за исключением mysql.

Предположим, что у меня есть две таблицы: t1 и t2, которые идентичны в макете, но могут содержать разные данные.

Каков наилучший способ разграничения этих двух таблиц?

Чтобы быть более точным, я пытаюсь выяснить простой SQL-запрос, который говорит мне, если данные из одной строки в t1 отличаются от данных из соответствующей строки в t2

Кажется, я не могу использовать пересечение или минус. Когда я пытаюсь

SELECT * FROM robot intersect SELECT * FROM tbd_robot

Я получаю код ошибки:

[Код ошибки: 1064, Состояние SQL: 42000] У вас есть ошибка в вашем SQL синтаксис; проверьте руководство, соответствующее версии вашего сервера MySQL. для правильного синтаксиса для использования рядом с 'SELECT * FROM tbd_robot' в строке 1

Я делаю что-то синтаксически неправильно? Если нет, есть ли другой запрос, который я могу использовать?

Изменить: Кроме того, я просматриваю бесплатную версию DbVisualizer. Не уверен, что это может быть фактором.

4b9b3361

Ответ 1

INTERSECT необходимо эмулировать в 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
        )

Изменить: добавлено `вокруг слов: set

Ответ 2

Вы можете построить пересечение вручную с помощью UNION. Это легко, если у вас есть уникальное поле в обеих таблицах, например. ID:

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

UNION

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

Если у вас нет уникального значения, вы все равно можете расширить указанный выше код, чтобы проверить все поля, а не только идентификатор, и использовать AND для их соединения (например, ID NOT IN (...) AND OTHER_FIELD NOT IN (...) и т.д.)

Ответ 3

Я нашел другое решение в этой

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

Ответ 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

попробуйте это. Это позволит сравнить вашу таблицу и найти все совпадающие пары, если какое-либо несоответствие возвращает NULL слева.

Ответ 5

На основе ответа Haim я создал PHP-код для тестирования и отображения всех различий между двумя базами данных. Это также будет отображаться, если таблица присутствует в исходных или тестовых базах данных. Вы должны изменить с вашими данными содержимое < > 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!";

        }

    }

?>