情境
最近在做一些網路交易系統的開發,過程中需要不斷往 DB 塞入大量的法規 html 字串,取出後在前端再用 v-html 渲染。
範例 SQL
1 2 3 4 5 6 7 8
| INSERT INTO DBP.CONTRACT_I18N (CONTRACT_ID, LOCALE, TITLE, CONTENT) VALUES ( 1, 'zh-TW', '數位網站<br>登入設施約定條款', TO_CLOB('<div>超長的法規條款內容</div>'), );
|
在 INSERT 的時候 IDE ORA-01704: string literal too long 的訊息;忽然想到以前做專案的時候會在各段落間穿插 ') || TO_CLOB(' 來分段。
原因是 Oracle SQL 單一字串(VARCHAR2 literal) 最大只能 4000 bytes。而在 Oracle SQL Parser(語法解析階段)啟動時,TO_CLOB('...') 內的內容,在進入 TO_CLOB 函數之前,首先被當作 SQL String Literal 處理。所以超過 4000 bytes,Oracle 在 Parser 階段會直接報錯。
如果字串合法(≤ 4000 bytes),Oracle 才會把這個 String Literal 當成參數傳給 TO_CLOB()。
所以就改為:
1 2 3 4 5 6 7 8
| INSERT INTO DBP.CONTRACT_I18N (CONTRACT_ID, LOCALE, TITLE, CONTENT) VALUES ( 1, 'zh-TW', '數位網站<br>登入設施約定條款', TO_CLOB('<div>超長的法規條款內容1 ') || TO_CLOB(' 超長的法規條款內容2 ') || TO_CLOB(' 超長的法規條款內容3</div>'), );
|
最後乾脆讓 AI 寫一個 Main 方法,之後包在測試工具類裡面。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| import java.io.*;
public class ToClobFormatter { public static void main(String[] args) { String inputFilePath = "D:/tmp/target.txt"; String outputFilePath = "D:/tmp/result.txt"; int chunkSize = 700;
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(inputFilePath), "UTF-8")); BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outputFilePath), "UTF-8"))) {
writer.write("TO_CLOB('"); int currentLength = 0; StringBuilder chunkBuffer = new StringBuilder();
String line; while ((line = reader.readLine()) != null) { String processedLine = line.replace("'", "''") + "\n"; int linePos = 0;
while (linePos < processedLine.length()) { int remaining = chunkSize - currentLength; int charsToTake = Math.min(remaining, processedLine.length() - linePos);
chunkBuffer.append(processedLine, linePos, linePos + charsToTake); currentLength += charsToTake; linePos += charsToTake;
if (currentLength >= chunkSize) { writer.write(chunkBuffer.toString()); writer.write("')||TO_CLOB('"); chunkBuffer.setLength(0); currentLength = 0; } } }
if (chunkBuffer.length() > 0) { writer.write(chunkBuffer.toString()); } writer.write("')");
} catch (IOException e) { e.printStackTrace(); } } }
|