首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> Oracle 資料庫 >> Oracle 資料庫基礎

動態 SQL 字串拼接實戰:跨資料庫同步資料的 MERGE 模式

     編輯:Oracle 資料庫基礎

需將來源資料庫(客戶端)資料同步至目標資料庫(接口表),要求「已存在不重複導入、不存在則新增」。本文示範在 C# 中拼接 Oracle MERGE / INSERT WHEN NOT EXISTS 動態 SQL,並解決日期、數字、NULL 值拼接陷阱。

目標表結構

CREATE TABLE A (
  ID NUMBER(20),
  UPDATED_BY NUMBER(20),
  UPDATE_DATE DATE,
  UPDATE_LOGIN NUMBER(20),
  CREATION_DATE DATE,
  CREATED_BY NUMBER(20),
  NAME VARCHAR2(60),
  IMPORT_STATE VARCHAR2(1)
);

核心邏輯:INSERT WHEN NOT EXISTS + SELECT 1 FROM DUAL

INSERT WHEN (NOT EXISTS (SELECT 1 FROM A WHERE A.ID = :id))
THEN INTO A (ID, UPDATED_BY, CREATED_BY, UPDATE_DATE, UPDATE_LOGIN, CREATION_DATE, NAME, IMPORT_STATE)
VALUES (:id, :ub, :cb, TO_DATE(:ud, 'YYYY-MM-DD HH24:MI:SS'), :ul, TO_DATE(:cd, 'YYYY-MM-DD HH24:MI:SS'), :name, :state)
SELECT 1 FROM dual;
  • WHEN NOT EXISTS 確保冪等性(重複執行不重複寫入)。
  • SELECT 1 FROM dual 滿足 Oracle INSERT ... WHEN 語法要求的子查詢。

C# 動態拼接完整範例

foreach (DataRow dr in dsOra.Tables[0].Rows)
{
    string str = $@"
INSERT WHEN (NOT EXISTS (SELECT 1 FROM A WHERE A.ID = '{dr["ID"]}'))
THEN INTO A (ID, UPDATED_BY, CREATED_BY, UPDATE_DATE, UPDATE_LOGIN, CREATION_DATE, NAME, IMPORT_STATE)
VALUES (
  '{dr["ID"]}',
  '{dr["UPDATED_BY"]}',
  '{dr["CREATED_BY"]}',
  TO_DATE('{Convert.ToDateTime(dr["UPDATE_DATE"]):yyyy-MM-dd HH:mm:ss}', 'YYYY-MM-DD HH24:MI:SS'),
  '{dr["UPDATE_LOGIN"]}',
  TO_DATE('{Convert.ToDateTime(dr["CREATION_DATE"]):yyyy-MM-dd HH:mm:ss}', 'YYYY-MM-DD HH24:MI:SS'),
  '{dr["NAME"].ToString().Replace("'", "''")}',
  '{dr["IMPORT_STATE"]}'
)
SELECT 1 FROM dual;";

    sb.Append(str);
    sb.AppendLine(";");
}

拼接六步法(避免引號、逗號錯誤)

  1. 寫好括號框架:VALUES ( )
  2. 填入佔位逗號:VALUES ( , , , , , , , )
  3. 加上單引號:VALUES ( '', '', '', '', '', '', '', '' )
  4. 加上雙引號(字串拼接界限):VALUES ( ''+'', ''+'', ... )
  5. 加上變數與 + 號:VALUES ( '' + id + '', '' + ub + '', ... )
  6. 移除首尾多餘逗號/加號,完成。

關鍵陷阱與對策

陷阱現象對策
數字欄位 NULL直接拼接數字變數若為 null 會產生 VALUES ( , ...) 語法錯誤統一以字串形式拼接,NULL 時拼入 NULL 關鍵字或空字串再 TO_NUMBER
日期格式隱式轉換依賴 NLS 設定,跨環境易失敗強制 TO_DATE('yyyy-MM-dd HH24:mi:ss', 'YYYY-MM-DD HH24:MI:SS')
單引號逸出資料含單引號導致 SQL 截斷.Replace("'", "''") 雙寫單引號
DUAL 忘寫INSERT WHEN ... THEN ... VALUES ... 缺子查詢報錯務必以 SELECT 1 FROM dual 結尾

更優雅的替代方案

  • MERGE 陳述式:Oracle 9i+ 支援,單條 SQL 完成 UPSERT,效能優於動態拼接。
  • 參數化命令:OracleCommand.Parameters.Add 避免注入、自動處理型別轉換、計畫重用。
  • 批次綁定:ArrayBindCount + 陣列參數,一次往返寫入成千上萬筆。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved