簡體   English   中英

從Java應用程序動態構建oracle sql查詢

[英]build oracle sql query dynamically from java application

如何從Java應用程序動態構建Oracle PL / SQL查詢? 將為用戶提供一堆列,這些列存在於數據庫的不同表中。 用戶可以選擇任何一組列,應用程序應僅使用包含選定列的表來構建完整的選擇查詢。 例如,讓我們考慮數據庫中有3個表。 用戶選擇col11,col22。 在這種情況下,應用程序應僅使用Tabl1和Tabl2構建查詢。 我該如何實現?

Tabl1
 - col11
 - col12
 - col13

Tabl2
 - fkTbl1
 - col21
 - col22
 - col23

Tabl3
 - col31
 - col32
 - col33
 - fkTbl1

臨時報告是一個舊的收藏夾。 它經常在“報告要求”部分的結尾處顯示為單行:“用戶必須能夠定義和運行自己的報告”。 唯一的障礙是,即席報告本身就是一種應用程序

你說

“將為用戶提供一堆在數據庫中不同表中存在的列。”

如果預先選擇並嚴格控制“列數”(和表的分布),則可以避免我在下面討論的某些復雜性。 las,根據臨時報告的性質,用戶幾乎需要所有表中的所有列。

讓我們從您的示例開始。 用戶選擇了col11col22 ,因此您需要生成以下查詢:

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

不太難。 您只需瀏覽數據字典視圖USER_CONSTRAINTSUSER_CONS_COLUMNS即可在USER_CONS_COLUMNS中建立列-前提是您已定義了外鍵(請有外鍵!)。

如果我們添加第四個表,事情將變得更加復雜:

Tabl4
 - col41
 - col42
 - col43
 - fkTbl2

現在,當用戶選擇col11col42您需要導航數據字典以建立Tabl2充當連接Tabl4Tabl1的中間表的Tabl1 (假定您不使用復合主鍵,因為大多數人沒有使用復合主鍵)。 但是假設用戶選擇col31col41 那是合法的組合嗎? 可以說是。 現在,您必須將Tabl4Tabl2Tabl1Tabl3 嗯...

如果用戶從兩個完全不相關的表Tabl1Tabl23選擇列, Tabl23怎么Tabl23 您是盲目生成CROSS JOIN還是拋出異常? 這是你的選擇。

回到第一個查詢,它將返回兩個表中的所有行。 幾乎可以肯定,您的用戶將希望使用該選項來限制結果集。 因此,您需要為他們提供向WHERE子句添加過濾器的功能。 這里的陷阱包括:

  • 確保提供的值具有適當的數據類型(數字不包含字符串,日期不包含數字)
  • 提供對參考數據值的查找
  • 處理多個值( IN列表而不是等於)
  • 確保日期范圍合理(開盤價在收盤價之前)
  • 處理自由文本搜索(您要允許它嗎?是否需要使用TEXT索引,還是會冒用戶對某些CLOB列執行LIKE '%whatever%'的風險?)

最后一點強調了即席報告固有的風險:如果用戶可以使用任何過濾器組合來自任何表的查詢,則他們可以組合查詢,這會消耗系統中的所有資源。 因此,最好應用配置文件來防止這種情況的發生。 同樣,正如我已經提到的,用戶有可能建立無意義的查詢。 請記住,您不需要在架構中使用太多表來生成太多要測試的排列。

最后,安全策略存在棘手的問題。 如果用戶被限制查看基於其部門或工作角色的數據子集,那么您將需要復制這些規則。 在這種情況下,通過行級安全性自動應用策略是真正的福音

所有這些都可能使您得出結論,最好的解決方案是促使用戶購買現成的產品。 盡管這種方法並非沒有自身的問題。

過去,我做這種事情的方式是簡單地使用StringBuilder即時構建SQL查詢,然后使用JDBC(未經准備的語句)執行它。 由於Oracle DB必須針對每個查詢重復所有查詢分析和優化工作,因此效率很低。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM