Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Cursors in a Loop

Reply
Thread Tools

Cursors in a Loop

 
 
t_rectenwald
Guest
Posts: n/a
 
      01-04-2008
I have a python script that uses the cx_Oracle module. I have a list
of values that I iterate through via a for loop and then insert into
the database. This works okay, but I'm not sure whether I can use one
cursor for all inserts, and define it outside of the loop, or
instantiate and close the cursor within the loop itself. For example,
I have:

for i in hostlist:
cursor = connection.cursor()
sql= "insert into as_siebel_hosts_temp values('%s')" % (i)
cursor.execute(sql)
cursor.close()

And I've also tried:

cursor = connection.cursor()
for i in hostlist:
sql= "insert into as_siebel_hosts_temp values('%s')" % (i)
cursor.execute(sql)
cursor.close()

Both work fine, and execute in the same amount of time. I'm just
trying to understand what is the "correct" approach to use.

Thanks,
Tom

 
Reply With Quote
 
 
 
 
t_rectenwald
Guest
Posts: n/a
 
      01-04-2008
On Jan 3, 7:47*pm, t_rectenwald <t.rectenw...@gmail.com> wrote:
> I have a python script that uses the cx_Oracle module. *I have a list
> of values that I iterate through via a for loop and then insert into
> the database. *This works okay, but I'm not sure whether I can use one
> cursor for all inserts, and define it outside of the loop, or
> instantiate and close the cursor within the loop itself. *For example,
> I have:
>
> for i in hostlist:
> * * cursor = connection.cursor()
> * * sql= "insert into as_siebel_hosts_temp values('%s')" % (i)
> * * cursor.execute(sql)
> * * cursor.close()
>
> And I've also tried:
>
> cursor = connection.cursor()
> for i in hostlist:
> * * sql= "insert into as_siebel_hosts_temp values('%s')" % (i)
> * * cursor.execute(sql)
> cursor.close()
>
> Both work fine, and execute in the same amount of time. *I'm just
> trying to understand what is the "correct" approach to use.
>
> Thanks,
> Tom


I think I have this one figured out. The answer would be the second
option, i.e. keep the cursor instantion and close outside of the
loop. I wasn't aware that one cursor could be used for multiple
executes.

Regards,
Tom
 
Reply With Quote
 
 
 
 
Carsten Haese
Guest
Posts: n/a
 
      01-04-2008
On Thu, 2008-01-03 at 17:25 -0800, t_rectenwald wrote:
> On Jan 3, 7:47 pm, t_rectenwald <t.rectenw...@gmail.com> wrote:
> > I have a python script that uses the cx_Oracle module. I have a list
> > of values that I iterate through via a for loop and then insert into
> > the database. This works okay, but I'm not sure whether I can use one
> > cursor for all inserts, and define it outside of the loop, or
> > instantiate and close the cursor within the loop itself. For example,
> > I have:
> >
> > for i in hostlist:
> > cursor = connection.cursor()
> > sql= "insert into as_siebel_hosts_temp values('%s')" % (i)
> > cursor.execute(sql)
> > cursor.close()
> >
> > And I've also tried:
> >
> > cursor = connection.cursor()
> > for i in hostlist:
> > sql= "insert into as_siebel_hosts_temp values('%s')" % (i)
> > cursor.execute(sql)
> > cursor.close()
> >
> > Both work fine, and execute in the same amount of time. I'm just
> > trying to understand what is the "correct" approach to use.


Actually, the correct approach would be "neither." You should NEVER use
string formatting to fill values into an SQL query. (Doing so causes
security vulnerabilities and performance problems. See, for example,
http://informixdb.blogspot.com/2007/...in-blanks.html for
detailed explanations.) Instead, you should use a parametrized query.

With a parametrized query, your code becomes this:

cursor = connection.cursor()
for i in hostlist:
cursor.execute("insert into as_siebel_hosts_temp values(?)", (i,) )
cursor.close()

Since this will save the database engine from having to re-parse the
query every time, it will run much faster if the list is long.

Even better would be to use executemany:

cursor = connection.cursor()
cursor.executemany("insert into as_siebel_hosts_temp values(?)",
[(i,) for i in hostlist] )
cursor.close()

Depending on whether cx_Oracle allows this, the list comprehension in
that example could be replaced by the generator expression
((i,) for i in hostlist), but I don't know if cx_Oracle allows
executemany with an arbitrary iterable.

Hope this helps,

--
Carsten Haese
http://informixdb.sourceforge.net


 
Reply With Quote
 
Chris
Guest
Posts: n/a
 
      01-04-2008
On Jan 4, 5:11 am, Carsten Haese <cars...@uniqsys.com> wrote:
> On Thu, 2008-01-03 at 17:25 -0800, t_rectenwald wrote:
> > On Jan 3, 7:47 pm, t_rectenwald <t.rectenw...@gmail.com> wrote:
> > > I have a python script that uses the cx_Oracle module. I have a list
> > > of values that I iterate through via a for loop and then insert into
> > > the database. This works okay, but I'm not sure whether I can use one
> > > cursor for all inserts, and define it outside of the loop, or
> > > instantiate and close the cursor within the loop itself. For example,
> > > I have:

>
> > > for i in hostlist:
> > > cursor = connection.cursor()
> > > sql= "insert into as_siebel_hosts_temp values('%s')" % (i)
> > > cursor.execute(sql)
> > > cursor.close()

>
> > > And I've also tried:

>
> > > cursor = connection.cursor()
> > > for i in hostlist:
> > > sql= "insert into as_siebel_hosts_temp values('%s')" % (i)
> > > cursor.execute(sql)
> > > cursor.close()

>
> > > Both work fine, and execute in the same amount of time. I'm just
> > > trying to understand what is the "correct" approach to use.

>


> Even better would be to use executemany:
>
> cursor = connection.cursor()
> cursor.executemany("insert into as_siebel_hosts_temp values(?)",
> [(i,) for i in hostlist] )
> cursor.close()
>
> Depending on whether cx_Oracle allows this, the list comprehension in
> that example could be replaced by the generator expression
> ((i,) for i in hostlist), but I don't know if cx_Oracle allows
> executemany with an arbitrary iterable.


You should bind all variables to save the pool.

cursor = connection.cursor()
cursor.executemany("""insert into as_siebel_hosts_temp
values (:whole, :lot, f, :bind, :variables)
"""
,[(i,)[0] for i in hostlist]
)
connection.commit()
connection.close()
 
Reply With Quote
 
Carsten Haese
Guest
Posts: n/a
 
      01-04-2008
On Fri, 2008-01-04 at 00:03 -0800, Chris wrote:
> You should bind all variables to save the pool.
>
> cursor = connection.cursor()
> cursor.executemany("""insert into as_siebel_hosts_temp
> values (:whole, :lot, f, :bind, :variables)
> """
> ,[(i,)[0] for i in hostlist]
> )
> connection.commit()
> connection.close()


Huh? In the OP's example, the table one has one column. I'll openly
admit that I don't know anything about Oracle, but that code doesn't
make sense to me. Maybe you're trying to execute a multi-row insert, but
that would be done with execute(), not executemany(), wouldn't it?

Also, isn't "[(i,)[0] for i in hostlist]" exactly the same as "[i for i
in hostlist]" which in turn is exactly the same as "hostlist"?

--
Carsten Haese
http://informixdb.sourceforge.net


 
Reply With Quote
 
Chris
Guest
Posts: n/a
 
      01-05-2008
On Jan 4, 4:32 pm, Carsten Haese <cars...@uniqsys.com> wrote:
> On Fri, 2008-01-04 at 00:03 -0800, Chris wrote:
> > You should bind all variables to save the pool.

>
> > cursor = connection.cursor()
> > cursor.executemany("""insert into as_siebel_hosts_temp
> > values (:whole, :lot, f, :bind, :variables)
> > """
> > ,[(i,)[0] for i in hostlist]
> > )
> > connection.commit()
> > connection.close()

>
> Huh? In the OP's example, the table one has one column. I'll openly
> admit that I don't know anything about Oracle, but that code doesn't
> make sense to me. Maybe you're trying to execute a multi-row insert, but
> that would be done with execute(), not executemany(), wouldn't it?
>
> Also, isn't "[(i,)[0] for i in hostlist]" exactly the same as "[i for i
> in hostlist]" which in turn is exactly the same as "hostlist"?
>
> --
> Carsten Haesehttp://informixdb.sourceforge.net


The OPs example has a formatted string, no idea what is in it...
My example creates a tuple out of each of the records you want to
insert and uses them in the bind variables.

You can do a loop through hostlist and do a single execute on each one
if you want. It won't make a large impact.
The [(i,)[0] for i in hostlist] was mainly directed to you because
your structure ends up being a tuple inside a list which doesn't work
for cx_Oracle. You need a straight tuple to bind to the statement.

My code creates a series of usable tuples for the executemany
function.
HTH,
Chris
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Triple nested loop python (While loop insde of for loop inside ofwhile loop) Isaac Won Python 9 03-04-2013 10:08 AM
Ann: OleDBProNet released for getting back server cursors on .Net platform Lei Yang ASP .Net 0 10-08-2005 05:17 PM
datasets, dropdownlists, cursors, defaultviews et ASP .Net 3 11-18-2004 05:10 PM
Database cursors in .NET 2003 Kenneth ASP .Net 3 08-07-2003 03:46 PM
Have a problem with using cursors in SQL server enterprise manager TaeHo Yoo ASP .Net 2 06-26-2003 10:08 AM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57