在运行时动态创建SQL select查询

在运行时动态创建SQL select查询,sql,Sql,我需要在运行时编写一个带有动态列的SQL select查询。数据库中几乎没有强制和可选字段。我希望在运行时根据传入请求中的值生成查询 例如:DB有列A、B、C、D、E 场景1:请求只有一个值,查询应生成为 select * from table where A='<somevalue>' select * from table where A='<somevalue>' and D='<somevalue>' 从A=''的表中选择* 情景2。请求具有A

我需要在运行时编写一个带有动态列的SQL select查询。数据库中几乎没有强制和可选字段。我希望在运行时根据传入请求中的值生成查询

例如:DB有列A、B、C、D、E
场景1:请求只有一个值,查询应生成为

select * from table where A='<somevalue>' 
select * from table where A='<somevalue>' and D='<somevalue>'
从A=''的表中选择*
情景2。请求具有A和D的值,查询应按如下方式生成

select * from table where A='<somevalue>' 
select * from table where A='<somevalue>' and D='<somevalue>'
从A=''和D=''的表中选择*
目前正在使用java为NOTNULL值创建字符串,并将其附加到select语句以形成最终查询

例:

if(A!=null)
字符串查询_a=“”
其他的
query_a=“”
然后追加
,形成最终查询


有更好的方法来实现这一点吗?

在SQL脚本中,您可以像下面这样更好地进行参数化。我假设您正在使用参数

**这基本上是sql的想法

选择*
从桌子上
在哪里(
(@p1为空或columnA=@p1)
或(@p2为空或columnB=@p2)
或(@p3为空或columnC=@p3)
或(@p4为空或columnD=@p4)
)

< /代码> 您可能想考虑在java中构造查询,为每个情况创建一个适当的。

List<String> clauses = new ArrayList<String>();
List<String> params = new ArrayList<String>();
clauses.add("1=1");
if (you_want_to_search_on_column_a) {
   clauses.Add("column_a = ?");
   params.Add(value_to_search_on_column_a);
}
if (you_want_to_search_on_column_b) {
   clauses.Add("column_b = ?");
   params.Add(value_to_search_on_column_b);
}
String queryString = "SELECT * FROM table WHERE " + String.join(" AND ", clauses);
PreparedStatement stmt = con.prepareStatement(queryString);
for (int i = 0; i < params.size; i++ ) {
   stmt.setString(i+1, params.get(i));
}
ResultSet rs = stmt.executeQuery();
List子句=新的ArrayList();
List params=new ArrayList();
条款。添加(“1=1”);
如果(您希望在列a上搜索){
添加(“a列=?”;
参数添加(值添加到列a上的搜索);
}
如果(您希望在列b上搜索){
添加(“b列=?”;
参数添加(值添加到列b上的搜索);
}
String queryString=“从表中选择*,其中“+String.join”(“AND”,子句);
PreparedStatement stmt=con.prepareStatement(查询字符串);
对于(int i=0;i
通过这种方式,您将使用所需的过滤条件呈现查询,从而为MySQL的查询计划器提供优化每个查询的最佳机会


如果您使用的是Oracle或SQL server,那么保存PreparedStatement对象的缓存是值得的,但MySQL却不是这样。

在Java或SQL中?因为您只有SQL标记,但在问题中没有提到您希望将其从Java中删除。基于
select*from table的示例,其中A=''和D=''
,“main”
逻辑可能是
。否则,它不会为可能所有的场景生成次优的查询计划吗?简化为
(columnA=@p1或@p1为NULL)
等。绝对正确@DávidLaczkó这是另一个性能问题。