2010-12-11 22 views
1

Ich versuche zu überprüfen, ob ein Datensatz bereits in der Datenbank (durch einen ähnlichen Titel) existiert, und fügen Sie es ein, wenn nicht. Ich habe es auf zwei Arten versucht und es funktioniert auch nicht.Probleme EINFÜGEN Datensatz, wenn es nicht bereits existiert

eleganteren Weg (?) Mit IF NOT

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 

Mit diesem VORHANDEN, erhalte ich einen Fehler auf der IF NOT EXISTS-Abfrage sagen, dass "Autor" nicht definiert ist (obwohl es ist).

Weniger elegante Weise mit Anzahl der gefundenen Datensätze

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 

In dieser Version anyresults ist ein Tupel, das wie (0L,) aussieht, aber ich kann nicht einen Weg passender es finden, der mich in die bekommt "Schleife zum Hinzufügen eines Buches." wenn anyresults [0] == 0, 0L, '0', '0L' - keiner von diesen scheint mich in die Schleife zu bringen.

Ich denke, ich kann nicht verwenden WENN NICHT EXISTEN richtig - Beispiele, die ich gefunden habe, sind für separate Verfahren, die nicht wirklich im Rahmen dieses kleinen Projekts sind.

ADDITION. Ich denke unutbu Code große Arbeit wird, aber ich werde noch diese dumme Nameerror bekommen Autor sagen nicht definiert ist, die die INSERT aus wird versucht, verhindert, auch wenn ich es auf jeden Fall bin vorbei in

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" 

Es druckt nie, dass "Ich bin hier" Testanweisung. Was würde es daran hindern, dorthin zu gelangen? Es scheint so offensichtlich - ich überprüfe meine Einrückung, und ich teste es auf der Kommandozeile und definiere definitiv alle drei Parameter.

+1

SQL-Injektion, los geh gehen! –

Antwort

0

Wenn Sie einen eindeutigen Index auf book einrichten, ist das Einfügen eindeutiger Zeilen einfach.

Zum Beispiel

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

ACHTUNG: Wenn es Zeilen mit nicht-eindeutigen (Titel, Autor) Paare, alle bis auf eine solche Reihe fallen gelassen wird. Wenn Sie möchten, dass nur das Feld author eindeutig ist, ändern Sie einfach in (author).

Je nachdem, wie groß der Tabelle, kann dies eine Weile dauern ...

nun einen einzigartigen Datensatz einfügen,

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

Wenn einzigartig sind, ist das Triplett (title,author,isbn) in die inserierte book Tabelle. Wenn die nicht eindeutig sind, wird der Befehl INSERT ignoriert.

Beachten Sie das zweite Argument zu . Das Übergeben von Argumenten auf diese Weise verhindert die SQL-Injektion.

+0

Danke - das ist ein klügerer Weg, es zu tun, weil ich mehrere Bücher mit demselben Titel haben möchte, solange sie von verschiedenen Autoren stammen. Ich habe immer noch einen Fehler, der besagt, dass "Autor" nicht definiert ist, auch wenn das Formular den Autor ausgefüllt hat. Ich habe zwei "wenn" in einer Reihe und es macht es nie innerhalb der zweiten. Ich fügte das oben abgeschnittene hinzu. – umbraphile

+0

@umbraphile: Irgendwie muss 'form.has_key (" author ")' False sein. Ist 'Form' ein Diktat? Können Sie 'form' oder' form.keys() 'ausdrucken, um zu sehen, welche Schlüssel es hat? Was möchten Sie tun, wenn 'form' keinen 'author'-Schlüssel hat? – unutbu

+0

Ja, das war es. Ich brauchte eine Weile, um herauszufinden, warum die anderen Formwerte verschwanden, aber es funktioniert jetzt. Danke noch einmal. – umbraphile

0

Das beantwortet Ihre Frage nicht, da es eher für Postgresql als für MySQL ist, aber ich dachte mir, ich würde es für Leute, die hier ihren Weg suchen, eintragen.

In Postgres können Sie Masseneinfügemodus Einzelteile, wenn sie existieren nicht:

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;  

Das ist ziemlich einfach. Sie wählt die neuen Zeilen so aus, als ob sie eine Tabelle wären, und dann verbindet sie sie mit den vorhandenen Daten. Die Zeilen, die noch nicht existieren, werden gegen eine NULL-Zeile zusammengefügt; Wir filtern dann diejenigen heraus, die bereits existieren (wobei book.title nicht NULL ist). Dies ist extrem schnell: Es braucht nur eine einzige Datenbanktransaktion, um einen großen Stapel von Einfügungen auszuführen, und das Datenbank-Backend führt eine Massenverbindung durch, was sehr gut ist.

Übrigens, Sie müssen wirklich aufhören, Ihre SQL-Abfragen direkt zu formatieren (es sei denn, Sie müssen wirklich und wirklich wissen, was Sie tun, was Sie hier nicht tun). Verwenden Sie Query-Substitution, z. cur.execute("SELECT * FROM table WHERE title=? and isbn=?", (title, isbn)).

Verwandte Themen