比較 10 萬筆 INSERT 操作,使用繫結變數 vs 字串拼接:
CREATE TABLE t (a VARCHAR2(20), b VARCHAR2(20));
DECLARE
v_sql VARCHAR2(50);
BEGIN
FOR i IN 1..100000 LOOP
v_sql := 'INSERT INTO t VALUES (:1, :2)';
EXECUTE IMMEDIATE v_sql USING 'a'||i, 'b'||i;
END LOOP;
COMMIT;
END;
/
DECLARE
BEGIN
FOR i IN 1..100000 LOOP
INSERT INTO t VALUES ('a'||i, 'b'||i);
END LOOP;
COMMIT;
END;
/
| 指標 | 繫結變數 | 字串拼接 |
|---|---|---|
| 解析次數 | 1 次(硬解析)+ 99,999 次軟解析 | 100,000 次硬解析 |
| 共用池記憶體 | 1 個游標佔用 | 100,000 個游標佔用 |
| Latch 競爭 | 極低 | 高(Library Cache Latch) |
| 執行時間 | 秒級 | 分級(視系統而定) |
| SQL 注入風險 | 無 | 高 |
-- 繫結變數版本:僅 1 筆 SQL_TEXT
SELECT sql_text, executions, parse_calls, version_count
FROM v$sqlarea
WHERE sql_text LIKE 'INSERT INTO T VALUES%';
-- 字串拼接版本:100,000 筆不同 SQL_TEXT
SELECT COUNT(*) FROM v$sqlarea
WHERE sql_text LIKE 'INSERT INTO T VALUES%';
PreparedStatement ps = conn.prepareStatement("INSERT INTO t VALUES (?, ?)");cmd.Parameters.Add("p1", OracleDbType.Varchar2).Value = val;cursor.execute("INSERT INTO t VALUES (:1, :2)", (val1, val2))INSERT INTO t VALUES (v1, v2); 自動繫結即使使用動態 SQL,也應盡量使用 USING 子句繫結變數,而非字串拼接。
繫結變數不是選項,是專業開發的基本功。從這個 10 萬筆測試可見,效能差距可達 10 倍以上,且消除 SQL 注入風險。代碼審查時,任何字串拼接 SQL 都應視為缺陷要求修正。