在Oracle SQL中执行合并时,如何更新非';来源不匹配?

在Oracle SQL中执行合并时,如何更新非';来源不匹配?,sql,oracle,sql-merge,Sql,Oracle,Sql Merge,我有一个main数据库和一个report数据库,我需要将一个表从main同步到report 但是,当在main数据库中删除项目时,我只想在报告数据库中设置IsDeleted标志 这样做的优雅方式是什么 我目前正在使用一个MERGE语句,如下所示: MERGE INTO report.TEST target USING (SELECT * FROM main.TEST) source ON (target.ID = source.ID) WHEN MATCHED THEN UPDAT

我有一个
main
数据库和一个
report
数据库,我需要将一个表从
main
同步到
report

但是,当在
main
数据库中删除项目时,我只想在
报告
数据库中设置
IsDeleted
标志

这样做的优雅方式是什么

我目前正在使用一个MERGE语句,如下所示:

MERGE INTO report.TEST target
USING (SELECT * FROM main.TEST) source
   ON (target.ID = source.ID)
WHEN MATCHED THEN
    UPDATE SET (target... = source...)
WHEN NOT MATCHED THEN
    INSERT (...) VALUES (source...)
;
WHEN NOT MATCHED
语句提供了
main
中的所有新值,但我还想更新
报告中的所有旧值


我使用的是Oracle PL/SQL。

您可以使用单独的UPDATE语句来完成

UPDATE report.TEST target
SET    is Deleted = 'Y'
WHERE  NOT EXISTS (SELECT 1
                   FROM   main.TEST source
                   WHERE  source.ID = target.ID);

我不知道有什么方法可以将它集成到MERGE语句中。

下面的答案是将数据合并到同一个表中。

MERGE INTO target
USING
(
    --Source data
    SELECT id, some_value, 0 deleteMe FROM source
    --And anything that has been deleted from the source
    UNION ALL
    SELECT id, null some_value, 1 deleteMe
    FROM
    (
        SELECT id FROM target
        MINUS
        SELECT id FROM source
    )
) source
   ON (target.ID = source.ID)
WHEN MATCHED THEN
    --Requires a lot of ugly CASE statements, to prevent updating deleted data
    UPDATE SET target.some_value =
        CASE WHEN deleteMe=1 THEN target.some_value ELSE source.some_value end
    ,isDeleted = deleteMe
WHEN NOT MATCHED THEN
    INSERT (id, some_value, isDeleted) VALUES (source.id, source.some_value, 0)

--Test data
create table target as
select 1 ID, 'old value 1' some_value, 0 isDeleted from dual union all
select 2 ID, 'old value 2' some_value, 0 isDeleted from dual;

create table source as
select 1 ID, 'new value 1' some_value, 0 isDeleted from dual union all
select 3 ID, 'new value 3' some_value, 0 isDeleted from dual;


--Results:
select * from target;

ID  SOME_VALUE   ISDELETED
1   new value 1  0
2   old value 2  1
3   new value 3  0
MERGE INTO YOUR_TABLE d
USING (SELECT 1 FROM DUAL) m
    ON ( d.USER_ID = '123' AND d.USER_NAME= 'itszaif') 
WHEN NOT MATCHED THEN
        INSERT ( d.USERS_ID, d.USER_NAME)
        VALUES ('123','itszaif');

此命令检查
USER\u ID
USER\u NAME
是否匹配,如果不匹配,则将插入。

要用哪些值更新
main.test
?从何处获取它们?如果从
main.test
中删除该行,则相应的
report.test
行将不匹配。我想为所有不匹配的行设置
report.test.IsDeleted
标志。我认为这是不可能的,因为基础联接(
使用(…)
)的结果将不包含该行。那么这些数据应该从哪里来呢?那么,
MERGE
是否类似于
左外连接?我想我希望它可能有一个
完全外部联接
选项。我认为SQL Server 2008在源
上不匹配时有一个
子句,它执行一个
完全外部联接
!我找不到太多关于它的文档,但我在Oracle中尝试了它,但没有成功,所以我想我会看看其他的选择。我不能用MERGE做这件事似乎很奇怪。我会考虑这个答案。如果我做了一个<代码>外部连接>代码,它会变得更“优雅”/高效吗?并且在哪里更新<代码> MIN?测试是NUL/<代码>。这里有一个相关的问题,我认为它会做一个外部连接,而不是一个完整的外部连接,所以我不认为你的建议会起作用。非常感谢,这个链接对我的学习非常有帮助:如果
MERGE
在匹配时只有
,那么它会使用一个常规的
JOIN
。如果不匹配时有一个
,则它使用
左外连接
。现在,我希望有一个特性,比如
在源代码上不匹配时
,它将执行
完全外部连接
。但这可能只适用于SQL Server,而不适用于Oracle。感谢您的创造性!我不会这么做,但它确实完成了任务。你从哪里找到这个语法的?(
by target
)这正是我要找的。。。然而,正如@FlorinGhita所说,您在哪里找到了这种语法?这是MS SQL语法吗?-1因为这不仅是供大家参考的语法,这是一个很好的答案,而且
未与目标匹配
未与源匹配
是MS SQL Server仅支持的功能。这个特性可以解决我的问题,所以我希望Oracle SQL支持它。
MERGE INTO YOUR_TABLE d
USING (SELECT 1 FROM DUAL) m
    ON ( d.USER_ID = '123' AND d.USER_NAME= 'itszaif') 
WHEN NOT MATCHED THEN
        INSERT ( d.USERS_ID, d.USER_NAME)
        VALUES ('123','itszaif');