7. User guide¶
This chapter of the documentation covers the relationship between MimerPy, Mimer SQL and the Mimer SQL C API.
7.1. Connection parameters¶
You can use a dictionary to store connection parameters. And you can omit connection parameters to use default values.
7.1.1. Use a dictionary for connection parameters¶
Python allows you to record a set of named parameters as a dictionary, and use it when calling functions. This allows you to specify the connection parameters centrally and reuse it everywhere a connection needs to be created, like this:
>>> import mimerpy
>>> data_source = {'dsn':'mimerDB', 'user':'mimerUser', 'password':'password'}
# Creating a connection
>>> con = mimerpy.connect(**data_source)
7.1.2. Default value for Mimer SQL database¶
If the parameter dsn is set to an empty string (“”) or None in the
connect()
method, the default database name will be used.
You can specify the default in two ways:
Specify a default database in the sqlhosts file (UNIX) or in the database administrator (Windows).
Set the environment variable MIMER_DATABASE to the default database name.
7.1.3. Default value for user name and password¶
You can create a Mimer SQL IDENT with the same name as the user in your host operating system, and add an OS_USER to that ident. This allows the user to log in to Mimer SQL without specifying a password. This only works on local databases and not on databases accessed over TCP/IP.
For example (on UNIX):
$ whoami
smith
$ bsql
Username: SYSADM
Password:
SQL>create ident smith as user;
SQL>alter ident smith add os_user 'smith';
SQL>exit;
$ python3
>>> import mimerpy
>>> con=mimerpy.connect()
7.2. Query structure¶
There are two ways to structure a query in MimerPy, with or without parameter markers.
7.2.1. Without parameter markers¶
Executing a query without parameter markers is done with the Mimer SQL syntax. If you are looking for help with basic elements of the SQL language and Mimer SQL please visit Mimer SQL documentation. Consider the following example:
>>> con = mimerpy.connect(dsn ="mimerDB", user="mimerUser", password="password")
>>> cur = con.execute("create table testtable(c1 NVARCHAR(128), c2 BINARY(3))")
>>> cur.execute("INSERT INTO ptable VALUES ('bar', x'ABCD01')")
There are some drawbacks using constant literals in SQL expressions:
The SQL database server will compile each new SQL statement into an intermediate executable representation. The database server maintains a cache of statements it has already compiled. If it finds the exact same SQL string, it can reuse an old compiled statement. Use parameter markers to keep the statements identical and reusable.
Creating SQL strings with data constants can create a security risk known as SQL Injection. Use parameter markers to avoid this risk.
7.2.2. With parameter markers¶
Executing queries with parameter markers should be done following a few rules.
According to the PEP 249 parameter markers should be a list of tuples.
Mimer SQL uses the qmark
parameter style. This means parameter markers are of
question mark style, e.g…WHERE name=?. Dictionaries can also be used as parameter markers.
The key(s) in the dictionary have to match up with the corresponding column you want to manipulate.
When executing to a single column, the rules can be bent a bit:
# Creating a table
>>> cur.execute("create table ptable(c1 NVARCHAR(128))")
# Executing a statement using parametermarkers
>>> cur.execute("INSERT INTO ptable VALUES (?)", "bar") # Correct
>>> cur.execute("INSERT INTO ptable VALUES (?)", ("bar")) # Correct
>>> cur.execute("INSERT INTO ptable VALUES (?)", ("bar",)) # Correct
>>> cur.execute("INSERT INTO ptable VALUES (?)", ["bar"]) # Correct
>>> cur.execute("INSERT INTO ptable VALUES (:a)", {'a':bar}) # Correct
When executing to multiple columns, the rules are more strict:
# Creating a table
>>> cur.execute("create table ptable(c1 NVARCHAR(128), c2 INTEGER, c3 FLOAT)")
# Executing a statement using parametermarkers
>>> cur.execute("INSERT INTO ptable VALUES (?,?,?)", ("bar",314,41.23)) # Correct
>>> cur.execute("INSERT INTO ptable VALUES (?,?,?)", ["bar",314,41.23]) # Correct
>>> cur.execute("INSERT INTO ptable VALUES (?,?,?)", "bar",314,41.23) # Incorrect
>>> cur.execute("INSERT INTO ptable VALUES (:a,:b,:c)", {'a':"bar",'b':314,'c':41.23}) # Correct
The same rules apply when using executemany()
. For an example,
see Executemany.
7.3. Transaction control¶
Every time an execute()
is called from a connection or a cursor,
a transaction, if not already open, starts. The transaction is
supposed to be open until a rollback()
or a commit()
is
performed. Unfortunately this is not always true. If a Data Definition
Language(DDL) statement is executed the transaction will implicitly end.
Because of this there are some limitations and a few things to keep in mind while
using the current version MimerPy.
DDL and Data Manipulation Language (DML) statements should (can) not be mixed in the same transaction.
DDL statement are always committed.
In most sequences of DDL and DML mixing, MimerPy will raise a
ProgrammingError
. However not always. MimerPy is coded to
handle mixing of DDL and DML statements, but the current version of
the Mimer SQL C API can not handle it. Because of this, unpredictable
behavior sometimes occur when mixing DDL and DML executes.
The MimerPy user has the responsibility to write code with transaction control in mind. Our recommendation is to always commit before and after a executing a DDL statement. Consider the following example:
>>> cur = conn.cursor()
>>> cur.execute("create table mytable(c1 NVARCHAR(128))")
>>> cur.execute("insert into mytable values ('foo')")
>>> cur.execute("select * from mytable")
>>> conn.commit()
In the current version of the Mimer SQL C API (11.0
) the example
above will not raise an error. However, because DDL statements are
always committed, this example gives a false impression. Consider the
following example:
>>> cur = conn.cursor()
>>> cur.execute("create table mytable(c1 NVARCHAR(128))")
>>> cur.commit()
>>> cur.execute("insert into mytable values ('bar')")
>>> cur.execute("select * from mytable")
>>> conn.commit()
This is what is done in the first example implicitly.
Note
If you wish to bypass this problem, autocommit()
can
be used and none of this applies.
7.3.1. Mimer SQL DML and DDL cheat sheet¶
DML |
DDL |
---|---|
SELECT |
CREATE |
INSERT |
ALTER |
UPDATE |
DROP |
DELETE |