<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>PostgreSQL | 酷 壳 - CoolShell</title>
	<atom:link href="https://coolshell.cn/tag/postgresql/feed" rel="self" type="application/rss+xml" />
	<link>https://coolshell.cn</link>
	<description>享受编程和技术所带来的快乐 - Coding Your Ambition</description>
	<lastBuildDate>Wed, 27 May 2009 15:02:14 +0000</lastBuildDate>
	<language>zh-CN</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.2</generator>
	<item>
		<title>如何比较两个数据表</title>
		<link>https://coolshell.cn/articles/925.html</link>
					<comments>https://coolshell.cn/articles/925.html#comments</comments>
		
		<dc:creator><![CDATA[陈皓]]></dc:creator>
		<pubDate>Wed, 27 May 2009 15:02:14 +0000</pubDate>
				<category><![CDATA[数据库]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[SQL]]></category>
		<guid isPermaLink="false">http://coolshell.cn/?p=925</guid>

					<description><![CDATA[<p>有些时候，我们可能想要比较一下两个数据表，以找到其中不同的数据。比如，在进行数据移植的时候，或是在合并数据的时候，或是在比对验证数据的时候。当然比较两个表，需要...</p>
<p class="read-more"><a class="btn btn-default" href="https://coolshell.cn/articles/925.html"> Read More<span class="screen-reader-text">  Read More</span></a></p>
The post <a href="https://coolshell.cn/articles/925.html">如何比较两个数据表</a> first appeared on <a href="https://coolshell.cn">酷 壳 - CoolShell</a>.]]></description>
										<content:encoded><![CDATA[<p><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-3415450859608158"
     crossorigin="anonymous"></script>有些时候，我们可能想要比较一下两个数据表，以找到其中不同的数据。比如，在进行数据移植的时候，或是在合并数据的时候，或是在比对验证数据的时候。当然比较两个表，需要这两个表结构是一样的。</p>
<p>我们先假设一下有如下表结构：</p>
<pre data-enlighter-language="sql" class="EnlighterJSRAW">
CREATE TABLE jajal
(
    user_id integer NOT NULL,
    first_name character varying(255),
    last_name character varying(255),
    grade character(1),
    CONSTRAINT jajal_pkey PRIMARY KEY (user_id)
)
</pre>
<p><span id="more-925"></span><br />
然后，我们有两张表——jajal和jajal_copy，其内容如下：</p>
<h4> jajal</h4>
<table id="wptable-7" class="wptable rowstyle-alt" border="0" cellspacing="1">
<thead>
<tr>
<th class="sortable" style="width: 30px;" align="center">user_id</th>
<th class="sortable" style="width: 30px;" align="center">first_name</th>
<th class="sortable" style="width: 30px;" align="center">last_name</th>
<th class="sortable" style="width: 30px;" align="center">grade</th>
</tr>
</thead>
<tbody>
<tr>
<td style="width: 30px;" align="center">1</td>
<td style="width: 30px;" align="center">Some</td>
<td style="width: 30px;" align="center">Dude</td>
<td style="width: 30px;" align="center">A</td>
</tr>
<tr class="alt">
<td style="width: 30px;" align="center">2</td>
<td style="width: 30px;" align="center">Other</td>
<td style="width: 30px;" align="center">Guy</td>
<td style="width: 30px;" align="center">B</td>
</tr>
<tr>
<td style="width: 30px;" align="center">3</td>
<td style="width: 30px;" align="center">You are</td>
<td style="width: 30px;" align="center">Welcome</td>
<td style="width: 30px;" align="center">B</td>
</tr>
<tr class="alt">
<td style="width: 30px;" align="center">4</td>
<td style="width: 30px;" align="center">What</td>
<td style="width: 30px;" align="center">Other</td>
<td style="width: 30px;" align="center">A</td>
</tr>
<tr>
<td style="width: 30px;" align="center">5</td>
<td style="width: 30px;" align="center">INeed</td>
<td style="width: 30px;" align="center">You</td>
<td style="width: 30px;" align="center">C</td>
</tr>
<tr class="alt">
<td style="width: 30px;" align="center">6</td>
<td style="width: 30px;" align="center">Mixed</td>
<td style="width: 30px;" align="center">Nuts</td>
<td style="width: 30px;" align="center">Z</td>
</tr>
<tr>
<td style="width: 30px;" align="center">7</td>
<td style="width: 30px;" align="center">Kirk</td>
<td style="width: 30px;" align="center">Land</td>
<td style="width: 30px;" align="center">B</td>
</tr>
<tr class="alt">
<td style="width: 30px;" align="center">8</td>
<td style="width: 30px;" align="center">Bit</td>
<td style="width: 30px;" align="center">Shooter</td>
<td style="width: 30px;" align="center">A</td>
</tr>
<tr>
<td style="width: 30px;" align="center">9</td>
<td style="width: 30px;" align="center">Sun</td>
<td style="width: 30px;" align="center">Microsystem</td>
<td style="width: 30px;" align="center">C</td>
</tr>
<tr class="alt">
<td style="width: 30px;" align="center">10</td>
<td style="width: 30px;" align="center">Extra</td>
<td style="width: 30px;" align="center">Fancy</td>
<td style="width: 30px;" align="center">B</td>
</tr>
</tbody>
</table>
<h4>jajal_copy</h4>
<table id="wptable-8" class="wptable rowstyle-alt" border="0" cellspacing="1">
<thead>
<tr>
<th class="sortable" style="width: 30px;" align="center">user_id</th>
<th class="sortable" style="width: 30px;" align="center">first_name</th>
<th class="sortable" style="width: 30px;" align="center">last_name</th>
<th class="sortable" style="width: 30px;" align="center">grade</th>
</tr>
</thead>
<tbody>
<tr>
<td style="width: 30px;" align="center">1</td>
<td style="width: 30px;" align="center">Some</td>
<td style="width: 30px;" align="center">Dude</td>
<td style="width: 30px;" align="center">A</td>
</tr>
<tr class="alt">
<td style="width: 30px;" align="center">2</td>
<td style="width: 30px;" align="center">Other</td>
<td style="width: 30px;" align="center">Guy</td>
<td style="width: 30px;" align="center">B</td>
</tr>
<tr>
<td style="width: 30px;" align="center">3</td>
<td style="width: 30px;" align="center">You are</td>
<td style="width: 30px;" align="center">Welcome</td>
<td style="width: 30px;" align="center">B</td>
</tr>
<tr class="alt">
<td style="width: 30px;" align="center">4</td>
<td style="width: 30px;" align="center">What</td>
<td style="width: 30px;" align="center">Other</td>
<td style="width: 30px;" align="center">A</td>
</tr>
<tr>
<td style="width: 30px;" align="center">5</td>
<td style="width: 30px;" align="center">INeed</td>
<td style="width: 30px;" align="center">You</td>
<td style="width: 30px;" align="center">C</td>
</tr>
<tr class="alt">
<td style="width: 30px;" align="center">6</td>
<td style="width: 30px;" align="center">Mixed</td>
<td style="width: 30px;" align="center">Nuts</td>
<td style="width: 30px;" align="center">C</td>
</tr>
<tr>
<td style="width: 30px;" align="center">7</td>
<td style="width: 30px;" align="center">Kirk</td>
<td style="width: 30px;" align="center">Land</td>
<td style="width: 30px;" align="center">B</td>
</tr>
<tr class="alt">
<td style="width: 30px;" align="center">8</td>
<td style="width: 30px;" align="center">Bit</td>
<td style="width: 30px;" align="center">Shooter</td>
<td style="width: 30px;" align="center">A</td>
</tr>
<tr>
<td style="width: 30px;" align="center">9</td>
<td style="width: 30px;" align="center">Sun</td>
<td style="width: 30px;" align="center">Microsystem</td>
<td style="width: 30px;" align="center">C</td>
</tr>
<tr class="alt">
<td style="width: 30px;" align="center">10</td>
<td style="width: 30px;" align="center">Extra</td>
<td style="width: 30px;" align="center">Fancy</td>
<td style="width: 30px;" align="center">B</td>
</tr>
</tbody>
</table>
<p> </p>
<p>要比较这两张表的数据，找出不一样的数据行。我们可以使用<a href="http://en.wikipedia.org/wiki/Join_(SQL)#Outer_joins"><span style="color: #967001;">outer join</span></a> 技术。我给outer join做了一个链接，是Wikipedia的，如果你对这个技术不是很清楚，还请你行看看其技术细节。</p>
<p>下面是具体的SQL语句：</p>
<h4><span style="text-decoration: underline;">使用FULL OUTER JOIN</span></h4>
<pre data-enlighter-language="sql" class="EnlighterJSRAW">
SELECT
     *
FROM
     jajal j
     FULL OUTER JOIN jajal_copy jc ON jc.first_name = j.first_name
     AND jc.last_name = j.last_name
     AND jc.grade = j.grade
     AND jc.user_id = j.user_id
WHERE
     j.user_id IS NULL
     OR jc.user_id IS NULL
</pre>
<p>运行结果如下：</p>
<table id="wptable-9" class="wptable rowstyle-alt" border="0" cellspacing="1">
<thead>
<tr>
<th class="sortable" style="width: 30px;" align="center">user_id</th>
<th class="sortable" style="width: 30px;" align="center">first_name</th>
<th class="sortable" style="width: 30px;" align="center">last_name</th>
<th class="sortable" style="width: 30px;" align="center">grade</th>
<th class="sortable" style="width: 30px;" align="center">user_id</th>
<th class="sortable" style="width: 30px;" align="center">first_name</th>
<th class="sortable" style="width: 30px;" align="center">last_name</th>
<th class="sortable" style="width: 30px;" align="center">grade</th>
</tr>
</thead>
<tbody>
<tr>
<td style="width: 30px;" align="center">[NULL]</td>
<td style="width: 30px;" align="center">[NULL]</td>
<td style="width: 30px;" align="center">[NULL]</td>
<td style="width: 30px;" align="center">[NULL]</td>
<td style="width: 30px;" align="center">6</td>
<td style="width: 30px;" align="center">Mixed</td>
<td style="width: 30px;" align="center">Nuts</td>
<td style="width: 30px;" align="center">C</td>
</tr>
<tr class="alt">
<td style="width: 30px;" align="center">6</td>
<td style="width: 30px;" align="center">Mixed</td>
<td style="width: 30px;" align="center">Nuts</td>
<td style="width: 30px;" align="center">Z</td>
<td style="width: 30px;" align="center">[NULL]</td>
<td style="width: 30px;" align="center">[NULL]</td>
<td style="width: 30px;" align="center">[NULL]</td>
<td style="width: 30px;" align="center">[NULL]</td>
</tr>
</tbody>
</table>
<p> </p>
<h4><span style="text-decoration: underline;">使用NATURAL FULL OUTER JOIN</span></h4>
<p>关于<a href="http://en.wikipedia.org/wiki/Join_(SQL)#Natural_join"><span style="color: #967001;">natural join</span></a>，你可以看看Wikipedia是怎么说的。</p>
<pre data-enlighter-language="sql" class="EnlighterJSRAW">
SELECT
       *
FROM
       jajal j
       NATURAL FULL OUTER JOIN jajal_copy jc
WHERE
       j.user_id IS NULL
       OR jc.user_id IS NULL
</pre>
<p>运行结果如下：</p>
<table id="wptable-10" class="wptable rowstyle-alt" border="0" cellspacing="1">
<thead>
<tr>
<th class="sortable" style="width: 30px;" align="center">user_id</th>
<th class="sortable" style="width: 30px;" align="center">first_name</th>
<th class="sortable" style="width: 30px;" align="center">last_name</th>
<th class="sortable" style="width: 30px;" align="center">grade</th>
</tr>
</thead>
<tbody>
<tr>
<td style="width: 30px;" align="center">6</td>
<td style="width: 30px;" align="center">Mixed</td>
<td style="width: 30px;" align="center">Nuts</td>
<td style="width: 30px;" align="center">C</td>
</tr>
<tr class="alt">
<td style="width: 30px;" align="center">6</td>
<td style="width: 30px;" align="center">Mixed</td>
<td style="width: 30px;" align="center">Nuts</td>
<td style="width: 30px;" align="center">Z</td>
</tr>
</tbody>
</table>
<p> </p>
<h4><span style="text-decoration: underline;">MySQL SQL 代码</span></h4>
<pre>MySQL 并不支持 FULL OUTER JOIN，但是我们可以使用LEFT JOIN 和 RIGHT JOIN 来实现这一功能。如下所示。</pre>
<pre data-enlighter-language="sql" class="EnlighterJSRAW">
SELECT
*
FROM
jajal j
LEFT JOIN jajal_copy jc ON jc.first_name = j.first_name
AND jc.last_name = j.last_name
AND jc.grade = j.grade
AND jc.user_id = j.user_id
WHERE
jc.user_id IS NULL
UNION ALL
SELECT
*
FROM
jajal j
RIGHT JOIN jajal_copy jc ON jc.first_name = j.first_name
AND jc.last_name = j.last_name
AND jc.grade = j.grade
AND jc.user_id = j.user_id
WHERE
j.user_id IS NULL
</pre>
<p>或者你更喜欢NATURAL JOIN 版本</p>
<pre data-enlighter-language="sql" class="EnlighterJSRAW">
SELECT
*
FROM
jajal j
NATURAL LEFT JOIN jajal_copy jc
WHERE
jc.user_id IS NULL
UNION ALL
SELECT
*
FROM
jajal j
NATURAL RIGHT JOIN jajal_copy jc
WHERE
j.user_id IS NULL
</pre>
<p>当然，如果你需要一个MySQL的存储过程的话，下面是一个示例：</p>
<pre data-enlighter-language="sql" class="EnlighterJSRAW">
DELIMITER $$

CREATE PROCEDURE `db_schema`.`tablediff`
    (schema_name VARCHAR(64), table1 VARCHAR(64), table2 VARCHAR(64))
BEGIN
    DECLARE done INT DEFAULT 0;
    DECLARE sql_statement TEXT DEFAULT &#039;&#039;;
    DECLARE sql_statement_where TEXT DEFAULT &#039;&#039;;
    DECLARE sql_statement_pk TEXT DEFAULT &#039;&#039;;
    DECLARE col_name VARCHAR(64);
    DECLARE col_name_cur CURSOR FOR
        SELECT
            COLUMN_NAME
        FROM
            information_schema.COLUMNS
        WHERE
            TABLE_SCHEMA = schema_name
            AND TABLE_NAME = table1
    ;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

    OPEN col_name_cur;
    traverse_columns: LOOP
        FETCH col_name_cur INTO col_name;

        IF done THEN
            CLOSE col_name_cur;
            LEAVE traverse_columns;
        END IF;

        SET sql_statement_where = CONCAT(sql_statement_where,
            &#039; AND a.&#039;, col_name, &#039; = b.&#039;, col_name);
        SET sql_statement_pk = CONCAT(sql_statement_pk,
            &#039;AND b.&#039;, col_name, &#039; IS NULL&#039;);
    END LOOP;

    SELECT
        COLUMN_NAME INTO col_name
    FROM
        information_schema.KEY_COLUMN_USAGE
    WHERE
        CONSTRAINT_SCHEMA = schema_name
        AND CONSTRAINT_NAME = &#039;PRIMARY&#039;
        AND TABLE_NAME = table1
    LIMIT 1
    ;
    IF col_name IS NOT NULL THEN
        SET sql_statement_pk = CONCAT(&#039;AND b.&#039;, col_name, &#039; IS NULL&#039;);
    END IF;

    SET sql_statement = CONCAT(&#039;SELECT * FROM &#039;, schema_name, &#039;.&#039;, table1, &#039; a LEFT JOIN &#039;, schema_name, &#039;.&#039;, table2, &#039; b ON TRUE&#039;);
    SET sql_statement = CONCAT(sql_statement, sql_statement_where, &#039; WHERE TRUE &#039;, sql_statement_pk);
    SET sql_statement = CONCAT(sql_statement, &#039; UNION ALL SELECT * FROM &#039;, schema_name, &#039;.&#039;, table1, &#039; b RIGHT JOIN &#039;, schema_name, &#039;.&#039;, table2, &#039; a ON TRUE&#039;);
    SET sql_statement = CONCAT(sql_statement, sql_statement_where, &#039; WHERE TRUE &#039;, sql_statement_pk);

    SET @s = sql_statement;
    PREPARE stmt1 FROM @s;
    EXECUTE stmt1;
    DEALLOCATE PREPARE stmt1;

END$$
DELIMITER ;
</pre>
<p> </p>
<p> </p>
<h4><span style="text-decoration: underline;">PostgreSQL 下的SQL语句</span></h4>
<p>下面是PostgreSQL的一个存储过程：</p>
<pre data-enlighter-language="sql" class="EnlighterJSRAW">
CREATE OR REPLACE FUNCTION tablediff (
    IN schema_name VARCHAR(64),
    IN table1 VARCHAR(64),
    IN table2 VARCHAR(64)
) RETURNS BIGINT AS
$BODY$
DECLARE
    the_result BIGINT DEFAULT 0;
    sql_statement TEXT DEFAULT &#039;&#039;;
    sql_statement_where TEXT DEFAULT &#039;&#039;;
    sql_statement_pk TEXT DEFAULT &#039;&#039;;
    col_name VARCHAR(64);
    col_name_cur CURSOR FOR
        SELECT
            column_name
        FROM
            information_schema.columns
        WHERE
            table_catalog = schema_name
            AND table_schema = &#039;public&#039;
            AND table_name = table1
    ;
BEGIN
    OPEN col_name_cur;

    LOOP
        FETCH col_name_cur INTO col_name;
        IF NOT FOUND THEN
            EXIT;
        END IF;

        sql_statement_where := sql_statement_where || &#039; AND a.&#039; || col_name || &#039; = b.&#039; || col_name;
    END LOOP;

    SELECT
        column_name INTO col_name
    FROM
        information_schema.table_constraints tc
        JOIN information_schema.constraint_column_usage ccu ON
            ccu.constraint_name = tc.constraint_name
    WHERE
        tc.table_catalog = schema_name
        AND tc.table_schema = &#039;public&#039;
        AND tc.table_name = table1
    LIMIT 1
    ;

    IF col_name IS NOT NULL THEN
        sql_statement_pk := &#039; a.&#039; || col_name || &#039; IS NULL&#039;;
        sql_statement_pk := sql_statement_pk || &#039; OR b.&#039; || col_name || &#039; IS NULL&#039;;
    END IF;

    sql_statement := &#039;SELECT COUNT(*) FROM &#039; || schema_name || &#039;.public.&#039; || table1 || &#039; a FULL OUTER JOIN &#039; || schema_name || &#039;.public.&#039; || table2 || &#039; b ON TRUE&#039;;
    sql_statement := sql_statement || sql_statement_where || &#039; WHERE &#039; || sql_statement_pk;

    EXECUTE sql_statement INTO the_result;

    RETURN the_result;
END;$BODY$
LANGUAGE &#039;plpgsql&#039; STABLE;
</pre>
<p> </p>
<p>文章：<a href="http://www.microshell.com/database/sql/comparing-data-from-2-database-tables/" target="_blank">来源</a><!--



<p align="center"><a href= target=_blank><img decoding="async" src=""></a></p>





<p align="center"><img decoding="async" src="https://coolshell.cn/wp-content/uploads/2020/03/coolshell.weixin.jpg"> <img decoding="async" loading="lazy" src="https://coolshell.cn/wp-content/uploads/2020/03/coolshell.mini_.jpg" width="300" height="300"> <br />关注CoolShell微信公众账号和微信小程序</p>

 

--></p>
<div style="margin-top: 15px; font-size: 16px;color: #cc0000;">
<p align="center"><strong>（转载本站文章请注明作者和出处 <a href="https://coolshell.cn/">酷 壳 &#8211; CoolShell</a> ，请勿用于任何商业用途）</strong></p>
</div>

<div class="wp_rp_wrap  wp_rp_vertical_m" id="wp_rp_first"><div class="wp_rp_content"><h3 class="related_post_title">相关文章</h3><ul class="related_post wp_rp"><li ><a href="https://coolshell.cn/articles/7490.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/uploads/2012/06/f1-150x150.jpg" alt="性能调优攻略" width="150" height="150" /></a><a href="https://coolshell.cn/articles/7490.html" class="wp_rp_title">性能调优攻略</a></li><li ><a href="https://coolshell.cn/articles/3433.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/plugins/wordpress-23-related-posts-plugin/static/thumbs/10.jpg" alt="6个有用的MySQL语句" width="150" height="150" /></a><a href="https://coolshell.cn/articles/3433.html" class="wp_rp_title">6个有用的MySQL语句</a></li><li ><a href="https://coolshell.cn/articles/8711.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/uploads/2012/12/200906020837401710-150x150.jpg" alt="程序员疫苗：代码注入" width="150" height="150" /></a><a href="https://coolshell.cn/articles/8711.html" class="wp_rp_title">程序员疫苗：代码注入</a></li><li ><a href="https://coolshell.cn/articles/7270.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/uploads/2012/05/overview2-1-150x150.png" alt="NoSQL 数据建模技术" width="150" height="150" /></a><a href="https://coolshell.cn/articles/7270.html" class="wp_rp_title">NoSQL 数据建模技术</a></li><li ><a href="https://coolshell.cn/articles/6639.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/uploads/2012/02/programming-language-150x150.jpg" alt="千万别惹程序员 " width="150" height="150" /></a><a href="https://coolshell.cn/articles/6639.html" class="wp_rp_title">千万别惹程序员 </a></li><li ><a href="https://coolshell.cn/articles/4939.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/plugins/wordpress-23-related-posts-plugin/static/thumbs/29.jpg" alt="Quora使用到的技术" width="150" height="150" /></a><a href="https://coolshell.cn/articles/4939.html" class="wp_rp_title">Quora使用到的技术</a></li></ul></div></div>The post <a href="https://coolshell.cn/articles/925.html">如何比较两个数据表</a> first appeared on <a href="https://coolshell.cn">酷 壳 - CoolShell</a>.]]></content:encoded>
					
					<wfw:commentRss>https://coolshell.cn/articles/925.html/feed</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
	</channel>
</rss>
