# Oracle中怎么利用row_number()over()方式解決插入數據時重復鍵
## 引言
在Oracle數據庫開發中,我們經常會遇到需要向表中插入數據時處理重復鍵的問題。傳統方法如使用MERGE語句或先查詢后插入的方式雖然可行,但效率較低且代碼復雜。本文將詳細介紹如何利用`row_number() over()`分析函數高效解決這一問題。
## 一、重復鍵問題的常見場景
### 1.1 業務數據去重
當從外部系統導入數據時,經常需要避免主鍵或唯一鍵沖突:
```sql
-- 典型報錯示例
ORA-00001: 違反唯一約束條件 (SCOTT.PK_EMP)
在不同環境間遷移數據時,需要處理目標表已存在部分數據的情況。
MERGE INTO target_table t
USING source_table s
ON (t.id = s.id)
WHEN NOT MATCHED THEN
INSERT VALUES(s.col1, s.col2...);
缺點:語法復雜,對大批量數據性能一般
DELETE FROM target_table WHERE id IN (SELECT id FROM source_table);
INSERT INTO target_table SELECT * FROM source_table;
缺點:存在事務風險,可能造成數據丟失
row_number() over()是Oracle的分析函數,可為結果集的每一行分配唯一序號:
SELECT
id,
name,
row_number() OVER(PARTITION BY id ORDER BY create_time DESC) rn
FROM source_data
INSERT INTO target_table(id, name, create_time)
SELECT id, name, create_time
FROM (
SELECT
id,
name,
create_time,
row_number() OVER(PARTITION BY id ORDER BY create_time DESC) rn
FROM source_data
)
WHERE rn = 1
AND NOT EXISTS (
SELECT 1 FROM target_table t
WHERE t.id = source_data.id
);
-- 假設唯一鍵由(col1,col2)組成
INSERT INTO target_table(col1, col2, col3)
SELECT col1, col2, col3
FROM (
SELECT
col1,
col2,
col3,
row_number() OVER(PARTITION BY col1, col2 ORDER BY version DESC) rn
FROM staging_table
)
WHERE rn = 1;
PARTITION BY子句包含所有唯一鍵列-- 根據業務需求選擇排序字段
row_number() OVER(PARTITION BY id ORDER BY
CASE WHEN source_system = 'ERP' THEN 0 ELSE 1 END,
update_date DESC)
-- 啟用并行查詢
INSERT /*+ PARALLEL(4) */ INTO target_table...
SELECT /*+ PARALLEL(4) */ ... FROM source_data
| 方案 | 優點 | 缺點 |
|---|---|---|
| row_number() over() | 單次掃描、代碼簡潔 | 需要理解分析函數 |
| MERGE | 原子性操作 | 語法復雜,性能中等 |
| 先刪后插 | 邏輯簡單 | 存在數據丟失風險 |
-- 每天同步訂單數據,保留最新版本
INSERT INTO dw_orders
SELECT order_id, user_id, status, update_time
FROM (
SELECT
order_id,
user_id,
status,
update_time,
row_number() OVER(PARTITION BY order_id ORDER BY update_time DESC) rn
FROM ods_orders
WHERE trunc(update_time) = trunc(SYSDATE)
)
WHERE rn = 1;
-- 合并多個系統的客戶數據
CREATE TABLE tmp_customers AS
SELECT customer_id, name, phone, source_system
FROM (
SELECT
customer_id,
name,
phone,
source_system,
row_number() OVER(PARTITION BY customer_id
ORDER BY data_quality_score DESC) rn
FROM (
SELECT * FROM crm_system
UNION ALL
SELECT * FROM erp_system
)
)
WHERE rn = 1;
PARTITION BY字段有適當索引通過row_number() over()函數解決重復鍵問題,不僅提高了代碼的可讀性,還能顯著提升大批量數據處理的效率。掌握這一技術后,開發人員可以更優雅地處理各類數據合并場景。建議在實際應用中結合具體業務需求調整分區和排序策略,以達到最佳性能。
“`
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。