繁体   English   中英

在Oracle SQL中的两个表之间同时进行SYNC和UPDATE

[英]SYNC and UPDATE at the same time between two tables in Oracle SQL

我在ORACLE SQL操作上遇到麻烦。 首先,我有两个表

TEST_TABLE_A
Insert into TEST_TABLE_A (NAME, VAL1, VAL2, STATUS) Values ('HEAD1', 100, 200, 'ACTIVE');
Insert into TEST_TABLE_A (NAME, VAL1, VAL2, STATUS) Values ('HEAD2', 300, 400, 'ACTIVE');
Insert into TEST_TABLE_A (NAME, VAL1, VAL2, STATUS) Values ('HEAD3', 500, 600, 'ACTIVE');
Insert into TEST_TABLE_A (NAME, VAL1, VAL2, STATUS) Values ('HEAD4', 700, 800, 'ACTIVE');

TEST_TABLE_B
Insert into TEST_TABLE_B (NAME, VAL1, VAL2) Values ('HEAD1', 1, 2);
Insert into TEST_TABLE_B (NAME, VAL1, VAL2) Values ('HEAD4', 700, 800);
Insert into TEST_TABLE_B (NAME, VAL1, VAL2) Values ('HEAD5', 900, 1000);

我的任务列出如下:1.将数据从表b同步到表a 2.当找到具有相同值的相同名称时,将其忽略3.当找到具有不同值的相同名称时,将具有相同值的数据插入表A名称和从B获取的值,并用“ INACTIVE”状态更新旧行4.当在基于表B的表A中找不到数据时,将数据插入表A

我的查询是这样的

    MERGE INTO TEST_TABLE_A TGT
    USING TEST_TABLE_B SRC
        ON (TGT.NAME = SRC.NAME)

    WHEN MATCHED THEN 
        UPDATE SET TGT.VAL1 = SRC.VAL1,
               TGT.VAL2 = SRC.VAL2

    WHEN NOT MATCHED THEN
        INSERT (TGT.NAME, TGT.VAL1, TGT.VAL2, TGT.STATUS)
        VALUES (SRC.NAME, SRC.VAL1, SRC.VAL2, 'ACTIVE');

所以我面临着我无法使#3工作的问题。 我尝试了SQL的许多组合,但它并没有起作用。

我如何通过忽略两个表中具有相同值的相同名称来使2号工作?

我希望结果会像这样

TEST_TABLE_A
NAME   VAL1   VAL2   STATUS
-----------------------------
HEAD1  100    200    INACTIVE
HEAD1  1      2      ACTIVE
HEAD2  300    400    INACTIVE
HEAD3  500    600    INACTIVE
HEAD4  700    800    ACTIVE
HEAD5  900    1000   ACTIVE

我真的很感谢你们的帮助。 问候

试试这个:

如果HEAD2和HEAD3不活跃

--> Update the data that does not exist in table BLE_B to be INACTIVE
 Update BLE_A
 Set STATUS = 'INACTIVE'
 From BLE_A a
 Left Join BLE_B b
    On b.Name = a.Name
    And b.Val1 = a.Val1
    And b.Val2 = a.Val2
 Where b.Name is Null


 --> Insert the data from BLE_B that does not exist in table BLE_A 
 --> or insert the data that different values with table BLE_A
 Insert Into BLE_A
 Select b.*, 'ACTIVE'
 From BLE_B b
 Left Join BLE_A a
    On a.Name = b.Name
    And a.Val1 = b.Val1
    And a.Val2 = b.Val2
 Where b.Name is Null

您不能仅对#3使用一次合并,因为您需要在相同的ON条件下进行更新和插入。

update test_table_a a set a.status = 'INACTIVE' 
where exists (select 1 from test_table_b b 
               where b.name = a.name and (b.val1 != a.val1 or b.val2 != a.val2));

merge into test_table_a a using test_table_b b on (b.val1 = a.val1 and b.val2 = a.val2)
when not matched then insert values (b.name, b.val1, b.val2, 'ACTIVE');

但是我不明白为什么在您的输出中HEAD2和HEAD3处于“ INACTIVE”状态。 也许您还需要将TEST_TABLE_A中不存在的TEST_TABLE_A中的行标记为'INACTIVE'(在这种情况下,您可以通过添加以下条件来更改第一个更新:“或不存在(从test_table_b b中选择1,其中b.name = a.name)“)

我希望结果会像这样

TEST_TABLE_A
NAME   VAL1   VAL2   STATUS
-----------------------------
HEAD1  100    200    INACTIVE
HEAD1  1      2      ACTIVE
HEAD2  300    400    INACTIVE
HEAD3  500    600    INACTIVE
HEAD4  700    800    ACTIVE
HEAD5  900    1000   ACTIVE

好的,让我们看一下如何满足SQL的每个规则。

1.第一件事只是两个表的简单UNION

2.然后,需要除去在NAMEVAL1VAL2列上重复的行。 因此,请使用ROW_NUMBER分析。

3最后,选择RANK为1。

SQL> SELECT name,
  2    val1,
  3    val2,
  4    status
  5  FROM
  6    (SELECT a.*,
  7      row_number() over(partition BY a.val1, a.val2 order by a.name, a.val1, a.val2) rn
  8    FROM
  9      ( SELECT name, val1, val2,'INACTIVE' status  FROM TEST_TABLE_A
 10      UNION
 11      SELECT b.*, 'ACTIVE' status FROM TEST_TABLE_B b ORDER BY 1
 12      ) A
 13    )
 14  WHERE rn = 1
 15  /

NAME                       VAL1       VAL2 STATUS
-------------------- ---------- ---------- --------
HEAD1                         1          2 ACTIVE
HEAD1                       100        200 INACTIVE
HEAD2                       300        400 INACTIVE
HEAD3                       500        600 INACTIVE
HEAD4                       700        800 ACTIVE
HEAD5                       900       1000 ACTIVE

6 rows selected.

SQL>

因此,这正是您想要的输出。

*更新**根据OP的要求添加测试用例

SQL> SELECT * FROM test_table_a;

NAME                       VAL1       VAL2 STATUS
-------------------- ---------- ---------- --------------------
HEAD1                       100        200 ACTIVE
HEAD2                       300        400 ACTIVE
HEAD3                       500        600 ACTIVE
HEAD4                       700        800 ACTIVE

SQL>
SQL> CREATE TABLE test_table_a_new AS
  2  SELECT name,
  3    val1,
  4    val2,
  5    status
  6  FROM
  7    (SELECT a.*,
  8      row_number() over(partition BY a.val1, a.val2 order by a.name, a.val1, a.val2) rn
  9    FROM
 10      ( SELECT name, val1, val2,'INACTIVE' status  FROM TEST_TABLE_A
 11      UNION
 12      SELECT b.*, 'ACTIVE' status FROM TEST_TABLE_B b ORDER BY 1
 13      ) A
 14    )
 15  WHERE rn = 1
 16  /

Table created.

SQL>
SQL> DROP TABLE test_table_a PURGE
  2  /

Table dropped.

SQL>
SQL> alter table test_table_a_new rename to test_table_a
  2  /

Table altered.

SQL> select * from test_table_a
  2  /

NAME                       VAL1       VAL2 STATUS
-------------------- ---------- ---------- --------
HEAD1                         1          2 ACTIVE
HEAD1                       100        200 INACTIVE
HEAD2                       300        400 INACTIVE
HEAD3                       500        600 INACTIVE
HEAD4                       700        800 ACTIVE
HEAD5                       900       1000 ACTIVE

6 rows selected.

SQL>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM