Python / postgres / psycopg2: obtendo o ID da linha recém-inserida


99

Estou usando Python e psycopg2 para fazer interface com o postgres.

Quando eu insiro uma linha ...

sql_string = "INSERT INTO hundred (name,name_slug,status) VALUES ("
sql_string += hundred_name + ", '" + hundred_slug + "', " + status + ");"
cursor.execute(sql_string)

... como obtenho o ID da linha que acabei de inserir? Tentando:

hundred = cursor.fetchall() 

retorna um erro, ao usar RETURNING id:

sql_string = "INSERT INTO domes_hundred (name,name_slug,status) VALUES ("
sql_string += hundred_name + ", '" + hundred_slug + "', " + status + ") RETURNING id;"
hundred = cursor.execute(sql_string)

simplesmente retorna None.

ATUALIZAÇÃO: O mesmo acontece currval(embora usando este comando diretamente no postgres funcione):

sql_string = "SELECT currval(pg_get_serial_sequence('hundred', 'id'));"
hundred_id = cursor.execute(sql_string)

Alguém pode aconselhar?

obrigado!

Respostas:


206
cursor.execute("INSERT INTO .... RETURNING id")
id_of_new_row = cursor.fetchone()[0]

E, por favor, não construa strings SQL contendo valores manualmente. Você pode (e deve!) Passar valores separadamente, tornando desnecessário o escape e a injeção de SQL impossível:

sql_string = "INSERT INTO domes_hundred (name,name_slug,status) VALUES (%s,%s,%s) RETURNING id;"
cursor.execute(sql_string, (hundred_name, hundred_slug, status))
hundred = cursor.fetchone()[0]

Consulte a documentação do psycopg para obter mais detalhes: http://initd.org/psycopg/docs/usage.html#passing-parameters-to-sql-queries


12
Só para esclarecer, o idin RETURNING iddeve ser o nome do campo do campo da chave serial / primária.
joshden

9
cursor fetchone me dá "nenhum resultado para buscar".
Leonid

@Leonid você descobriu isso?
Alison S

4
@AlisonS @Leonid Eu tive o mesmo erro, mas adicionar RETURNING idno final da INSERTconsulta corrigiu para mim.
Banjer

Talvez apenas uma pequena observação, mas um ponto importante a ser mencionado para todos: certifique-se de usar apenas cursor .execute () e não um cursor .mogrify () antes do comando execute () , caso contrário (como no meu caso) cursor.fetchone () não terá nenhum resultado! Usando apenas cursor .execute () sem "nada" antes desse comando, você receberá um id.
TheHeroOfTime

14

Acabei aqui porque tive um problema semelhante, mas estamos usando Postgres-XC, que ainda não suporta a cláusula RETURNING ID. Nesse caso, você pode usar:

cursor.execute ('INSERT INTO ........')
cursor.execute ('SELECT LASTVAL ()')
lastid = cursor.fetchone () ['lastval']

Para o caso de ser útil para alguém!


4
Apenas lembre-se - fazer isso em duas instruções como essa corre um risco (muito pequeno) de condições de corrida, se algo inserir uma linha no banco de dados diretamente depois de você, mas antes de seu comando lastval () retornar o valor atual da sequência.
Dave Thomas

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.