关于 sql:JasperReports 中的条件 Where 子句

Conditional Where clauses in JasperReports

假设我想要一个 JasperReport,让用户可以根据需要过滤日期。 SQL如下:

1
SELECT * FROM foo WHERE bar = $P{bar} AND some_date > $P{SOME.date}

现在,如果他们没有传递日期,我不想按某个日期进行过滤。我发现了人们使用的以下内容:

1
SELECT * FROM foo WHERE bar = $P{bar} $P!{SOME.date.fragment}

并且some.date.fragment参数定义为如下默认值:

1
($P{SOME.date} == NULL || $P{SOME.date}.equals("")) ?"" :"AND some_date >'" + NEW java.sql.Date($P{SOME.date}.getTime()).toString() +"'"

这不起作用,因为 toString 不会以我的 SQL 服务器可以理解的格式输出日期。我想让条件仍然使用带有 jdbc 驱动程序的准备好的语句并将参数折腾进去,我只希望准备好的语句依赖于参数是否为空。这个可以吗?


在您使用 $P!{} 表达式之前,JDBC-Driver 会为您完成所有格式化。

但是如果你使用 $P!{} 表达式你必须自己格式化。

这样的事情应该可以工作:

1
2
3
4
5
6
7
(
$P{SOME.date} == NULL
?
""
:
"AND some_date >'" + (NEW SimpleDateFormat("dd.MM.yyyy HH:mm:ss.SSS")).format($P{SOME.date}) +"'"
)

根据您的数据类型,您必须自定义 dd.MM.yyyy HH:mm:ss.SSS.

如果您不想使用 $P!{} 表达式,您可以使用以下解决方案来避免它。

我个人不喜欢这种方式。它也可能导致错误的执行计划。

如果不想使用 $P!{} 因为担心 sql 注入。只要您的参数 $P{some.date} 包含像 java.lang.Date.

这样的安全数据类型,就没有必要

创建一个参数。让我们称之为 ${is_null_pram} 并添加一个带有参数类 Integer:

的默认表达式

1
($P{SOME.date} == NULL ? 1 : 0)

现在可以查询了:

1
2
3
4
5
6
7
8
9
10
SELECT
    *
FROM foo
WHERE
    bar = $P{bar}
    AND
        (
            some_date > $P{SOME.date}
            OR 1 = $P{is_null_pram}
        )


我想你可以使用这个功能:

$X{EQUAL, <column_name>, <parameter_name>}

如您在此帮助页面中所见,它优化了查询。


你可以使用这个条件语句

1
2
3
    SELECT *
    FROM foo
    WHERE bar = $P{bar} AND some_date > $P{SOME.date} OR $P{SOME.date}  IS NULL