簡體   English   中英

如何編寫條件可選的sql查詢?

[英]How to write sql query whose conditions are optional?

我必須編寫一個查詢,其中條件參數未知,因為它們是在jdbc中動態設置的。 這些條件應該是可選的。 我使用h2數據庫。 查詢是:

select e.event_id,a.attempt_id,a.preferred,a.duration,a.location 
from event e,attempt a 
where e.user_label=? and e.start_time=? 
and e.end_time=? and e.duration_min=? 
and e.duration_max=? 
and e.event_id=a.event_id

但是如何使這些條件成為可選條件(除了使用OR之外,因為不知道參數)?

謝謝!

如果可以切換到命名參數 ,則可以將條件更改為檢查參數是否為null ,如下所示:

select e.event_id,a.attempt_id,a.preferred,a.duration,a.location 
from event e,attempt a 
where
     (:ul is null OR e.user_label=:ul)
 and (:st is null OR e.start_time=:st)
 and (:et is null OR e.end_time=:et)
 and (:dmin is null OR e.duration_min=:dmin)
 and (:dmax is null OR e.duration_max=:dmax)
 and e.event_id=a.event_id

如果無法切換到命名參數,則仍然可以使用相同的技巧,但是您需要為每個可選參數傳遞兩個參數:如果設置了第二個參數,則該對的第一個參數為1如果第二個參數為0則為0一個被省略:

select e.event_id,a.attempt_id,a.preferred,a.duration,a.location 
from event e,attempt a 
where
     (? = 1 OR e.user_label=?)
 and (? = 1 OR e.start_time=?)
 and (? = 1 OR e.end_time=?)
 and (? = 1 OR e.duration_min=?)
 and (? = 1 OR e.duration_max=?)
 and e.event_id=a.event_id

您可能正在看的是動態SQL。 當所需的值不為null時,可以追加查詢中可以更改的部分:

String sqlQuery ="select e.event_id,a.attempt_id,a.preferred,a.duration,a.location from     event e,attempt a where 1=1"  


if (vUserLabel!=null){ //vUserLabel : The variable expected to contain the required value
sqlQuery = sqlQuery+"e.user_label=?";
}

稍后您可以執行:

int pos = 1;
...
if (vUserLabel!=null) {
    stmt.setString(pos++, vUserLabel);
}

stmt.executeQuery(sqlQuery);

這樣,條件就可以動態地附加到查詢中,而無需重復努力,工作就完成了。

我自己的解決方案。 如果未提供命名參數,則刪除帶有[]的行。 因此,有時需要(1=1)才能保持語法正常。

在這樣的示例中:label, :startt, :endt是可選的,所有其他要求

select e.event_id,a.attempt_id,a.preferred,a.duration,a.location 
from event e,attempt a 
where (1=1) -- sometimes required
[and e.user_label=:label and e.start_time=:startt ]
[and e.end_time=:endt ]
and e.duration_min=:durationmin
and e.duration_max=:durationmax
and e.event_id=a.event_id

注意:我的重要問題是JDBC沒有命名參數。 我使用Spring JDBC NamedParameterJdbcTemplate,但有很大的依賴性。 許多臨時命名的參數解決方案都有錯誤,如果使用的參數大於1x (對我而言最重要的參數,請使用named代替positional)則構建錯誤的查詢,或者字符串替換對於特殊字符而言並不安全

好的,自問這個問題已經有一段時間了,但是我將寫出我的解決方案。

我發現,當查詢太大或太復雜時,在末尾附加另一個String並不容易,有時資源可以存儲在文件或db中,我所做的就是這樣。

我將查詢保存在.sql文件中,因此我在查詢中添加了一個標記。

存儲查詢的my.sql文件。

SELECT * FROM my_table
WHERE date_added BETWEEN :param1 and param2
$P{TEX_TO_REPLACE}
GROUP BY id

現在在我的代碼中

String qry = component.findQuery("my.sql");//READ THE FILE

String additionalQuery = " AND classification = 'GOB'";
if(condition1 == true) {
    additionalQuery = " AND customer_id = 66";
}


qry = qry.replace("$P{TEX_TO_REPLACE}",additionalQuery);

現在我的查詢看起來像這樣。

SELECT * FROM my_table
WHERE date_added BETWEEN :param1 and param2
AND customer_id = 66
GROUP BY id

暫無
暫無

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

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