2009-09-27 68 views
0

如何從java應用程序動態構建oracle pl/sql查詢?用戶將看到數據庫中不同表格中的一堆列。用戶可以選擇任何一組列,並且應用程序應該僅使用包含所選列的表來構建完整的選擇查詢。例如,讓我們考慮數據庫中有3個表。用戶選擇col11,col22。在這種情況下,應用程序應僅使用Tabl1和Tabl2構建查詢。 我該如何做到這一點?從Java應用程序動態構建oracle sql查詢

Tabl1 
- col11 
- col12 
- col13 

Tabl2 
- fkTbl1 
- col21 
- col22 
- col23 

Tabl3 
- col31 
- col32 
- col33 
- fkTbl1 
+0

給用戶提供這種極端靈活性的問題在於,如果性能很差的SQL很容易陷入困境。我建議使用某種專爲此目的而設計的軟件,除非您的用戶具有足夠的SQL來編寫自己的查詢。 – 2009-09-27 12:18:20

回答

0

我過去做過這種事情的方式是簡單地使用StringBuilder構建SQL查詢,然後使用JDBC執行一個未準備好的語句。這是相當低效的,因爲Oracle數據庫必須重複每個查詢的所有查詢分析和優化工作。

+0

更不用說安全考慮! – 2012-02-06 12:07:02

+0

@atc - 這取決於你在建立查詢。但是,是的,這當然是一個問題。 – 2012-02-08 10:51:23

5

臨時報告是一箇舊的喜愛。在「報告要求」部分末尾,它經常表現爲一行:「用戶必須能夠定義和運行自己的報告」。唯一的障礙是臨時報告是,它自己的權利爲

你說

「的用戶將與 一堆存在於數據庫中的 不同的表列的呈現。」

如果預選並嚴格控制「一堆列」(以及表格的擴展),則可以避免以下討論的一些複雜性。唉,特別報道的性質是用戶需要幾乎所有表格中的所有列。

讓我們從你的例子開始。用戶已經選擇了col11col22,所以你需要生成此查詢:

SELECT tabl1.col11 
     , tabl2.col22 
FROM tabl1 JOIN tabl2 
    ON (TABL1.ID = TABL2.FKTABL1) 
/

這不是太困難。您只需導航數據字典視圖USER_CONSTRAINTSUSER_CONS_COLUMNS即可在連接條件中建立列 - 只要您定義了外鍵(請有外鍵!)。

事情變得更加複雜,如果我們加上第四臺:

Tabl4 
- col41 
- col42 
- col43 
- fkTbl2 

現在,當用戶選擇col11col42您需要導航數據字典來建立Tabl2充當中介表加入Tabl4Tabl1(假設你沒有使用複合主鍵,因爲大多數人不這樣做)。但是,假設用戶選擇col31col41。這是一個合法的組合嗎?假設是這樣。現在您必須加入Tabl4Tabl2Tabl1Tabl3。嗯...

如果用戶從兩個完全無關的表中選擇列 - Tabl1Tabl23?你是否盲目生成CROSS JOIN或者你拋出異常?這是你的選擇。

回到第一個查詢,它將返回兩個表中的所有行。幾乎肯定你的用戶會想要限制結果集的選項。所以你需要爲他們提供添加到WHERE條款的過濾器的能力。這裏陷阱包括:

  • 確保提供的值是適當的數據類型(沒有字符串的數,日期沒有數字)的
  • 提供查找窗口來引用數據 值
  • 處理多個值(IN列表 而不是等於)
  • 確保日期範圍是明智的
  • 處理自由文本搜索 (關閉邊界開放前方向)(你 會允許嗎?你需要 使用TEXT索引或將運行執行LIKE '%whatever%'對一些CLOB 欄中的用戶的 風險)

最後一點突出了一個風險固有的專案報告:如果用戶可以用任何過濾器組裝來自任何表格的查詢,他們可以組裝查詢,從而可以排除系統中的所有資源。因此,應用profiles來防止這種情況發生是一個好主意。另外,正如我已經提到的那樣,用戶可能會構建無意義的查詢。請記住,您的架構中不需要很多表來生成太多的排列來測試。

最後還有一個棘手的安全策略。如果用戶被限制爲根據其部門或其工作角色查看數據子集,則需要複製這些規則。在這種情況下,通過Row Level Security通過Row Level Security自動應用策略是一個真正的好處

所有這些都可能導致您得出結論:最好的解決方案是追求用戶獲得現成的產品。儘管這種方法不是沒有它自己的問題。