Skip to content
Advertisement

pyscopg2: Is it possible to dynamically add %s in loop

I am trying to create a method in python insert records into a table passing in a list of column names, and an associated list of records.

I was able to set it up where the column names populated dynamically via a for loop, but I can’t figure out how to do the same thing with values because the psycopg2.executemany function relies on having %s’s as placeholders.

Is it possible to have the number of %s’s in the string populate dynamically via a loop? Is there another way to do this?

def load_table(dbname,table_name,fields,records):
        try:
                #Variable Qty Column Loop
                sql_fields = []
                for i in fields:
                        i = sql.Identifier(i)
                        sql_fields.append(i)

                #Need similar loop to replace %s values
                #Replace (%s,%s,%s) ???
                #.....
                #.....
                sql_values = []
                for i in fields:
                        sql_values.append('%s')

                print(sql_values)
                flist = sql.SQL(',').join(sql_fields)  
                connection, cursor = create_connection(dbname)
                insert_query = sql.SQL('INSERT INTO {table_name} ({fields}) VALUES (%s,%s,%s)').format(
                table_name = sql.Identifier(table_name),
                fields = flist,
                cursor.executemany(insert_query,records)
                print('Records Loaded Successfully')

        except (Exception,psycopg2.Error) as error:
                print("Failed to insert record into table {error}".format(error = error))

        finally:
                # closing database connection.
                if (connection):
                        close_connection(connection,cursor)

Advertisement

Answer

You can use sql.Placeholder, to populate the sql statement with the amount of %s-placeholders you need:

def load_table(dbname,table_name,fields,records):
        con, cur = create_connection('foo')
        query = sql.SQL("insert into {} ({}) values ({})").format(
            sql.Identifier(table_name),
            sql.SQL(', ').join(map(sql.Identifier, fields)),
            sql.SQL(', ').join(sql.Placeholder() * len(fields)))
        print(query.as_string(con))


if __name__ == '__main__':
    dbname = '...'
    table_name = 'messages'
    fields = ['user_id', 'message_type', 'message_title']
    records = [['12345', 'json', 'my first message'], ]

load_table(dbname,table_name,fields,records)

Output:

insert into "messages" ("user_id", "message_type", "message_title") values (%s, %s, %s)
8 People found this is helpful
Advertisement