2012-11-14 13 views
8

Im creando un programma python che si connette a mysql.Come verificare se esiste un record con Python MySQdb

ho bisogno di verificare se una tabella contiene il numero 1 per dimostrare che si è collegato con successo, questo è il mio codice finora:

xcnx.execute('CREATE TABLE settings(status INT(1) NOT NULL)') 
    xcnx.execute('INSERT INTO settings(status) VALUES(1)') 
    cnx.commit() 
    sqlq = "SELECT * FROM settings WHERE status = '1'" 
    xcnx.execute(sqlq) 
    results = xcnx.fetchall() 
    if results =='1': 
    print 'yep its connected' 
    else: 
    print 'nope not connected' 

Che cosa ho mancato? Sono un noob, grazie ragazzi.

+0

Vuoi solo per verificare che sia possibile stabilire una connessione con il database o che sia possibile creare tabelle e inserire dati correttamente? – jdi

+0

No so che posso collegarmi creare e inserire, ho solo bisogno di sapere come controllare e verificare se esiste un record. –

risposta

14

credo che il più efficiente "Esiste" query è solo fare un count:

sqlq = "SELECT COUNT(1) FROM settings WHERE status = '1'" 
xcnx.execute(sqlq) 
if xcnx.fetchone()[0]: 
    # exists 

invece di chiedere al database per eseguire qualsiasi operazione di conteggio sui campi o righe, si sta solo chiedendo di restituisce 1 o 0 se il risultato produce corrispondenze. Questo è molto più efficiente che restituisce i record effettivi e conta il numero di client lato perché salva la serializzazione e la deserializzazione su entrambi i lati e il trasferimento dei dati.

In [22]: c.execute("select count(1) from settings where status = 1") 
Out[22]: 1L # rows 

In [23]: c.fetchone()[0] 
Out[23]: 1L # count found a match 

In [24]: c.execute("select count(1) from settings where status = 2") 
Out[24]: 1L # rows 

In [25]: c.fetchone()[0] 
Out[25]: 0L # count did not find a match 

count(*) sta per essere lo stesso di count(1). Nel tuo caso perché stai creando una nuova tabella, mostrerà 1 risultato. Se hai 10.000 corrispondenze, sarebbe 10000. Ma tutto quello che ti interessa nel test è se NON è 0, quindi puoi eseguire un test di verità bool.

Aggiornamento

In realtà, è ancora più veloce di appena usare il conteggio delle righe, e nemmeno recuperare i risultati:

In [15]: if c.execute("select (1) from settings where status = 1 limit 1"): 
      print True 
True 

In [16]: if c.execute("select (1) from settings where status = 10 limit 1"): 
      print True 

In [17]: 

Questo è anche il modo ORM di Django fa un queryObject.exists().

+0

Sono assolutamente d'accordo con il tuo metodo e lo userei in qualsiasi altra situazione, ma credo che 'COUNT (*)' sia un caso strano in cui una riga viene effettivamente restituita anche nel caso di una non corrispondenza (la riga contiene solo la numero 0). – RocketDonkey

+0

@RocketDonkey: ho corretto il mio esempio per utilizzare l'elaborazione minima possibile per verificare l'esistenza della query. Fare un 'count (1)' è ancora più piccolo. E tu verificherai il primo risultato per un singolo int. – jdi

+0

+1, ottieni il mio voto :) – RocketDonkey

1

Quando si esegue results = xcnx.fetchall(), il valore di ritorno è una sequenza di tuple che contengono i valori di riga. Pertanto, quando si controlla se results == '1', si sta tentando di confrontare una sequenza con una costante, che restituirà False. Nel tuo caso, una sola fila di valore 0 verrà restituito, così si potrebbe provare questo:

results = xcnx.fetchall() 
# Get the value of the returned row, which will be 0 with a non-match 
if results[0][0]: 
    print 'yep its connected' 
else: 
    print 'nope not connected' 

Si potrebbe in alternativa, utilizzare un DictCursor (quando si crea il cursore, utilizzare .cursor(MySQLdb.cursors.DictCursor) che renderebbe le cose un po 'più facile per interpretare codewise, ma il risultato è lo stesso:

if results[0]['COUNT(*)]': 
    # Continues... 

Inoltre, non è un grosso problema in questo caso, ma si sta confrontando un valore intero in una stringa. MySQL eseguirà la conversione del tipo, ma è possibile utilizzare SELECT COUNT(*) FROM settings WHERE status = 1 e salvare un (molto piccolo) bit di elaborazione.

2

Se tutto ciò che si vuole fare è controllare se è stata stabilita una connessione, perché si sta tentando di creare una tabella, inserire una riga e quindi recuperare i dati da essa?

Si potrebbe semplicemente effettuare le seguenti ...

sqlq = "SELECT * FROM settings WHERE status = '1'" 
xcnx.execute(sqlq) 
results = xcnx.fetchone() 
if results =='1': 
    print 'yep its connected' 
else: 
    print 'nope not connected' 

In realtà, se il programma non ha generato un'eccezione finora indica che è stata stabilita la connessione con successo. (Controlla il codice qui sopra, non sono sicuro che fetchone restituirà una tupla, una stringa o un int in questo caso).

A proposito, se per qualche motivo hai bisogno di creare la tabella, ti suggerisco di lasciarlo prima di uscire in modo che il tuo programma funzioni correttamente la seconda volta.

0

Recentemente ho migliorato la mia efficienza anziché interrogare select, aggiungendo semplicemente un indice primario alla colonna univoca e quindi aggiungendolo. MySQL lo aggiungerà solo se non esiste.

Così, invece di 2 affermazioni:

Query MySQL for exists: 
    Query MySQL insert data 

Just do 1 e funziona solo se è unico nel suo genere:

Query MySQL insert data 

1 Query è meglio di 2.

Problemi correlati