2009-06-30 8 views
1

Je suis nouveau sur python et j'ai rencontré un problème avec une requête SQL que j'essaie d'effectuer.Python SQL Select avec des valeurs NULL possibles

Je crée une instruction SQL SELECT qui est rempli avec des valeurs d'un tableau comme suit:

ret = conn.execute('SELECT * FROM TestTable WHERE a = ? b = ? c = ?', *values) 

Cela fonctionne bien où j'ai des valeurs réelles dans le tableau de valeurs. Cependant, dans certains cas, une entrée individuelle dans les valeurs peut être définie sur Aucune. La requête échoue alors parce que le test "= NULL" ne fonctionne pas puisque le test devrait être IS NULL.

Y at-il un moyen facile de contourner ce problème?

Répondre

1

Si vous utilisez SQL Server puis aussi longtemps que vous définissez ansi_nulls hors de la session « = null » comparaison marchera.

SET ANSI_NULLS

+0

C'est une bonne solution simple et fonctionne bien. Merci beaucoup! – JamieH

3

Utilisation: "Select * from testtable où (a = ou est nul?) Et (b = b est nul?)"

Cela permet de sélectionner les cas où un correspond exactement à la valeur fournie et comprendra les valeurs nulles dans la colonne - si c'est ce que vous voulez.

+0

En outre, la valeur Python 'None' est équivalente à un SQL' NULL'. –

0

Si vous vous sentez aventureux, vous pouvez également consulter SQLAlchemy. Il fournit entre autres un ensemble d'outils de construction SQL qui convertit automatiquement les comparaisons en None dans les opérations IS NULL.

1

Vous pouvez toujours utiliser l'opérateur ternaire pour passer '=' pour 'EST':

("=","IS")[var is None] 

reviendriez "IS" si var est None et "=" autrement.

Ce n'est pas très élégant de faire cela en une ligne bien, mais juste pour démontrer:

query = "SELECT * FROM testTable WHERE a %s %s" % (("=","IS")[a is None], str(a)) 
0

D'abord et avant tout, je ne saurais trop vous mettre en garde contre l'utilisation SELECT * FROM tbl WHERE (col = :x OR col IS NULL) car cela sera très probablement disqualifier votre requête de l'indexation (utilisez un profileur de requête). SET ANSI_NULLS est également l'une de ces choses qui ne peuvent pas être pris en charge dans votre type de base de données particulier.

Une meilleure solution (ou au moins une solution plus universelle) est, si votre dialecte SQL prend en charge Coalesce, pour écrire votre requête comme ceci:

SELECT * FROM tbl WHERE col = COALESCE(:x, col) 

Depuis col = col sera toujours évaluée à true, en passant NULL pour :x ne nuira pas à votre requête, et devrait permettre un plan de requête plus efficace. Cela présente également l'avantage de fonctionner à l'intérieur d'une procédure stockée, où vous n'avez pas la liberté de créer dynamiquement une chaîne de requête.

0

Ce qui suit a été testé sur python sqlite3 maintenant, mais il devrait fonctionner dans d'autres types de DB car il est assez général. L'approche est la même pour @MoshiBin répondre avec quelques ajouts:

Voici la forme en utilisant le curseur.execute() syntaxe régulière, de sorte que les variables nulles ne sont pas pris en charge en utilisant ce formulaire:

import sqlite3 
conn = sqlite3.connect('mydbfile.db') 
c = conn.cursor() 
c.execute('SELECT * FROM TestTable WHERE colname = ?', (a,)) 

Afin de soutenir les variables nulles que vous pouvez remplacer la 4e ligne:

request = 'SELECT * FROM TestTable WHERE colname %s' % ('= ' + str(a) if a else 'IS NULL') 
c.execute(request) 

En outre, si la variable est dans le type de texte, vous devez également inclure un devis:

request = "SELECT * FROM TestTable WHERE colname %s" % ("= '" + a + "'" if a else 'IS NULL') 

Finaly si une variable peut contenir un seul se guillemets, vous devez également y échapper en doublant:

request = "SELECT * FROM TestTable WHERE colname %s" % ("= '" + a.replace("'", "''") + "'" if a else 'IS NULL') 

Modifier:
Dernièrement, j'ai trouvé deux autres approches qui peuvent également être utilisés dans ce cas et utilise la syntaxe cursor.execute() régulière, mais je did't tester ce les maintenant:

c.execute('SELECT * FROM TestTable WHERE colname = :1 OR (:1 IS NULL AND colname IS NULL)', {'1': a}) 

(Thx à @BillKarwin answer)

ou, en utilisant l'expression CASE:

c.execute('SELECT * FROM TestTable WHERE CASE :1 WHEN NOT NULL THEN colname = :1 ELSE colname IS NULL END', {'1': a}) 
Questions connexes