Executing “SELECT … WHERE … IN …” using MySQLdb

后端 未结 10 2015
耶瑟儿~
耶瑟儿~ 2020-11-29 21:23

I\'m having a problem executing some SQL from within Python, despite similar SQL working fine from the mysql command-line.

The table looks like this:

10条回答
  •  误落风尘
    2020-11-29 22:13

    Improving on João's and satru's code, I suggest creating a cursor mixin that can be used to build a cursor with an execute that accepts nested iterables and handles them correctly. A better name would be nice, though... For Python3, use str instead of basestring.

    from MySQLdb.cursors import Cursor
    
    class BetterExecuteMixin(object):
        """
        This mixin class provides an implementation of the execute method
        that properly handles sequence arguments for use with IN tests.
        Examples:
        execute('SELECT * FROM foo WHERE id IN (%s) AND type=%s', ([1,2,3], 'bar'))
        # Notice that when the sequence is the only argument, you still need
        # a surrounding tuple:
        execute('SELECT * FROM foo WHERE id IN (%s)', ([1,2,3],))
        """
    
        def execute(self, query, args=None):
            if args is not None:
                try:
                    iter(args)
                except TypeError:
                    args = (args,)
                else:
                    if isinstance(args, basestring):
                        args = (args,)
                real_params = []
                placeholders = []
                for arg in args:
                    # sequences that we treat as a single argument
                    if isinstance(arg, basestring):
                        real_params.append(arg)
                        placeholders.append('%s')
                        continue
                    try:
                        real_params.extend(arg)
                        placeholders.append(','.join(['%s']*len(arg)))
                    except TypeError:
                        real_params.append(arg)
                        placeholders.append('%s')
                args = real_params
                query = query % tuple(placeholders)
            return super(BetterExecuteMixin, self).execute(query, args)
    
    class BetterCursor(BetterExecuteMixin, Cursor):
        pass
    

    This can then be used as follows (and it's still backwards compatible!):

    import MySQLdb
    conn = MySQLdb.connect(user='user', passwd='pass', db='dbname', host='host',
                           cursorclass=BetterCursor)
    cursor = conn.cursor()
    cursor.execute('SELECT * FROM foo WHERE id IN (%s) AND type=%s', ([1,2,3], 'bar'))
    cursor.execute('SELECT * FROM foo WHERE id IN (%s)', ([1,2,3],))
    cursor.execute('SELECT * FROM foo WHERE type IN (%s)', (['bar', 'moo'],))
    cursor.execute('SELECT * FROM foo WHERE type=%s', 'bar')
    cursor.execute('SELECT * FROM foo WHERE type=%s', ('bar',))
    

提交回复
热议问题