今天在plsql中使用merge into更新字段時遇到了一個問題。
相關代碼如下:
MERGE INTO TABLE1 A USING (SELECT T.ID, T.NEW_CORE_SIZE FROM TABLE2 T) B ON (A.ID = B.ID AND A.CORE_SIZE IS NULL) WHEN MATCHED THEN UPDATE SET A.CORE_SIZE = B.NEW_CORE_SIZE;
這裏請注意,在ON中出現的字段,不可以在WHEN MATCHED THEN中更新,所以無法更新A.CORE_SIZE字段
正確的寫法如下:
MERGE INTO TABLE1 A USING (SELECT T.ID, T.NEW_CORE_SIZE FROM TABLE2 T) B ON (A.ID = B.ID) WHEN MATCHED THEN UPDATE SET A.CORE_SIZE = DECODE(A.CORE_SIZE,null,B.NEW_CORE_SIZE,A.CORE_SIZE);
merge (oracle中merge用法) - chenhonggao - 博客園 (cnblogs.com)
merge (oracle中merge用法)
[Oracle] Merge語句
Merge的語法例如以下:
MERGE [hint] INTO [schema .] table [t_alias] USING [schema .]
{ table | view | subquery } [t_alias] ON ( condition )
WHEN MATCHED THEN merge_update_clause
WHEN NOT MATCHED THEN merge_insert_clause;
MERGE是什麼,怎樣使用呢?讓我們先看一個簡單的需求:
需求是,從T1表更新數據到T2表中。假設T2表的NAME 在T1表中已存在,就將MONEY累加,假設不存在。將T1表的記錄插入到T2表中。
大家知道,在等價的情況下,一定需要至少兩條語句,一條爲UPDATE,一條爲INSERT,並且語句中必需要與推斷的邏輯,或者寫在過程中,假設是單條語句,就要寫全條件。
寫在UPDATE和INSERT的語句中,顯的比較麻煩並且easy出錯。假設了解MERGE,我們能夠不借助存儲過程,直接用單條SQL便實現了該業務邏輯,且代碼非常簡潔。詳細例如以下:
MERGE INTO T2
USING T1
ON (T1.NAME=T2.NAME)
WHEN MATCHED THEN
UPDATE
SET T2.MONEY=T1.MONEY+T2.MONEY
WHEN NOT MATCHED THEN
INSERT
VALUES (T1.NAME,T1.MONEY);
Merge的四大靈活之處
--我們可選擇只UPDATE目標表
MERGE INTO T2
USING T1
ON (T1.NAME=T2.NAME)
WHEN MATCHED THEN
UPDATE
SET T2.MONEY=T1.MONEY+T2.MONEY;
--也可選擇只INSERT目標表而不做不論什麼UPDATE動作
MERGE INTO T2
USING T1
ON (T1.NAME=T2.NAME)
WHEN NOT MATCHED THEN
INSERT
VALUES (T1.NAME,T1.MONEY);
2.可對MERGE語句加條件MERGE INTO T2
USING T1
ON (T1.NAME=T2.NAME)
WHEN MATCHED THEN
UPDATE
SET T2.MONEY=T1.MONEY+T2.MONEY
WHERE T1.NAME='A';
3.可用DELETE子句清除行/*
在這樣的情況下,首先是要先滿足T1.NAME=T2.NAME的記錄,假設T2.NAME=’A’並不滿足T1.NAME=T2.NAME過濾出的記錄集,
那這個DELETE是不會生效的。在滿足的條件下,能夠刪除目標表的記錄。
*/
MERGE INTO T2
USING T1
ON (T1.NAME=T2.NAME)
WHEN MATCHED THEN
UPDATE
SET T2.MONEY=T1.MONEY+T2.MONEY
DELETE WHERE (T2.NAME = 'A');
4.可採用無條件方式Insert/*
方法非常easy,在語法ONkeyword處寫上恆不等條件(如1=2)後,MATCHED語句的INSERT就變爲無條件INSERT了,詳細例如以下
*/
MERGE INTO T2
USING T1
ON (1=2)
WHEN NOT MATCHED THEN
INSERT
VALUES (T1.NAME,T1.MONEY);
Merge的誤區
1. 不能更新ON子句引用的列MERGE INTO T2
USING T1
ON (T1.NAME=T2.NAME)
WHEN MATCHED THEN
UPDATE
SET T2.NAME=T1.NAME;
ORA-38104: 無法更新 ON 子句中引用的列: "T2"."NAME"
2. DELETE子句的WHERE順序必須最後MERGE INTO T2
USING T1
ON (T1.NAME=T2.NAME)
WHEN MATCHED THEN
UPDATE
SET T2.MONEY=T1.MONEY+T2.MONEY
DELETE WHERE (T2.NAME = 'A')
WHERE T1.NAME='A';
ORA-00933: SQL 命令未正確結束
3.DELETE 子句僅僅能夠刪除目標表。而無法刪除源表/*
這裏須要引起注意,不管DELETE WHERE (T2.NAME = 'A' )這個寫法的T2是否改寫爲T1。效果都一樣,都是對目標表進行刪除。
*/
SELECT * FROM T1;
NAME MONEY
-------------------- ----------
A 10
B 20
SELECT * FROM T2;
NAME MONEY
-------------------- ----------
A 30
C 20
MERGE INTO T2
USING T1
ON (T1.NAME=T2.NAME)
WHEN MATCHED THEN
UPDATE
SET T2.MONEY=T1.MONEY+T2.MONEY
DELETE WHERE (T2.NAME = 'A' );
SELECT * FROM T1;
NAME MONEY
-------------------- ----------
A 10
B 20
SELECT * FROM T2;
NAME MONEY
-------------------- ----------
C 20
4.更新同一張表的數據,需操心USING的空值
SELECT * FROM T2;
NAME MONEY
-------------------- ----------
A 30
C 20
/*
需求爲對T2表進行自我更新。假設在T2表中發現NAME=D的記錄,就將該記錄的MONEY字段更新爲100,假設NAME=D的記錄不存在,
則自己主動添加。NAME=D而且MONEY=100的記錄。依據語法完畢例如以下代碼:
*/
MERGE INTO T2
USING (select * from t2 where NAME='D') T
ON (T.NAME=T2.NAME)
WHEN MATCHED THEN
UPDATE
SET T2.MONEY=100
WHEN NOT MATCHED THEN
INSERT
VALUES ('D',200);
--可是查詢發現。本來T表應該由於NAME=D不存在而要添加記錄。可是實際卻根本無變化。
SQL> SELECT * FROM T2;
NAME MONEY
-------------------------------------------------------
A 30
C 20
/*
原來是由於此時select * from t2 where NAME='D'爲NULL,所以出現了無法插入的情況。
我們能夠利用COUNT(*)的值不會爲空的特點來等價改造。詳細例如以下:
*/
MERGE INTO T2
USING (select COUNT(*) CNT from t2 where NAME='D') T
ON (T.CNT<>0)
WHEN MATCHED THEN
UPDATE
SET T2.MONEY=100
WHEN NOT MATCHED THEN
INSERT
VALUES ('D',100);
SQL> SELECT * FROM T2;
NAME MONEY
-------------------------------
A 30
C 20
D 100
5. 必需要在源表中獲得一組穩定的行---構造數據,請注意這裏多插入一條A記錄,就產生了ORA-30926錯誤
INSERT INTO T1 VALUES ('A',30);
COMMIT;
---此時繼續運行例如以下
MERGE INTO T2
USING T1
ON (T1.NAME=T2.NAME)
WHEN MATCHED THEN
UPDATE
SET T2.MONEY=T1.MONEY+T2.MONEY;
ORA-30926: 無法在源表中獲得一組穩定的行
/*
oracle中的merge語句應該保證on中的條件的唯一性,T1.NAME=T2.NAME的時候。T1表記錄相應到了T2表的兩條記錄,所以就出錯了。
解決方法非常easy。比方我們能夠對T1表和T2表的關聯字段建主還鍵,這樣基本上就不可能出現這種問題,並且一般而言,MERGE語句的關聯字段互相有主鍵。 MERGE的效率將比較高!或者是將T1表的ID列做一個聚合。這樣歸併成單條,也能避免此類錯誤。
如: */ MERGE INTO T2 USING (select NAME,SUM(MONEY) AS MONEY FROM T1 GROUP BY NAME)T1 ON (T1.NAME=T2.NAME) WHEN MATCHED THEN UPDATE SET T2.MONEY=T1.MONEY+T2.MONEY; --正常情況下,一般出現反覆的NAME須要引起懷疑,不太應該。
oracle-merge into using on用法_張三李四dw的博客-CSDN博客_merge into using on
在sql中看到如下
截圖:
merge into 表1 using 表2 on(.... and ...)
when matched then ....
上圖大概樣式
那麼表達什麼意思?
以下內容摘自博文:
https://blog.csdn.net/qq_34745941/article/details/81176140?utm_source=copy
1. 適用場景:'有則更新,無則插入'
2. 好處
(1) 執行 '效率高'
(2) 語法簡潔
語法:
merge into 目標表 b
using 源表 a
on (b.字段1 = a.字段1 and b.字段n = a.字段n) -- 必須帶 '()'
when matched then -- 整體掃描,匹配時,執行此處
update 子句
when not matched then -- 整體掃描,不匹配時,執行此處
insert 子句;
Oracle中時間日期轉化函數to_date和to_char用法總結_旺旺_123的博客-CSDN博客_to_char函數用法 日期
在實際的工作中會經常會用到to_char()、to_date()函數來對時間、日期進行處理。
1、to_char()函數的用法
1.1、將時間日期按照指定的格式輸出,得到的是字符串,而非date類型。
-
select sysdate,to_char(sysdate,'yyyy-mm-dd')from dual;
-
select sysdate,to_char(sysdate,'yyyy/mm/dd')from dual;
-
select sysdate,to_char(sysdate,'yyyymmdd')from dual;
-
select sysdate,to_char(sysdate,'yyyymmdd hh24:mi:ss')from dual;
運行的輸出結果爲:
-
2017/6/15 17:07:24 2017-06-15
-
2017/6/15 17:07:25 2017/06/15
-
2017/6/15 17:07:25 20170615
-
2017/6/15 17:07:25 20170615 17:07:25
1.2、用to_char()可以得到日期中的年、月、日、時、分
-
select sysdate,to_char(sysdate,'yyyy')from dual;
-
select sysdate,to_char(sysdate,'mm')from dual;
-
select sysdate,to_char(sysdate,'hh24')from dual;
-
select sysdate,to_char(sysdate,'mi')from dual;
運行的輸出結果爲:
-
2017/6/15 17:09:14 2017
-
2017/6/15 17:09:14 06
-
2017/6/15 17:09:14 17
-
2017/6/15 17:09:14 09
注:to_char()得到的是字符串,要查詢具體單日、時、分要特別注意。
-
select accept_time,to_char(accept_time,'mi') from TMP_WW_0615_GYTS_S2
-
where to_char(accept_time,'mi')='06' ;
-
select accept_time,to_char(accept_time,'mi') from TMP_WW_0615_GYTS_S2
-
where to_char(accept_time,'mi')='6' ;
運行輸出結果爲:
-
2017/6/8 21:06:59 06
-
null
2、to_date()函數的用法
2.1、將字符串轉換爲具體指定的時間日期格式
-
select sysdate,to_date('20170615','yyyymmdd')from dual;
-
select sysdate,to_date('20170615','yyyy-mm-dd')from dual;
-
select sysdate,to_date('20170615','yyyy/mm/dd')from dual;
-
select sysdate,to_date('20170615','yyyy-mm-dd hh24:mi:ss')from dual;
運行輸出結果爲:
-
2017/6/15 17:20:27 2017/6/15
-
2017/6/15 17:20:27 2017/6/15
-
2017/6/15 17:20:27 2017/6/15
-
2017/6/15 17:20:27 2017/6/15
注:to_date()得到的日期格式是和系統的日期格式保持一致;
得到的時間爲當天的 00 :00:00。
2.2、可以直接使用date'yyyy-mm-dd'
select date'2017-5-1',to_date('20170615','yyyymmdd')from dual;
運行輸出結果爲:
2017/5/1 2017/6/15
注:date'2017/5/1' 會提示格式不對。