473,406 Members | 2,273 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,406 software developers and data experts.

oracle interface

In searching I find there several different ways to
connect to an Oracle server on MS Windows:

mxODBC - http://www.egenix.com/files/python/mxODBC.html
built on top of the ODBC drivers for a given database

DCOracle2 - http://www.zope.org/Members/matt/dco2/
last update is 1.3 beta released 2 years ago?

cx_oracle - http://www.computronix.com/utilities.shtml

oc8py - http://sourceforge.net/projects/oci8py
Looks dead

Based on my own observations, people generally use the
first two packages. Left to me I would use DCOracle2
because I've used it under unix - I have rather little
MS Windows experience.

There hasn't been much discussion about either option
on c.l.py so I'ld be grateful for feedback.

Andrew
da***@dalkescientific.com

Jul 18 '05 #1
15 2177
We use cx_oracle, for us it has proven to be very stable running on
Solaris.

Jul 18 '05 #2
We're so satisfied with cx_Oracle (HP-UX & Win32) that we
have not even bothered checking the other ones.

Highly recommended.
Jul 18 '05 #3
cx_Oracle rocks

Jul 18 '05 #4
I subscribe to the other posters' opinion: cx_Oracle is what I use on
Windows, Linux and Solaris. Works great cross-platform and across
Oracle versions (I use it with Oracle 9 and 10, haven't tried 8 yet).

Grig

Jul 18 '05 #5
A while back I asked about which Oracle client to use for
MS Windows. Turns out I also needed one for unix so I followed
people's advice and installed cx_Oracle.

I want to execute a query with an "IN" in the WHERE clause
and with the parameter taken from a Python variable. That
is, I wanted something like this to work

id_list = ["AB001", "AB002", "AB003"]

c.execute("""SELECT s.smiles FROM smiles_database s WHERE """
""" s.id IN :id_list""", id_list = id_list)

I couldn't get it to work. It complained

arrays can only be bound to PL/SQL statements

I tried looking at the source code but couldn't figure out
how to do this. In no small part due to my nearly complete
lack of experience with Oracle or for that matter SQL databases.

My solution was to build a new string to executed but it
wasn't pretty and I needed to explain to my client about
SQL injection; wanted to use repr(a_tuple) which was *almost*
correct.

How do I do what I want to do?

Andrew
da***@dalkescientific.com

Jul 19 '05 #6
Something like this might work for you:
ids= ['D102', 'D103', 'D107', 'D108']
in_clause = ', '.join([':id%d' % x for x in xrange(len(ids))])
sql = "select * from tablename where id in (%s)" % in_clause
import cx_Oracle as ora
con = ora.connect('foo/bar@geewhiz')
cur = con.cursor()
cur.execute(sql, ids)


Jul 19 '05 #7
infidel wrote:
Something like this might work for you:
ids= ['D102', 'D103', 'D107', 'D108']
in_clause = ', '.join([':id%d' % x for x in xrange(len(ids))])
sql = "select * from tablename where id in (%s)" % in_clause
import cx_Oracle as ora
con = ora.connect('foo/bar@geewhiz')
cur = con.cursor()
cur.execute(sql, ids)


That's pretty much what I did but it seems inelegant.
I would rather do

ids = ['D102', 'D103', 'D107', 'D108']
.. connect and set up the cursor ..
cursor.execute("select * from tablename where id in :ids", ids)

and if 'ids' is seen to be a list or tuple then it does
the appropriate conversion. (I'm also fine with having
to use ()s in the SQL query, as in "id in (:ids)".)

The lack of a simple way to do this is error prone. I've seen
people do

cursor.execute("select * from tablename where id in (%s)" % repr(ids))

because the repr of a string is close enough that it works
for expected string values. But it opens up the possibility
of SQL injection problems.

Andrew
da***@dalkescientific.com

Jul 19 '05 #8
I think perhaps you are asking for something that the OCI doesn't
provide. At least I'd be rather surprised if it did. I know that the
SQL syntax doesn't provide for such a mechanism.

And really, it all boils down to the list comprehension:

in_clause = ', '.join([':id%d' % x for x in xrange(len(ids))])

.... elegance is certainly subjective, and the above statement isn't the
cleanest ever, but it solves your main problem while avoiding the other
problem you mentiong (sql injection). Seems "elegant enough" to me.

Jul 19 '05 #9
infidel wrote:
I think perhaps you are asking for something that the OCI doesn't
provide.
But it doesn't need to be supported by the OCI.
And really, it all boils down to the list comprehension:

in_clause = ', '.join([':id%d' % x for x in xrange(len(ids))])
And why can't the equivalent to that be supported in the
DB-API interface, so I can pass in a list/tuple and have
it just work?
... elegance is certainly subjective, and the above statement isn't the
cleanest ever, but it solves your main problem while avoiding the other
problem you mentiong (sql injection). Seems "elegant enough" to me.


The problem I mentioned is supporting inexperienced developers
(scientists writing software without local programming support)
who, in my experience, don't know about this pitfall and are
more likely to use a close but wrong solution than this correct
one. repr(ids) is after all much easier to write.

Andrew
da***@dalkescientific.com

Jul 19 '05 #10
Andrew Dalke wrote:
infidel wrote:
I think perhaps you are asking for something that the OCI doesn't
provide.

But it doesn't need to be supported by the OCI.

And really, it all boils down to the list comprehension:

in_clause = ', '.join([':id%d' % x for x in xrange(len(ids))])

And why can't the equivalent to that be supported in the
DB-API interface, so I can pass in a list/tuple and have
it just work?

... elegance is certainly subjective, and the above statement isn't the
cleanest ever, but it solves your main problem while avoiding the other
problem you mentiong (sql injection). Seems "elegant enough" to me.

The problem I mentioned is supporting inexperienced developers
(scientists writing software without local programming support)
who, in my experience, don't know about this pitfall and are
more likely to use a close but wrong solution than this correct
one. repr(ids) is after all much easier to write.

Andrew:

I cannot help but agree that a more sympathetic treatment of the various
sequence types would help tyros and pros alike.

Do you think this is a DB-API 3-ish kind of a thing, or would it layer
over DB-API 2 in a relatively platform-independent manner? I suspect
that some of the code has to be inside the driver (and hence possibly at
least partly written in C) to hook into platform-dependent features like
quoting string literals.

but-you-may-know-better-ly y'rs - steve
--
Steve Holden +1 703 861 4237 +1 800 494 3119
Holden Web LLC http://www.holdenweb.com/
Python Web Programming http://pydish.holdenweb.com/

Jul 19 '05 #11
Steve Holden wrote:
Do you think this is a DB-API 3-ish kind of a thing, or would it layer
over DB-API 2 in a relatively platform-independent manner? ... but-you-may-know-better-ly y'rs - steve


I am a tyro at this. I had to find some tutorials on SQL
to learn there even was an IN clause for the WHERE statement.
All told I've had about 1 hour experience using DB-API 2.

I thought this would be a common enough need that others
would have chimed in by now saying "oh yes, you just need
to XYZ" where XYZ is something cleaner than "make a new
string to execute".

Andrew
da***@dalkescientific.com

Jul 19 '05 #12
Andrew Dalke wrote:
Steve Holden wrote:
Do you think this is a DB-API 3-ish kind of a thing, or would it layer
over DB-API 2 in a relatively platform-independent manner?


...
but-you-may-know-better-ly y'rs - steve

I am a tyro at this. I had to find some tutorials on SQL
to learn there even was an IN clause for the WHERE statement.
All told I've had about 1 hour experience using DB-API 2.

I thought this would be a common enough need that others
would have chimed in by now saying "oh yes, you just need
to XYZ" where XYZ is something cleaner than "make a new
string to execute".

I seem to remember from a good while back that there have *been*
database (perhaps even specifically Oracle) interface modules that
supported a set-style interface in ways similar to your stated
requirements, but alas it's a long time ago and the details are dim.

Given that we now have a Decimal type, allowing us to fulfil an
outstanding DB API wish list item, maybe it's time for DB API 3. Anyone?

regards
Steve
--
Steve Holden +1 703 861 4237 +1 800 494 3119
Holden Web LLC http://www.holdenweb.com/
Python Web Programming http://pydish.holdenweb.com/

Jul 19 '05 #13
Andrew Dalke wrote:
I want to execute a query with an "IN" in the WHERE clause
and with the parameter taken from a Python variable. That
is, I wanted something like this to work

id_list = ["AB001", "AB002", "AB003"]

c.execute("""SELECT s.smiles FROM smiles_database s WHERE """
""" s.id IN :id_list""", id_list = id_list)

I couldn't get it to work. It complained

arrays can only be bound to PL/SQL statements


Possible workarounds:
- use executemany: a few databases allow to execute several sets of
input parameters at once. And even fewer allow this for SELECTs, where
the result is one cursor created from the UNION of a SELECt for each set
of input parameters. Apart from being unlikely to work, this also
requires that *all* input parameters are lists of the same length
(unless the driver is smart enough to expand skalars to lists in this
context)

- specify a maximum number of input parameters 's.id in (:id0, :id1,
....)' and fill missing values with the first value

- create a class for this purpose. Statement are created on the fly, but
with placeholders so you don't run into the SQL Injection problem. As
it's an object, you could cache these generated statements base on the
size of the list

- create a temporary table, insert all the values into that table
(executemany is great for INSERTS) and then join with that table

You could also search comp.language.java.database where this is a
frequent question.

It is unlikely that this can be solved at the driver level. Without
support from the database, the driver would have to manipulate the SQL
statement. And there are few predicates where a list parameter is
useful. Expanding a list always yould lead to very bizarre error
messages. Expanding them only where useful would require a SQL parser.

Daniel
Jul 19 '05 #14
Daniel Dittmar wrote:
Possible workarounds: ... - create a class for this purpose. Statement are created on the fly, but
with placeholders so you don't run into the SQL Injection problem. As
it's an object, you could cache these generated statements base on the
size of the list It is unlikely that this can be solved at the driver level. Without
support from the database, the driver would have to manipulate the SQL
statement.
And there are few predicates where a list parameter is useful. Expanding
a list always yould lead to very bizarre error messages. Expanding them
only where useful would require a SQL parser.


Perhaps I'm missing something fundamental here. I thought the
terms like :arg2 were already being parsed at the Python/driver
interface, to insert the right values from the Python args.

If that was so then it could be solved at the driver level pretty
easily; use the aformentioned "class for this purpose".

It sounds like you're saying that the interface is actually implemented
by passing the execute string and a database-specific dictionary-like
object; the latter created by the DB-API interface.

If so, I now understand the limitation.

Hmmmm.....

Andrew
da***@dalkescientific.com

Jul 19 '05 #15
Andrew Dalke wrote:
It sounds like you're saying that the interface is actually implemented
by passing the execute string and a database-specific dictionary-like
object; the latter created by the DB-API interface.


That's the way it's supposed to work. The program prepares a statement
with placeholders only once and sends it with varying parameters to the
database. That way, the statement has to be parsed by the database only
once and the execution plan can be reused (with Oracle even between
different sessions). It seems as if nothing ticks Oracle DBAs more off
than if you're complaining about poor performance, but you're not using
these prepared statements.

<History>
The :placeholder syntax comes from embedded SQL. You would write the
names of actual program variables there and a precompiler would generate
the code to 'bind' the program variables to SQL parameters. Embedded SQL
has fallen out of favour and new APIs (ODBC, JDBC) use the question mark
as the placeholder. The principle remains the same for many databases:
the SQL string is sent unchanged to the database. Additionally, a list
of actual values is sent for each execution.
</History>

Daniel
Jul 19 '05 #16

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: madunix | last post by:
i want to implememt private area(authorized users)in the internet main page. Our Backend Database Server running Oracle 9i on AIX I am looking for a solution to pull up live data form Backend...
63
by: Nick Palmer | last post by:
Hi all, Is there a DB2 equivilant to Oracle's DB Link functionality ? I have two DB2 databases and I need to get access to the tables in one from the other. In Oracle I would just create a DB...
2
by: Vinod Sadanandan | last post by:
All, Below listed are the new features in Oracle 11g ,please join me in this discussion to generate a testcase and analyze each of the listed features . Precompilers:...
23
by: Gloops | last post by:
Hello everybody, Is anyone able to give me some indications about how to develop an Access interface for an Oracle database ? I dispose of Access 2003 (11.6566.8107) SP2, Oracle 9i 9.2.0.1.0...
4
by: maxpirate | last post by:
application is built on an MS Access database utilizing the GUI facilities of MS Access. Copies of this application are used stand alone in 4 different geographical locations.The users in these...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.