您可以使用方便的DISTINCT predicate(从 Db2 11.1 开始)尝试以下原样。等价表达式可能用于早期版本,但它们会更长一些。
WITH
A (ID, C1, C2) AS
(
VALUES
(1, '=', '=')
, (2, '=', '=')
, (4, 'A', '=')
, (5, '=', NULL)
, (6, 'A', 'A')
)
, B (ID, C1, C2) AS
(
VALUES
(1, '=', '=')
, (3, '=', '=')
, (4, 'B', '=')
, (5, '=', NULL)
, (6, 'B', 'B')
)
SELECT
COALESCE(A.ID, B.ID) AS ID
, CASE
WHEN A.ID IS NULL THEN '-A'
WHEN B.ID IS NULL THEN '-B'
ELSE ''
END
|| CASE WHEN A.ID = B.ID AND A.C1 IS DISTINCT FROM B.C1 THEN ', C1' ELSE '' END
|| CASE WHEN A.ID = B.ID AND A.C2 IS DISTINCT FROM B.C2 THEN ', C2' ELSE '' END
--...
--|| CASE WHEN A.ID = B.ID AND A.C60 IS DISTINCT FROM B.C60 THEN ', C60' ELSE '' END
AS FLAG
FROM A
FULL JOIN B ON B.ID = A.ID
WHERE
A.ID IS DISTINCT FROM A.ID
OR A.C1 IS DISTINCT FROM B.C1
OR A.C2 IS DISTINCT FROM B.C2
--...
--OR A.C60 IS DISTINCT FROM B.C60;
结果是:
|ID |FLAG |
|-----------|----------|
|4 |, C1 |
|6 |, C1, C2 |
|3 |-A |
|2 |-B |
我们在两个表之间使用FULL OUTER JOIN,具有以下 OR 条件:
- KEY (
ID) 仅对于这些表之一为 NULL(此 KEY 在对应表中不匹配)
- 对应的列值之一存在差异
FLAG 列包含差异类型:
-
-TABNAME - 表中缺少 KEY TABNAME
-
, Cx - 在Cx 列中存在差异 - 对于每个这样的列
如果两个表中都有大量列,则可以使用多个 Db2 系统视图为此 SELECT 语句生成相应的表达式。
例如,如果我们要为SYSIBM.SYSTABLES 表生成这样的表达式,
使用其唯一索引之一(您必须选择这样的索引,最好是支持主键的索引),然后按原样运行以检查:
SELECT
'|| CASE WHEN ' || I.KEY_EXPR || ' AND A.' || C.COLNAME || ' IS DISTINCT FROM B.' || C.COLNAME || ' THEN '', ' || COLNAME || ''' ELSE '''' END' AS SELECT_LIST_EXPR
, 'OR A.' || C.COLNAME || ' IS DISTINCT FROM B.' || C.COLNAME AS WHERE_EXPR
FROM
SYSCAT.COLUMNS C
, TABLE
(
SELECT LISTAGG('A.' || U.COLNAME || ' = B.' || U.COLNAME, ' AND ') AS KEY_EXPR
FROM SYSCAT.INDEXES I
JOIN SYSCAT.INDEXCOLUSE U ON U.INDSCHEMA = I.INDSCHEMA AND U.INDNAME = I.INDNAME
WHERE
I.TABSCHEMA=C.TABSCHEMA AND I.TABNAME=C.TABNAME
AND I.INDSCHEMA='SYSIBM' AND I.INDNAME='INDTABLES01'
AND I.UNIQUERULE IN ('P', 'U')
) I
WHERE C.TABSCHEMA='SYSIBM' AND C.TABNAME='SYSTABLES'
--FETCH FIRST 10 ROWS ONLY
;