需要在Mule 4 DW 2.0中构建动态选择查询的帮助。

huangapple go评论60阅读模式
英文:

Need help in Building dynamic select query in Mule 4 DW 2.0

问题

以下是翻译好的内容:

{
    "PERSON_ID": "123456",
    "LAST_MODIFIED_DATE": "2011-12-15T00:00:00",
    "START_DATE": "2011-12-15T00:00:00",
    "END_DATE": "2012-12-15T00:00:00"
}

我需要根据输入参数构建不同的动态 SQL 查询,输入参数可以是以下之一 - (要么 LAST_MODIFIED_DATE,要么 (START_DATE  END_DATE)。但是 PERSON_ID 可以传递给其他任何参数。

选择 * from Person where PERSON_ID = 123456
选择 * from Person where LAST_MODIFIED_DATE = 2011-12-15T00:00:00
选择 * from Person where PERSON_ID = 123456 and LAST_MODIFIED_DATE = 2011-12-15T00:00:00
选择 * from Person where PERSON_ID = 123456 and LAST_MODIFIED_DATE between 2011-12-15T00:00:00 and 2012-12-15T00:00:00
选择 * from Person where LAST_MODIFIED_DATE between 2011-12-15T00:00:00 and 2012-12-15T00:00:00
如果没有传递查询参数,则为
选择 * from Person

我的数据仓库逻辑无法满足这个要求。

尝试了以下但未能获得所需的结果。您能否建议一种推荐的方法或最佳解决方案

{
    "PERSON_ID": "123456",
    "LAST_MODIFIED_DATE": "2011-12-15T00:00:00",
    "START_DATE": "2011-12-15T00:00:00",
    "END_DATE": "2012-12-15T00:00:00"
}

选择 * from Person Where
((data filterObject ((value, key, index) -> (value != null and value != "")) mapObject ((value, key, index) -> {
    (myData : "LAST_MODIFIED_DATE between " ++ (key as String)) if ((key as String) == "START_DATE"),
    (myData : "AND " ++ (key as String)) if ((key as String) == "END_DATE"),
    (myData : (key as String) ++ " = :" ++ (key as String)) if ((key as String) == "PERSON_ID"),
    myData : (key as String) ++ " = :" ++ (key as String)
})).*myData joinBy " AND ")

稍后在数据库连接器中,我将上述输出变量设置为 SQL 字符串中的查询。

英文:

I have the following query params coming to my API

{
"PERSON_ID": "123456",
"LAST_MODIFIED_DATE": "2011-12-15T00:00:00",
"START_DATE": "2011-12-15T00:00:00",
"END_DATE": "2012-12-15T00:00:00"
}

I need to build a different dynamic SQL query based on the input parameters which can be any of the these given below - (either LAST_MODIFIED_DATE or (START_DATE and END_DATE) will be based. But PERSON_ID can be passed any of the other params

select * from Person where PERSON_ID = 123456 
select * from Person where LAST_MODIFIED_DATE = 2011-12-15T00:00:00 
select * from Person where PERSON_ID = 123456 and LAST_MODIFIED_DATE = 2011-12-15T00:00:00 
select * from Person where PERSON_ID = 123456 and LAST_MODIFIED_DATE between 2011-12-15T00:00:00 and 2012-12-15T00:00:00
select * from Person where LAST_MODIFIED_DATE between 2011-12-15T00:00:00 and 2012-12-15T00:00:00
or if no query params are passed it will be 
select * from Person

my DW logic is not able to cater to this requirement.

Tried below but not able to get the required results. Could you please suggest a recommended approach or best solution

%dw 2.0
output application/json
var data = {
"PERSON_ID": "123456",
"LAST_MODIFIED_DATE": "2011-12-15T00:00:00",
"START_DATE": "2011-12-15T00:00:00",
"END_DATE": "2012-12-15T00:00:00"
}
"Select * from Person Where " ++
((data filterObject ((value, key, index) -> (value != null and value != "")) mapObject ((value, key, index) -> {
(myData : "LAST_MODIFIED_DATE between " ++ (key as String)) if ((key as String) == "START_DATE"),
(myData : "AND " ++ (key as String)) if ((key as String) == "END_DATE"),
(myData : (key as String) ++ " = :" ++ (key as String)) if ((key as String) == "PERSON_ID"),
myData : (key as String) ++ " = :" ++ (key as String)
})).*myData joinBy  " AND ")

Later in the DB connector I am setting the above output variable as query in SQL String

答案1

得分: 1

以下是翻译好的部分:

这是一个非常常见的用例,有很多可能的解决方案。
我喜欢做的是创建一个包含所有条件的数组作为项。然后使用joinBy函数将它们连接起来,使用' AND '字符串来连接这些条件。

如果你遵循这个方法,使用Conditional Elements可以使复杂和动态的SQL生成非常清晰和易读,我认为。

根据Aled的建议更新以下内容以避免SQL注入
例如

%dw 2.0
output text/plain
fun generateWhereClause(queryParams) = 
    [
        ("PERSON_ID = :PERSON_ID") if(queryParams.PERSON_ID?),
        ("LAST_MODIFIED_DATE = :LAST_MODIFIED_DATE") if(queryParams.LAST_MODIFIED_DATE?),
        ("LAST_MODIFIED_DATE >= :START_DATE") if(queryParams.START_DATE?),
        ("LAST_MODIFIED_DATE <= :END_DATE") if(queryParams.END_DATE?),
    ] joinBy " AND "
---
'SELECT * FROM person WHERE $(generateWhereClause(vars.queryParams))'

这将生成一个参数化的SQL语句,你可以将查询参数作为select操作的输入参数传递。

<db:select config-ref="dbConfig">
    <db:sql>#[payload]</db:sql>
    <db:input-parameters>
      #[vars.queryParams // 无论你的参数在哪里]
    </db:input-parameters>
  </db:select>

我已经放弃了between运算符,改用了>= and <=运算符,因为between不容易适应模式,使数组中的条件复杂化。但如果你想使用它,也可以。

英文:

It is a very common use case with a lot of possible solutions.
What I like to do is I create an Array with all the conditions as items. Then join them using joinBy function with a &#39; AND &#39; string to join those condition.

If you follow this the use of Conditional Elements makes the complex and dynamic SQL generation very readable and clear IMO

Updated the following based on Aled's suggestion to avoid SQL Injection
For Example

%dw 2.0
output text/plain
fun generateWhereClause(queryParams) = 
    [
        (&quot;PERSON_ID = :PERSON_ID&quot;) if(queryParams.PERSON_ID?),
        (&quot;LAST_MODIFIED_DATE = :LAST_MODIFIED_DATE&quot;) if(queryParams.LAST_MODIFIED_DATE?),
        (&quot;LAST_MODIFIED_DATE &gt;= :START_DATE&quot;) if(queryParams.START_DATE?),
        (&quot;LAST_MODIFIED_DATE &lt;= :END_DATE&quot;) if(queryParams.END_DATE?),
    ] joinBy &quot; AND &quot;
---
&#39;SELECT * FROM person WHERE $(generateWhereClause(vars.queryParams))&#39;

This will generate a parameterized SQL Statement, and you can pass your query parameters as the input parameter in the select operation.

&lt;db:select config-ref=&quot;dbConfig&quot;&gt;
    &lt;db:sql&gt;#[payload]&lt;/db:sql&gt;
    &lt;db:input-parameters&gt;
      #[vars.queryParams // whereever you have your params]
    &lt;/db:input-parameters&gt;
  &lt;/db:select&gt;

I have dropped between operator and used &gt;= and &lt;= operators because between does not fit the pattern easily and makes the conditions in the array complex. If you want to use it though, you can.

huangapple
  • 本文由 发表于 2023年6月8日 11:23:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/76428412.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定