2009-10-24 8 views
8

Solo un principiante con la combinazione python/postgres quindi perdonami se questo è banale. Sto esecuzione di una query SQL greggio sqlalchemy lungo le linee di:clausola IN con numeri interi in sqlalchemy/psycopg2

SELECT * FROM table WHERE pk_table_id IN() 

Per l'esempio qui sotto ho provato self.ids come una tupla contenente stringa o numeri interi, nonché una matrice contenente stringa o numeri interi. In ogni caso, non ha funzionato.

Quando uso questa linea:

my_connection.execute('SELECT * FROM public.table WHERE pk_table_id IN (%s)', self.ids) 

ottengo l'errore:

TypeError: not all arguments converted during string formatting 

Qualche suggerimento?

risposta

3

Il segnaposto %s in execute prevede uno scalare, non una tupla. È necessario sostituirlo con ','.join(('%s',) * len(mytuple)) o utilizzare invece la sostituzione di stringhe!

+0

fissa la risposta, perché la la versione originale produrrebbe ''%, s,%, s,%, s''. –

+0

Non è corretto: la query single '% s' si aspetta la sequenza con un singolo elemento. –

+0

Questa è la soluzione che ho usato per risolvere il mio problema, grazie. Il mio usecase: '' tags_to_remove = set (['foo', 'bar']) '' '' db.execute ('DELETE FROM article_tags WHERE article_id =? AND nome tag IN (% s)'% (', '.join ((' '?',) * len (tags_to_remove))), article_id, * tags_remove) '' – bufh

0

se self.ids è un array, si verificherà un problema durante la conversione all'interno dell'istruzione execute. Invece, dovresti farlo come operazione stringa prima di chiamare l'istruzione execute.

Prova questa:

my_connection.execute('SELECT * FROM public.table WHERE pk_table_id IN (%s)' % 
         ",".join(str(x) for x in self.ids)) 
+0

Nota: la chiamata data a 'join' richiederebbe che gli ID in' self.ids' siano stringhe. – Walter

+0

No, non lo farebbe. Python usa% s per tutte le sostituzioni di variabili. – vy32

+0

Certo, il passaggio dei parametri di formattazione delle stringhe 'int's a'% s' funzionerebbe, ma 'str.join()' non è così liberale. Prova '','. Join (range (10))' in una shell Python. – Walter

6

ho finito ammaraggio SQLAlchemy per psycopg2 dritto, quindi non so se si applica al 100%. Quello che ho scoperto è che psycopg2 compilerà correttamente la clausola IN se si passa una tupla piuttosto che una matrice/lista. Ho passato una tupla di interi e ha funzionato bene.

+0

Grazie, funziona molto bene. Invece di usare 'params = [list]' si dovrebbe usare 'params = [tuple (list)]' – jnns

+1

+1 - vedi anche i documenti: http://initd.org/psycopg/docs/usage.html#passing- parametri-to-sql-query – moooeeeep

7

È possibile utilizzare il metodo cur.mogrify:

cur = my_connection.cursor() 
cur.execute(cur.mogrify('SELECT * FROM public.table WHERE pk_table_id IN %s', (tuple(self.ids),))) 
+0

non dimenticare di chiudere il cursore 'cur.close()' – Pykler

+0

Non penso che sia necessario usare 'cur.mogrify' all'interno di 'cur.execute', questo funziona direttamente nel 'execute' method – Anentropic

+0

@Anentropic se funziona allora questa è una nuova versione. Se intendi per lavori che usi il segno%, allora stai introducendo un problema di sicurezza e spero che tu non lo intenda! – Pykler

2

se gli ID sono in un elenco è possibile utilizzare l'elenco di adattamento:

my_connection.execute('SELECT * FROM public.table WHERE pk_table_id = ANY(%s)', (self.ids,)) 

Tratto da lists-adaptation

Problemi correlati