You are using bindings incorrectly.
There are three different ways to bind variables with cx_Oracle: see here :
1), passing the tuple to the SQL statement with numbered variables :
sql = "select * from sometable where somefield = :1 and otherfield = :2" cur.execute(sql, (aValue, anotherValue))
2) By passing keyword arguments to SQL statements with named variables :
sql = "select * from sometable where somefield = :my_field and otherfield = :anotherOne" cur.execute(sql, myField=aValue, anotherOne=anotherValue)
3) By passing a dictionary to an SQL statement with named variables :
sql = "select * from sometable where somefield = :my_field and otherfield = :anotherOne" cur.execute(sql, {"myField":aValue, "anotherOne":anotherValue})
Notes
Why does your code work?
Let's try to understand what is happening here:
bind= {"var" : "ciao"} sql = "select * from sometable where somefield = :bind and otherfield = :bind" cur.execute(sql,(bind["var"], bind["var"]))
Oracle will understand that it expects a single variable. This is a named variable associated with the name bind . Then you must specify the parameter as a named parameter as follows:
cur.execute(sql, bind="ciao")
Or using a dictionary, for example:
cur.execute(sql, {bind:"ciao"})
However, since cx_Oracle receives the tuple instead, it disappears in the number binding, as if your SQL statement were:
sql = "select * from sometable where somefield = :1 and otherfield = :2"
And as you pass bind['var'] twice, this is just the string "ciao" . This is a mapping of two tuple elements to numbered variables:
cur.execute(sql, ("ciao", "ciao"))
This is random, but the code is very misleading.
Tuple with a single value for binding
Also note that the first option requires a tuple. But if you have a single value for binding, you can use this notation to create a tuple with a single value:
sql = "select * from sometable where somefield = :1" cur.execute(sql, (aValue,))
[EDIT]: Thanks to @ tyler-christian for passing the dict was supported by cx_Oracle.