La déclaration est
SELECT * FROM tableA WHERE x = ?
et le paramètre est inséré via Java.sql.PreparedStatement 'stmt'
stmt.setString(1, y); // y may be null
Si y
est null, l'instruction ne renvoie aucune ligne dans tous les cas car x = null
est toujours faux (doit être x IS NULL
) .
SELECT * FROM tableA WHERE x = ? OR (x IS NULL AND ? IS NULL)
Mais alors je dois définir le même paramètre deux fois. Y a-t-il une meilleure solution?
Merci!
Je l'ai toujours fait comme vous l'avez montré dans votre question. Définir le même paramètre deux fois n'est pas une si grande difficulté, n'est-ce pas?
SELECT * FROM tableA WHERE x = ? OR (x IS NULL AND ? IS NULL);
Il existe un opérateur ANSI-SQL assez inconnu, IS DISTINCT FROM
, qui gère les valeurs NULL. Il peut être utilisé comme ça:
SELECT * FROM tableA WHERE x NOT IS DISTINCT FROM ?
Donc, un seul paramètre doit être défini. Malheureusement, ceci n'est pas supporté par MS SQL Server (2008).
Une autre solution pourrait être, s'il y a une valeur qui est et ne sera jamais utilisée ('XXX'):
SELECT * FROM tableA WHERE COALESCE(x, 'XXX') = COALESCE(?, 'XXX')
voudrais simplement utiliser 2 déclarations différentes:
Déclaration 1:
SELECT * FROM tableA WHERE x is NULL
Affirmation 2:
SELECT * FROM tableA WHERE x = ?
Vous pouvez vérifier votre variable et construire l'instruction appropriée en fonction de la condition. Je pense que cela rend le code beaucoup plus clair et facile à comprendre.
EDIT.__ Au fait, pourquoi ne pas utiliser de procédures stockées? Ensuite, vous pouvez gérer toute cette logique NULL dans le SP et simplifier les choses lors de l'appel frontal.
Si vous utilisez par exemple mysql, vous pourriez probablement faire quelque chose comme:
select * from mytable where ifnull(mycolumn,'') = ?;
Alors tu pourrais faire:
stmt.setString(1, foo == null ? "" : foo);
Vous devrez vérifier votre plan d'explication pour voir s'il améliore vos performances. Cela signifierait cependant que la chaîne vide est égale à null, elle n'est donc pas accordée et répondrait à vos besoins.
Dans Oracle 11g, je le fais de cette façon, car x = null
est techniquement évalué à UNKNOWN
:
WHERE (x IS NULL AND ? IS NULL)
OR NOT LNNVL(x = ?)
L'expression avant le OR
prend soin d'associer NULL à NULL, puis l'expression après prend en charge toutes les autres possibilités. LNNVL
change UNKNOWN
en TRUE
, TRUE
en FALSE
et FALSE
en TRUE
, qui est l'exact opposé de ce que nous voulons, d'où le NOT
.
La solution acceptée ne fonctionnait pas pour moi dans Oracle dans certains cas, alors qu’elle faisait partie d’une expression plus large, impliquant une NOT
.