[DB-SIG] Could someone please write a Python DB Tutorial?

Dave Cole djc@object-craft.com.au
24 Nov 2000 10:04:39 +1100


>>>>> "mal" == M -A Lemburg <mal@lemburg.com> writes:

mal> BTW, I'd suggest asking in a forum like this before taking off
mal> into an uncertain direction. The subscribers on this list do have
mal> a lot of experience and may well be able to point you to a
mal> possible solution.

mal> For the Linux -> MS SQL access I would have pointed you to the
mal> OpenLink/Merant ODBC driver kits which should allow you to
mal> connect from Linux to NT. Another possibility would have been to
mal> try to use a Sybase ODBC driver for Linux -- MS SQL Server's wire
mal> protocol is said to be compatible with Sybase's.

They are extremely compatible.  I have been slowly developing a DB API
2.0 Sybase module.  The compliance is pretty good, but still needs
more work.

The biggest area of non conformance is that you can only use SELECT
statements in the Cursor.execute() method.  INSERT, UPDATE, DELETE,
... can only be used in the Connect.execute() method.  After
implementing cursors, I discovered that I was using the wrong set of
Sybase API's.  At some time in the not-to-distant future, I am going
to fix this.

The other area of non-conformance is DATETIME values.  I still have to
integrate mxDateTime...

Anyway, I have actually used it on Linux to talk to an MS SQL database
with good results.  The cursor functionality does not work, but you
can simply use the Connect.execute() method.  I even wrote a small
MSSQL wrapper class which makes it look like cursors work:

The Connect.execute() method returns multiple result sets, whereas the
Cursor.execute() method only returns a single result set.  This makes
Connect.execute() useful for getting the results of stored procedures
such as sp_help which return multiple result sets.

- Dave

import Sybase

class MSSQLCursor:
    def __init__(self, db):
        self.db = db

    def execute(self, cmd):
        result_set = self.db.execute(cmd)
        if len(result_set) > 0:
            self.rows = result_set[0]
        else:
            self.rows = []
        self.row_num = 0

    def fetchone(self):
        if self.row_num >= len(self.rows):
            return None
        row = self.rows[self.row_num]
        self.row_num = self.row_num + 1
        return row

    def fetchmany(self, num = 1):
        if self.row_num + num > len(self.rows):
            num = len(self.rows) - self.row_num
        if num > 0:
            rows = self.rows[self.row_num: self.row_num + num]
            self.row_num = self.row_num + num
        else:
            return []
        return rows

    def fetchall(self):
        return self.fetchmany(len(self.rows))

    def close(self):
        pass

class MSSQL:
    def __init__(self, server, user, passwd, database = None):
        db = Sybase.connect(server, user, database)
        if database:
            db.execute('use %s' % database)
        self.db = db

    def cursor(self):
        return MSSQLCursor(self.db)

    def execute(self, cmd):
        return self.db.execute(cmd)

db = MSSQL('pissey', 'sa', '')
c = db.cursor()
c.execute('select * from sysobjects where type = "P" order by name')
print string.join(map(lambda x: x[0], c.fetchall()), '\n')

-- 
http://www.object-craft.com.au