2010-12-11 1 views
1

J'essaie de vérifier si un enregistrement existe déjà dans la base de données (par un titre similaire) et de l'insérer si ce n'est pas le cas. Je l'ai essayé de deux façons et ni tout à fait fonctionne.Problèmes INSERTION d'un enregistrement s'il n'existe pas déjà

façon plus élégante (?) En utilisant SINON EXISTE

if mode=="update": 
    #check if book is already present in the system 
    cursor.execute('IF NOT EXISTS (SELECT * FROM book WHERE TITLE LIKE "%s") INSERT INTO book (title,author,isbn) VALUES ("%s","%s","%s") END IF;' % (title,title,author,isbn)) 
    cursor.execute('SELECT bookID FROM book WHERE TITLE LIKE "%s";' % (title)) 
    bookID = cursor.fetchall() 
    print('found the bookid %s' % (bookID)) 
    #cursor.execute('INSERT INTO choice (uid,catID,priority,bookID) VALUES ("%d","%s","%s","%s");' % ('1',cat,priority,bookID)) #commented out because above doesn't work 

Avec cela, je reçois une erreur sur la SINON EXISTE requête en disant que « l'auteur » n'est pas défini (bien qu'il soit).

moins élégante façon en utilisant le nombre d'enregistrements correspondant à

if mode=="update": 
    #check if book is already present in the system 
    cursor.execute('SELECT COUNT(*) FROM book WHERE title LIKE "%s";' % (title)) 
    anyresults = cursor.fetchall() 
    print('anyresults looks like %s' % (anyresults)) 
    if anyresults[0] == 0: # if we didn't find a bookID 
     print("I'm in the loop for adding a book") 
     cursor.execute('INSERT INTO book (title,author,isbn) VALUES ("%s","%s","%s");' % (title,author,isbn)) 
    cursor.execute('SELECT bookID FROM book WHERE TITLE LIKE "%s";' % (title)) 
    bookID = cursor.fetchall() 
    print('found the bookid %s' % (bookID)) 
    #cursor.execute('INSERT INTO choice (uid,catID,priority,bookID) VALUES ("%d","%s","%s","%s");' % ('1',cat,priority,bookID)) #commented out because above doesn't work 

Dans cette version, anyresults est un tuple qui ressemble à (0L,) mais je ne peux pas trouver un moyen de celui-ci qui me fait correspondre dans ce "boucle pour ajouter un livre." si anyresults [0] == 0, 0L, '0', '0L' - aucun de ceux-ci ne semble me mettre dans la boucle.

Je pense que je ne vais peut-être pas utiliser IF NOT EXISTS correctement - des exemples que j'ai trouvés sont pour des procédures séparées, qui ne sont pas vraiment dans le cadre de ce petit projet.

AJOUT:. Je pense que le code de unutbu fonctionnera très bien, mais je vais faire encore cette NameError muet disant auteur est indéfini qui empêche l'INSERT d'être essayé, même quand je suis faisant passer définitivement dans

if form.has_key("title"): 
    title = form['title'].value 
    mode = "update" 
if form.has_key("author"): 
    author = form['author'].value 
    mode = "update" 
    print("I'm in here") 
if form.has_key("isbn"): 
    isbn = form['isbn'].value 
    mode = "update" 

Il n'imprime jamais cette instruction "Je suis ici". Qu'est-ce qui l'empêcherait d'entrer là-bas? Cela semble si évident - je continue de vérifier mon indentation, et je la teste sur la ligne de commande et je spécifie clairement les trois paramètres.

+1

Injection SQL, partez! –

Répondre

0

Si vous définissez un index UNIQUE sur book, l'insertion de lignes uniques est facile.

Par exemple,

mysql> ALTER IGNORE TABLE book ADD UNIQUE INDEX book_index (title,author); 

AVERTISSEMENT: s'il y a des lignes avec des paires non uniques (titre, auteur), tout sauf une telle ligne seront supprimés. Si vous voulez que le champ author soit unique, changez simplement en (author).

Selon la taille de la table, cela peut prendre un certain temps ...

Maintenant, pour insérer un enregistrement unique,

sql='INSERT IGNORE INTO book (title,author,isbn) VALUES (%s, %s, %s)' 
cursor.execute(sql,[title,author,isbn]) 

Si sont uniques, le triplet (title,author,isbn) est inséré dans le book tableau. Si ne sont pas uniques, la commande INSERT est ignorée.

Remarque, le second argument à cursor.execute. Passer des arguments de cette façon permet d'éviter l'injection SQL.

+0

Merci - c'est une façon plus intelligente de le faire parce que je veux être en mesure d'avoir plusieurs livres avec le même titre tant qu'ils sont par des auteurs différents. J'ai toujours un bogue, où il est dit que "auteur" n'est pas défini même si le formulaire a un auteur rempli. J'ai deux "si" dans une rangée et il ne le fait jamais dans le second. J'ai ajouté le snipped ci-dessus. – umbraphile

+0

@umbraphile: D'une manière ou d'une autre, 'form.has_key (" author ")' doit être False. Est-ce que 'form' est un dict? Pouvez-vous imprimer 'form' ou' form.keys() 'pour voir quelles clés il a? Que voulez-vous arriver si 'form' n'a pas de clé 'author'? – unutbu

+0

Oui, c'était tout. Il m'a fallu un certain temps pour comprendre pourquoi les valeurs des autres formes disparaissaient mais cela fonctionne maintenant. Merci encore. – umbraphile

0

Cela ne répond pas à votre question car c'est pour Postgresql plutôt que pour MySQL, mais je me suis dit que je laisserais tomber les gens qui cherchent leur chemin ici.

En Postgres, vous pouvez regrouper des éléments d'insertion par lots si elles n'existez pas:

CREATE TABLE book (title TEXT, author TEXT, isbn TEXT); 

# Create a row of test data: 
INSERT INTO book (title,author,isbn) VALUES ('a', 'b', 'c'); 

# Do the real batch insert: 
INSERT INTO book 
SELECT add.* FROM (VALUES 
('a', 'b', 'c'), 
('d', 'e', 'f'), 
('g', 'h', 'i'), 
) AS add (title, author, isbn) 
LEFT JOIN book ON (book.title = add.title) 
WHERE book.title IS NULL;  

Ceci est assez simple. Il sélectionne les nouvelles lignes comme s'il s'agissait d'une table, puis les rejoint à gauche par rapport aux données existantes. Les lignes qui n'existent pas déjà se joindront à une ligne NULL; nous filtrons ensuite ceux qui existent déjà (où book.title n'est pas NULL). C'est extrêmement rapide: il suffit d'une seule transaction de base de données pour effectuer un grand nombre d'insertions, et le backend de la base de données fait une jointure en masse, ce qui est très bien. A propos, vous devez vraiment arrêter de formater vos requêtes SQL directement (sauf si vous avez vraiment besoin de savoir ce que vous faites et que vous savez vraiment ce que vous faites, ce qui n'est pas le cas ici). Utilisez la substitution de requête, par exemple. cur.execute("SELECT * FROM table WHERE title=? and isbn=?", (title, isbn)).

Questions connexes