2012-09-07 12 views
6

Angenommen, ich möchte einen JasperReport, mit dem der Benutzer nach einem Datum filtern kann, wenn er dies wünscht. Die SQL ist wie folgt:.Bedingte Where-Klauseln in JasperReports

select * from foo where bar = $P{bar} and some_date > $P{some.date} 

Nun, ich nicht von einem Datum filtern will, wenn sie das Datum nicht bestanden haben, fand ich folgende Flickschusterei, dass die Menschen nutzen:

select * from foo where bar = $P{bar} $P!{some.date.fragment} 

Und die some.date.fragment Parameter werden mit dem folgenden Standard definiert:

($P{some.date} == null || $P{some.date}.equals("")) ? "" : "AND some_date >'" + new java.sql.Date($P{some.date}.getTime()).toString() + "'" 

Dies ist nicht als toString nicht ausgibt das Datum in einem Format arbeiten, das mein SQL Server versteht. Ich möchte, dass die Bedingung immer noch eine vorbereitete Anweisung mit dem jdbc-Treiber verwendet und den Parameter hineinwirft, ich möchte nur, dass die vorbereitete Anweisung davon abhängt, ob der Parameter null ist oder nicht. Kann das gemacht werden?

+0

In meinem Fall der zweite Parameter war ein String und der Teil der Klausel where I $ P verwendet {String}. –

Antwort

6

Bevor Sie den Ausdruck $P!{} verwendet haben, übernimmt der JDBC-Treiber alle Formatierungen für Sie.

Aber wenn Sie den Ausdruck $P!{} verwenden, müssen Sie sich formatieren.

So etwas sollte funktionieren:

(
$P{some.date} == null 
? 
"" 
: 
"AND some_date >'" + (new SimpleDateFormat("dd.MM.yyyy HH:mm:ss.SSS")).format($P{some.date}) + "'" 
) 

Je nach Datentyp Sie dd.MM.yyyy HH:mm:ss.SSS anpassen müssen.

Wenn Sie den Ausdruck $P!{} nicht verwenden möchten, können Sie dies mit der folgenden Lösung vermeiden.

Ich persönlich mag diesen Weg nicht. Es kann auch einen schlechten Ausführungsplan verursachen.

Wenn Sie nicht $P!{} verwenden möchten, weil Sie sich Sorgen über SQL-Injektion. Es ist unnötig, solange Ihr Parameter $P{some.date} einen sicheren Datentyp wie java.lang.Date enthält.


Erstellen Sie einen Parameter. Sagen wir es ${is_null_pram} anrufen und einen Standard-Ausdruck mit param-Klasse hinzufügen Integer:

($P{some.date} == null ? 1 : 0) 

Jetzt können Sie abfragen:

SELECT 
    * 
FROM foo 
WHERE 
    bar = $P{bar} 
    AND 
     (
      some_date > $P{some.date} 
      OR 1 = $P{is_null_pram} 
     ) 
+0

Nun, keine dieser Lösungen ist, was ich als eine ideale Lösung wünschen würde. Ich möchte, dass der NULL-Parameter die Ausführung der SQL-Anweisung ändert, aber ich möchte auch, dass der JDBC-Treiber die Eingabe parametrisiert.Ich hasse herauszufinden, Datum Formatierung, etc. Die zweite Option scheint jedoch besser, und ich habe einige Tests mit Show Plan/Explain Plan und die Datenbanken behandeln das OR geeignet durch ignorieren das Prädikat, wenn es eine 1 = 1 wahr Bedingung ist. –

+0

Nur ein Gruß an alle, die dies sehen. Haben 'is_null_param' eine Integerzahl, die Sie mit einer anderen 1 vergleichen. Der Stringvergleich wird von einigen Datenbanken nicht optimiert. –

+0

Jup. Bearbeiten erledigt. Danke. – edze

1

ich glaube, Sie die Funktion nutzen können:

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

Es optimiert die Abfrage, wie Sie auf der Hilfeseite this sehen können.

0

Sie können diese bedingte Anweisung verwenden

select * 
    from foo 
    where bar = $P{bar} and some_date > $P{some.date} or $P{some.date} is null