#**********************************************************************
# FILENAME :    CallSPFindName.py
#
# DESCRIPTION :
#               This example simulates using parameter arrays with a stored
#               procedure by emulating the parameter arrays using tuples in
#               Python.
#
#               We place the alphabet in a list of values and select records
#               based on them, returning any records that have a 'like' match
#		on the FirstName field in the table. The tuple index value
#               is also returned to indicate which tuple generated the result
#		along with the number of matching records.
#
#		Stored procedures can only be called though the cursor
#               execute() or executemany() methods at this time since
#               CallProc(), the intended method, has yet to be implemented.
#
#		Input parameters are catered for but output parameters and
#		procedure return values are not. Although limited, these can
#		be be emulated via result set generating SELECTs, the output
#		from which can be accessed though nextset(), fetchone() and
#		fetchall() in the program. This is demonstrated by this
#		example.
#
# ODBC USAGE :
#
#               Emulates parameter array by creating a tuple array containing
#               pairs of parameters representing the alphabet to match the
#		FirstName column in the table and an index value to indicate
#		which tuple was used to generate the result.
#
#               Connects to Data Source using Data Source Name
#               Creates cursor on the connection
#               Drops and recreates a procedure 'pyFind_ByName' which takes
#               two parameters, one for each tuple entry.
#               For each tuple,
#                   executes the procedure using cursor.execute()
#                   retrieves the results using cursor.fetchall() for the
#                   record details and cursor.nextset() and 'for rec in cursor'
#                   to retrieve the tuple index which was passed as param 2
#		    and again to retrieve the number of records returned.
#               Closes and deletes cursor and closed connection

import pyodbc

# Call SP with pairs of param values. We could use cursor.executemany() here
# to take the whole tuple list, but this would only give us the results from
# the last param tuple. i.e. the record with FirstName LIKE  = z and index 25.
# We want the results for each tuple and since drivers often emulate parameter
# arrays by executing an SQL statement once for each set of parameter values,
# this is effectively what is done here.
params = [ ('a', 0),\
		   ('b', 1),\
		   ('c', 2),\
		   ('d', 3),\
		   ('e', 4),\
		   ('f', 5),\
		   ('g', 6),\
		   ('h', 7),\
		   ('i', 8),\
		   ('j', 9),\
		   ('k', 10),\
		   ('l', 11),\
		   ('m', 12),\
		   ('n', 13),\
		   ('o', 14),\
		   ('p', 15),\
		   ('q', 16),\
		   ('r', 17),\
		   ('s', 18),\
		   ('t', 19),\
		   ('u', 20),\
		   ('v', 21),\
		   ('w', 22),\
		   ('x', 23),\
		   ('y', 24),\
		   ('z', 25),\
		 ]

# Stored Procedure Create Statement
sqlCreateSP="CREATE PROCEDURE pyFind_ByName \
           (@pFirstName nvarchar(255), @pPersonIX int) AS \
            DECLARE @RecCount INT;\
            SELECT PersonID, FirstName, \
            LastName, Address, City FROM TestTBL1 WHERE FirstName LIKE @pFirstName+'%' \
            ORDER BY PersonID; \
            SELECT @pPersonIX;\
            SELECT @RecCount=count(*) FROM TestTBL1 WHERE FirstName LIKE @pFirstName+'%';\
            SELECT @RecCount;"

# Stored Procedure Drop Statement
sqlDropSP="IF EXISTS (SELECT * FROM sys.objects \
           WHERE type='P' AND name='pyFind_ByName') \
           DROP PROCEDURE pyFind_ByName"

# Stored Procedure Call Statement
sqlExecSP   = "{CALL pyFind_ByName(?, ?)}";

# Connect to datasource
conn=pyodbc.connect('DSN=DATASOURCE', autocommit=True)

# Create cursor associated with connection
cursor=conn.cursor()

print "\nStored Procedure is : pyFind_ByName"

# Drop SP if exists
cursor.execute(sqlDropSP)

# Create SP using Create statement
cursor.execute(sqlCreateSP)

# Call SP with pairs of param values
for id in params:
    try:
        cursor.execute(sqlExecSP, id)
    except pyodbc.Error, err:
        print 'Error !!!!! %s' % err

    recs = cursor.fetchall()            # rows generated by parameter 1
    for rec in recs:
        print "\nPersonID   : ", rec[0]
        print "First Name : ",          # Comma on end stops new line being output
        if rec[1]!=None:                # None indicates empty column
            print rec[1][0:10]          # print string from 0 upto 10
        else:
            print "-"                   # print - for empty column
        print "Last Name  : ",
        if rec[2]!=None:
            print rec[2][0:10]
        else:
            print "-"
        print "Address    : ",
        if rec[3]!=None:
            print rec[3][0:10]
        else:
            print "-"
        print "City       : ",
        if rec[4]!=None:
            print rec[4][0:10]
        else:
            print "-"

    if cursor.nextset()==True:          # value passed IN as as parameter 2
        for rec in cursor:              # passed OUT by SELECT @pPersonIX in
            print "\nSelection was on (@p1) : ", params[rec[0]][0]
            print "Tuple index was  (@p2) : ", rec[0]

    if cursor.nextset()==True:          # additional record count returned by
        for rec in cursor:				# SELECT @RecCount
            print "Records Returned       : ", rec[0]

print ("\n\nComplete.")

# Close and delete cursor
cursor.close()
del cursor

# Close Connection
conn.close()

Further information