approach for assigning ODBC results to fieldnames as variables?

Robin Thomas robin.thomas at starmedia.net
Tue Feb 27 13:54:30 EST 2001


At 03:41 PM 2/27/01 +0000, fluxent at yahoo.com wrote:
>When you execute a SQL (select) query via ODBC and do a fetchall(),
>you get back a result set as a tuple (array). You can also ask for
>the cursor's description, which returns a separate tuple, the first
>column of which contains the fieldnames (or other labels calculated
>by SQL).

A common approach is to encapsulate the cursor so that the description is 
fetched once, and rows are turned into dictionaries with the values in 
description tuple used as keys.


>Is there a standard approach to assigning field names to columns, so
>that this output line could be changed to something like
>   Response.Write('<tr><td>%s<td>%s<td>%s<td><a
>href="matterEdit.asp?clientID=%s&matterID=%s">%s</a><td>%s<td>%
>s</tr>' % (maxDate, clientID, clientName, clientID, jobID, jobID,
>jobName, totalHours))

Dynamic name binding can be very problematic. Dictionaries give you the 
desired behavior without the name-binding mess. Especially when you use 
named placeholders in string formatting. A shortened example:

Response.Write('<tr><td>%(MAXDATE)s' % row_as_dictionary)

Be careful of the case of the column names returned by description().

>or even at least something like
>   Response.Write('<tr><td>%s<td>%s<td>%s<td><a href="matterEdit.asp?
>clientID=%s&matterID=%s">%s</a><td>%s<td>%s</tr>' % (maxDate[i],
>clientID[i], clientName[i], clientID[i], jobID[i], jobID[i], jobName
>[i], totalHours[i]))

Slicing the row tuples into new column value sequences is, happily, no 
faster than making dictionaries using the description tuple. Test script is 
below.

# script start
def get_description():
     return ('ONE', 'TWO', 'THREE', 'FOUR', 'FIVE')

def get_row():
     return (1,2,3,4,5)

def rows_as_dicts(rows, description):
     if not rows: return []
     length = len(rows[0])
     r = range(length)
     l = []
     for row in rows:
         d = {}
         for i in r:
             d[description[i]] = row[i]
         l.append(d)
     return l

def rows_as_columns(rows, description):
     if not rows: return []
     length = len(rows[0])
     r = range(length)
     l = []
     for i in r: l.append([])
     for row in rows:
         for i in r:
             l[i].append(row[i])
     return l

def test(funcs, rows=20, reps=1000):
     desc = get_description()
     rowlist = []
     for i in range(rows):
         rowlist.append(get_row())

     from time import time
     for func in funcs:
         n = func.__name__
         t = time()
         for i in range(reps):
             func(rowlist,desc)
         t = time() - t
         print "%s on %d rows: %s reps in %.04f s (%.05f s each)" % \
               (n, rows, reps, t, t/reps)

if __name__ == '__main__':
     for rowamt in (10,20,50,100):
         test( (rows_as_dicts, rows_as_columns), rowamt )

# output
rows_as_dicts on 10 rows: 1000 reps in 0.4665 s (0.00047 s each)
rows_as_columns on 10 rows: 1000 reps in 0.5636 s (0.00056 s each)
rows_as_dicts on 20 rows: 1000 reps in 0.9083 s (0.00091 s each)
rows_as_columns on 20 rows: 1000 reps in 1.0523 s (0.00105 s each)
rows_as_dicts on 50 rows: 1000 reps in 2.5213 s (0.00252 s each)
rows_as_columns on 50 rows: 1000 reps in 2.5186 s (0.00252 s each)
rows_as_dicts on 100 rows: 1000 reps in 4.5625 s (0.00456 s each)
rows_as_columns on 100 rows: 1000 reps in 5.0504 s (0.00505 s each)


--
Robin Thomas
Engineering
StarMedia Network, Inc.
robin.thomas at starmedia.net





More information about the Python-list mailing list