sqlite3.ProgrammingError: nombre incorrect de liaisons fournies. La déclaration actuelle utilise 1, et 74 sont fournis

198
def insert(array):
    connection=sqlite3.connect('images.db')
    cursor=connection.cursor()
    cnt=0
    while cnt != len(array):
            img = array[cnt]
            print(array[cnt])
            cursor.execute('INSERT INTO images VALUES(?)', (img))
            cnt+= 1
    connection.commit()
    connection.close()

Je ne comprends pas pourquoi cela me donne l'erreur, La chaîne réelle que j'essaie d'insérer est de 74 caractères, c'est: "/ gifs / epic-fail-photos-there-i-fixed-it-aww-man-the -tire-pressions-low.gif "

J'ai essayé de str (array [cnt]) avant de l'insérer, mais le même problème se produit, la base de données n'a qu'une seule colonne, qui est une valeur TEXT.

J'y suis depuis des heures et je n'arrive pas à comprendre ce qui se passe.

AB49K
la source

Réponses:

410

Vous devez passer dans une séquence, mais vous avez oublié la virgule pour faire de vos paramètres un tuple:

cursor.execute('INSERT INTO images VALUES(?)', (img,))

Sans la virgule, (img)est juste une expression groupée, pas un tuple, et donc la imgchaîne est traitée comme la séquence d'entrée. Si cette chaîne comporte 74 caractères, Python considère cela comme 74 valeurs de liaison distinctes, chacune d'un caractère.

>>> len(img)
74
>>> len((img,))
1

Si vous le trouvez plus facile à lire, vous pouvez également utiliser un littéral de liste:

cursor.execute('INSERT INTO images VALUES(?)', [img])
Martijn Pieters
la source
38
Nous sommes beaucoup de codeurs avancés qui ont fait cette erreur, donc pas besoin de se sentir stupide. :)
MrGumble
6
Cela m'a mordu aussi. Si les "codeurs avancés" sont trompés par cela, cela signifie que ce n'est pas intuitif. À mon humble avis, il serait plus naturel que execute () prenne une valeur unique au lieu d'un tuple à valeur unique s'il n'y en a qu'un? dans la requête. Quoi qu'il en soit, merci pour l'indice!
Laryx Decidua
5
@ user465139: L' %opérateur on strfait ce genre de magie - il traite un tuple comme plusieurs valeurs, mais a str(ou tout autre type d'itérable) comme une valeur unique. Mais cela cause de la confusion beaucoup plus souvent que cela ne le résout, c'est pourquoi presque rien d'autre dans le stdlib ne tente ce genre de magie.
abarnert le
l'utilisation %sn'est pas non plus recommandée pour des raisons de sécurité - docs.python.org/3/library/sqlite3.html
wesinat0r
2
cursor.execute(sql,array)

Prend seulement deux arguments.
Il itérera l'objet "tableau" et correspondra? dans la chaîne sql.
(avec des contrôles de cohérence pour éviter l'injection SQL)

Punnerud
la source