今天運行壹個小程序,功能是讀取指定目錄下的 SQL 腳本,並加載到內存中批量執行,以前的程序運行良好。可是今天相關開發人員更新了其中壹個 SQL 腳本,因而程序運行的時候就出錯了,錯誤提示信息以下:批處理中出現錯誤: ORA-01756: 引號內的字符串沒有正確結束。用 Notepad++ 打開看了下 SQL 腳本,沒有發現明顯的語法錯誤,再仔細找了找包含單引號和雙引號的語句,也沒有看到語句未正確結束的地方。因而有點困惑,開始啓動 Eclipse 的 Debug 模式仔細分析,並調低了日誌級別到 DEBUG,將全部解析出來的 SQL 語句打印至控制檯。 java
結果在日誌中發現有的 SQL 語句解析以後竟然是亂碼,截取部份內容以下所示: sql
4,2,'?佔淇跡罩湛賈? from TRUSTDB.TRUST_PRDT_MEM_SET t很明顯的,數字2後面的部分只有壹個開始的單引號,而沒有關閉的單引號,看來極有多是這段亂碼引發的,上述內容在原始的 SQL 文件(GBK 編碼)中實際是這樣的:
4,2,'日間開始,日終開始以前' from TRUSTDB.TRUST_PRDT_MEM_SET t不知道爲何通過 Java 解析以後會變成壹串亂碼。找到問題的所在,修改的時候直接把「日間開始,日終開始以前」中間的全角逗號改爲了半角逗號,問題就宣告解決,同時我還注意到在這個 SQL 腳本中,還有其它地方也使用到了全角的逗號,可是那些地方沒有出問題,獨獨此處報錯了,真是奇怪。在我看來,這個修復方法實在不太理想,不知道是否還有更好的方法。另外,附上個人 SQL 文件解析代碼以下。
List<String> loadSql(String filepath) throws Exception { List<String> sqls = new ArrayList<String>(); StringBuffer sb = new StringBuffer(); byte[] buff = new byte[1024]; int byteRead = 0; LOGGER.debug("Start parse sql file [" + filepath + "]."); InputStream sqlFileIn = ClasspathResourceLoader.getResourceAsStream(filepath); //開始讀取文件內容 while ((byteRead = sqlFileIn.read(buff)) != -1) { sb.append(new String(buff, 0, byteRead)); } //將讀取到的字符串以換行符分割 String[] sqlArr = sb.toString().split("(;\\s*\\r\\n)|(;\\s*\\n)"); for (int i = 0; i < sqlArr.length-1; i++) { //將每個獨立語句中的註釋和末尾的分號去掉,只保留語句內容 String sql = sqlArr[i].replaceAll("--.*", "").replaceAll(";", " ").trim(); if (!sql.equals("")) { sqls.add(sql); } } LOGGER.debug("sql list=" + sqls); return sqls; }目前這個問題暫存,待往後有更好的方法時我會回過頭來繼續補充完善。其實有個更簡單的辦法找到 SQL 語句中出錯的地方,就是把日誌中解析以後輸出的 SQL 語句複製粘貼到 PL/SQL Developer 的編輯器中,觀察這些語句的語法染色,一般來說,若是由於單引號或者雙引號不匹配引起了語句錯誤,在編輯器裏顯示出來的效果就會有點不大壹樣。咱們只須要從代碼尾部開始往上找到那個不壹樣的地方,而後修改掉它,就很容易解決問題了。