2017-09-12 2 views
3

J'ai été sur cela plusieurs fois, j'ai pris une copie du fichier de base de données à des fins de test et même renommé le champ pour correspondre au script Python. Donc, le nom de champ que j'utilise en Python correspond exactement au nom du champ des tables.Python PYODBC INSERT - Trop peu de paramètres

import pyodbc 

def main(): 
tble="SomeTable" 
fld1="SomeField" 
val1="TestValue" 
sqlStrng = """INSERT INTO %s (%s) VALUES(%s);""" %(tble, fld1,val1) 

contStrng = (
    r'DRIVER={Microsoft Access Driver (*.mdb, *.accdb)};' 
    r'DBQ=Some\Path\File.accdb;' 
) 

cnnctn = pyodbc.connect(contStrng) 
cursr = cnnct.cursor() 

cursr.execute(sqlStrng) 

cnnctn.commit() 
cnnctn.close() 

Ceci n'est pas un problème d'orthographe. J'ai fait une copie de test du fichier Access et créé une table appelée SomeTable avec un champ appelé SomeField. J'ai le bon chemin, j'ai vérifié cela en exécutant un script SELECT SQL, qui fonctionne sans problème.

J'ai essayé de faire de fld1 un paramètre et de l'envoyer avec la commande d'exécution, mais alors je suis informé que j'ai besoin de 0 paramètres. Quand je l'enlève, je suis informé que j'ai besoin de 1.

Je commence à penser que c'est peut-être ce fichier? Le même code fonctionne sur un autre fichier que j'ai. Cependant, j'ai créé un tout nouveau fichier et les mêmes résultats. Je dois manquer quelque chose.

Répondre

2

Si vous print(sqlStrng) immédiatement après l'avoir assigné, vous verrez que sa valeur est

INSERT INTO SomeTable (SomeField) VALUES(TestValue); 

Les friandises moteur de base de données d'accès des noms non reconnus en tant que paramètres, il veut donner une valeur de paramètre pour nomTestValue . Si vous souhaitez insérer alors la valeur de chaîne 'TestValue' vous devez utiliser un espace réservé paramètre pyodbc (?) et passer val1 comme paramètre dans la méthode .execute, comme ceci:

tble="SomeTable" 
fld1="SomeField" 
val1="TestValue" 
sqlStrng = """INSERT INTO [%s] ([%s]) VALUES(?);""" %(tble, fld1) 

contStrng = (
r'DRIVER={Microsoft Access Driver (*.mdb, *.accdb)};' 
r'DBQ=Some\Path\File.accdb;' 
) 

cnnctn = pyodbc.connect(contStrng) 
cursr = cnnct.cursor() 

cursr.execute(sqlStrng, val1) 

Notez que vous ne seriez pas obtenir une erreur si SomeField était un champ Numéro et que vous utilisiez val1=123 car 123 serait traité comme un littéral numérique et non comme un nom non reconnu (valeur de texte non cotée).

+0

Cela a fonctionné, mais pourriez-vous me dire pourquoi dans un cas cela fonctionne bien, et dans celui-ci il ne fonctionne pas? Je suis nouveau à l'écriture de code Python, pas à la connexion de bases de données. Une autre fonction d'insertion que j'ai écrite fait la même chose sur une table différente et cela fonctionne sans problème. Évidemment, les noms de champs et de valeurs sont différents. Merci de clarifier; De toute évidence, dans mes recherches, j'ai mal compris comment appliquer les paramètres. –

+0

Le terme pour votre approche originale est "SQL dynamique", et le SQL dynamique est sujet à des vulnérabilités "d'injection SQL" où les valeurs de données * peuvent causer des problèmes avec la syntaxe SQL. La plus célèbre de ces vulnérabilités est liée à la sécurité et à l'intégrité de la base de données (réf: "Little Bobby Tables"), mais les problèmes d'injection SQL peuvent aussi provoquer le crash des programmes pour certaines valeurs de données. C'est pourquoi il est important d'utiliser une "requête paramétrée" pour transmettre les valeurs de données à la requête, comme indiqué dans ma réponse. –

+0

Je voulais ajouter à cela, car j'ai commencé à travailler plus régulièrement en Python et j'ai rencontré un problème similaire. J'essayais de faire une requête de sélection. J'ai gardé un message indiquant que 4 paramètres étaient requis, mais 3 ont été fournis. J'ai ajouté un aléatoire supplémentaire seulement pour être dit à la requête requise seulement 3. Le problème est qu'un nom de table ne peut pas être un paramètre: https://stackoverflow.com/questions/6669009/passing-table-name-as-a- paramètre-dans-pyodbc. Tout le reste peut être des paramètres, mais vous devez écrire votre sql et stocker dans une variable de chaîne avec la variable de table passée dedans. –