Sql oracle11g中的自合并
通常情况下,我们需要使用两个不同的查询对同一个表执行更新或插入。我想看看是否可以使用merge语句在表上执行此操作 我只想知道这是否可以做到。否则,我将不得不坚持将查询分离回单独的更新/插入操作 以下是我到目前为止的情况: 方法1:Sql oracle11g中的自合并,sql,oracle,merge,Sql,Oracle,Merge,通常情况下,我们需要使用两个不同的查询对同一个表执行更新或插入。我想看看是否可以使用merge语句在表上执行此操作 我只想知道这是否可以做到。否则,我将不得不坚持将查询分离回单独的更新/插入操作 以下是我到目前为止的情况: 方法1: MERGE INTO TABLEA TARGET USING ( SELECT 1 FROM DUAL ) SOURCE ON (TARGET.TARGET.
MERGE INTO TABLEA TARGET
USING (
SELECT 1 FROM DUAL
) SOURCE
ON (TARGET.TARGET.COLA = '001'
AND TARGET.TARGET.COLB = '1111111'
AND TARGET.COLC = '201302'
)
WHEN MATCHED THEN
UPDATE SET TARGET.COLA = '001'
,TARGET.COLB = '1111111'
,TARGET.COLC = '201304'
,TARGET.CREATEDATE = SYSDATE
,TARGET.USERID = 'USERA'
WHEN NOT MATCHED THEN
INSERT (TARGET.COLA
,TARGET.COLB
,TARGET.COLC
,TARGET.COLD
,TARGET.CREATEDATE
,TARGET.USERID)
VALUES('001'
,'1111111'
,'201304'
,'123'
,SYSDATE
,'USERA')
起初,这种方法对我来说很有意义,因为我总是从源代码返回结果,并且会相应地进行更新和插入。然而,甲骨文拒绝这样做:
SQL错误:ORA-38104:无法更新ON子句中引用的列:TARGET.EFF\u FISCAL\u YR\u PD\u NBR
3810400000-无法更新ON子句中引用的列:%s
*原因:更新集的LHS包含ON子句中引用的列
方法2:
MERGE INTO TABLEA TARGET
USING (
SELECT ROWID AS RID,COLA,COLB,COLC
FROM TABLEA
WHERE COLA = '001'
AND COLB = '1111111'
AND COLC = '201301'
) SOURCE
ON (TARGET.ROWID = SOURCE.RID)
WHEN MATCHED THEN
UPDATE SET TARGET.COLA = '001'
,TARGET.COLB = '1111111'
,TARGET.COLC = '201304'
,TARGET.CREATEDATE = SYSDATE
,TARGET.USERID = 'USERA'
WHEN NOT MATCHED THEN
INSERT (TARGET.COLA
,TARGET.COLB
,TARGET.COLC
,TARGET.COLD
,TARGET.CREATEDATE
,TARGET.USERID)
VALUES('001'
,'1111111'
,'201304'
,'123'
,SYSDATE
,'USERA')
这背后的逻辑是,如果我尝试从源表中查找值,并且它匹配,它将找到记录并用这些值更新自己。但是,如果不匹配,则在尝试插入时会出现问题。因为源是经过筛选的,所以不会返回任何记录,因此目标没有可匹配的内容,也不会插入任何内容。如果在源中没有发现与目标隐式不匹配的记录,我希望这样做是插入,特别是因为insert语句不包含从变量而不是源本身传入的任何by值
我已尝试将源代码更新为如下所示:
SELECT ROWID AS RID,COLA,COLB,COLC
FROM TABLEA
WHERE COLA = '001'
AND COLB = '1111111'
AND COLC = '201301'
UNION ALL
SELECT ROWID,NULL,NULL,NULL FROM DUAL
WHERE ROWNUM <= COUNTOFRETURNEDRESULTS
但问题是合并对匹配的记录进行更新,对不匹配的记录进行插入
对于那些想知道我为什么使用ROWID的人。这是因为并非由我设计的设计表明COLA和COLB将组合成主键,用作表上的索引。不允许复制COLA、COLB和COLC,但它们都可以通过前端接口进行更新。我理解ROWID的缺陷,但因为我只使用一个表作为目标和源,所以无论我对表执行任何CRUD操作,ROWID都将始终与自身匹配
摘要:只有在对匹配项执行更新时,我才使自合并生效,但插入不起作用。如果我理解正确,COLA、COLB和COLC是TABLEA的复合主键 如果是这种情况,您实际上不需要在这里使用ROWID,只需从dual中选择,然后像第一次尝试那样在ON语句中使用复合键,就可以完成所需的操作 您不需要更新主键列,因此可以在ON子句中使用它们
MERGE INTO TABLEA TARGET
USING (
SELECT '001' COLA,
'1111111' COLB,
'201301' COLC
FROM DUAL
) SOURCE
ON (TARGET.COLA = SOURCE.COLA
AND TARGET.COLB = SOURCE.COLB
AND TARGET.COLC = SOURCE.COLC
)
WHEN MATCHED THEN
UPDATE SET TARGET.CREATEDATE = SYSDATE
,TARGET.USERID = 'USERA'
WHEN NOT MATCHED THEN
INSERT (TARGET.COLA
,TARGET.COLB
,TARGET.COLC
,TARGET.COLD
,TARGET.CREATEDATE
,TARGET.USERID)
VALUES('001'
,'1111111'
,'201304'
,'123'
,SYSDATE
,'USERA')
哇,这花了我很长时间 我使用方法3 UNION ALL时走的方向是正确的,它具有来自dual的空记录集 您只需要满足三个条件: 您总是需要从源表返回结果集,但返回的方式与目标不匹配。 不能同时返回匹配集和非匹配集,否则将同时执行插入和更新操作 您的主键是可更新的,因为它在多个列上匹配。我对它们有唯一的约束,所以如果我尝试复制,它将抛出一个错误 因此,源代码应该是这样的:
SELECT RID,COLA,COLB,COLC FROM
(
SELECT ROWID AS RID,COLA,COLB,COLC
FROM TABLEA
WHERE COLA = '001'
AND COLB = '1111111'
AND COLC = '201301'
UNION ALL
SELECT ROWID,NULL,NULL,NULL FROM DUAL
ORDER BY COLA ASC
) f
WHERE ROWNUM <= 1
因此,您返回一条记录。如果满足where子句,则按升序对数据集排序,并仅返回顶部记录集。这样,合并将在此基础上更新。如果不包含ROWNUM的where子句返回零值,它仍将返回null记录集,合并将基于该记录集进行插入
不止一条记录
在我的例子中,如果你真的想得到nutty并得到多条记录,我需要1,那么你必须使用聚合或分析函数获得匹配记录集的计数,并将其填充到变量中,以便where子句标准如下所示:
SELECT ROWID AS RID,COLA,COLB,COLC
FROM TABLEA
WHERE COLA = '001'
AND COLB = '1111111'
AND COLC = '201301'
UNION ALL
SELECT ROWID,NULL,NULL,NULL FROM DUAL
WHERE ROWNUM <= COUNTOFRETURNEDRESULTS
合并到我的目标中
使用从双s中选择1
在t.COL1=:p1上
当匹配时
更新集t.COL3=:p3
当不匹配时
插入列1、列2、列3
值:p1,:p2,:p3
您必须返回一些内容才能进行insertYeh这没有帮助,因为update语句只会更新CREATEDATE和USERID,如果我需要更新COLA、COLB或COLC中的任何一个呢?如下所示:更新TABLEA SET COLA='1'其中COLA='2'。我花了一段时间,但我想我在开车回家的时候发现了一个黑客。在查看代码时,我并不清楚。更新主键几乎总是一个坏主意。主键的整体思想是,它应该定义记录特有的内容,并且不应该更改。不幸的是,您留下了一个需要执行此操作的模式!我同意。DBA承包商宣布它更容易维护。我提出了分离索引信息的观点
从实际数据来看,否则会使查询变得非常复杂。在我的例子中,ROWID已经足够了,因为它正在对自身进行查询。如果我使用连接,就会出现问题。我对你的答案投了更高的票,因为这是一种正确的格式,可以在一个有建筑感的设计上进行自我合并。@sksallaj-非常感谢你的解释,这正是我想要的。但我这里有个小问题。当我从ORDERBY子句运行此查询时,得到的“COLA”是无效标识符。这是dual要求的订单吗?因为我们只得到一个记录,我理解我们需要通过ASC订购。请帮帮我,似乎没有人在merge语句中提到这种情况。。