- 1.
Your system must be capable of compiling the source code. The C compiler and linker must be installed in order to create the module. On Linux you can check that the compiler is installed by running the following command:
- 2.If pip is not installed, then install it using your distribution’s package installer. Do not be concerned about Python versions of pip as the install will create a link to the proper version of pip for your version of Python:sudo dnf install piporsudo yum install pip
- 3.If you are running on Linux or Unix, the python-devel package must be installed. Use your distribution’s package installer to install the python-devel (or python3-devel) package:sudo dnf install python-develorsudo yum install python-devel
This will install the Db2 package so that it will be available to your Python scripts. You do not need to install the Db2 client software unless you need it for other purposes. The ibm_db module will allow a Python script/program to access Db2 either locally or remotely without any other software packages.
The ibm_db package contains two modules that can be imported into your scripts: the ibm_db module, which is the standard way to access Db2 from Python, and the ibm_db_dbi module, which conforms to the Python DB-API 2.0 standard for accessing database systems generically. In this book, we will concentrate on the ibm_db module because that module is the base module for accessing Db2 and is actually used by the ibm_db_dbi module to perform all the work to access Db2.
The ibm_db module is a C source code–based module. It is open source and can be found at http://github.com/ibmdb/python-ibmdb/. Also, the Python tests for the module are available at the same location as well as the Python source code for the ibm_db_dbi module.
If you get error messages when you try to install the ibm_db package, then one or more of the prerequisites are not installed. If the message claims the Python.h file cannot be found, then you have not installed the python-devel package from the Linux/Unix distribution’s code repository, or it is not installed properly.
Once the ibm_db package is successfully installed, you are ready to write your first Python script to access Db2.
What follows are some examples of using the ibm_db module to retrieve data from the sample database. All these examples prompt you for a username and password. These values are always those that exist on the Db2 server, not on your local machine (unless that is where the Db2 system resides). If the sample database was installed on the server with the default options, then the username will be db2inst1, and the password will be whatever was set by the database administrator.
Your First Python ibm_db Program
This should display the department table, and it should contain 14 records.
Once this executes successfully, you are now ready to write your first Python programs that access the Db2 sample database.
Our first Python program/script is actually very simple. It emulates the SQL select command we used previously to test the sample database. We want a nicely formatted display of the table contents, and we want to perform all the error checking needed to make sure we can track any errors the program may encounter. This will require a rather longer program than a first example usually requires, but it also gives us a chance to describe a number of ibm_db APIs that you will be using in all your Python programs.
Display the department Table
The Python script starts with the usual first line to notify the system that this is a Python script and then specifies the Python interpreter to be executed.
The only thing here that is out of the ordinary is the import of the ibm_db module.
The first function, getColNamesWidths(), obtains the column name and display width needed for each column from the result table. The call to the ibm_db.num_fields() function obtains the number of columns that the result set contains. Once we have that number, we loop over each column and call the ibm_db.field_name() and ibm_db.field_width() to obtain the column name and the column display width. These will be used to add a title to each column and set the column display width. These values are then returned to the caller.
The next function, populateColTitleLines(), creates two lines, which will be eventually printed to the screen. These lines are a column title line and a separator dashed line. It utilizes the values from the previous function getColNamesWidths() to figure out how to format these lines. Once the lines have been created, they are returned to the caller as a Python list.
The next function, populateLines(), creates the lines fetched from the department table and formats each record as a display line using information passed to the function. Each line created is added to a Python list and then returned to the caller. Each result set record is fetched via the ibm_db.fetch_tuple() function and then formatted from the information passed to the function.
The main program code immediately follows the populateLines() function. The first part of the main program code sets some values that will be used later when the program connects to the Db2 database. The driver variable is always the same in all your Python scripts that use the ibm_db module. The host variable is either the IP address or the DNS name of the server that holds the sample database. If the database is local on your machine, then it can also be the IP address 127.0.0.1. The db variable has the name of the database you want to connect to; in our case, this is sample. We leave the uid and pw variables uninitialized so we do not code the userid and password information into the program. The autocommit and connecttype variables are options that we are not using in this script.
The next lines obtain the uid and pw variable information from the user. We then call the ibm_db.connect() function to actually connect to Db2 and the database specified by the previous variables. If this function fails for any reason, the Python script will exit with an error message. This is a deliberate decision so that we do not have a lot of code built into the program to correct information supplied by the user or mistyped into the script.
The next two sections of code are where the real work is performed. The first section sets the SQL statement to be executed. In this case, we want to fetch all information about the department table. We then call ibm_db.exec_immediate() to execute the SQL statement. If the ibm_db.exec_immediate() failed, an error message will be displayed, and the program will exit with an error message. If it succeeds, we proceed to the next section of code.
The next section of code calls the three functions defined in our program to fetch and display the results of the SQL statement. These functions were described previously.
The last major section actually prints the column titles and the fetched data to the standard output.
The last section calls ibm_db.close() to close our session with the Db2 database and exit the script.
Whew! That was a lot of code, but it is important to note that we included all the necessary error checking and produced a nicely formatted report back to our program user. Also, this is code that can be used over and over again in almost any program you write that uses the select statement or as the basis for a much more complicated and bigger program. And that is exactly what we will do in our later examples. Most of the program will be reused without any changes, and only the SQL statement will be changed or code added to that section to support extended functionality.
Output of Listing 8-1
Although there are some small differences between our output and the display from the test Db2 command from the beginning of the chapter, it is essentially the same. We deliberately spaced the columns with two spaces to better separate the columns visually. Records that contain NULL data have a single dash character to indicate the NULL value in the beginning character of the column.
At this point, we should point out that this book has an appendix devoted to documenting the ibm_db APIs. Although this information has been taken from the ibm_db documentation, we have added a few notes that we hope make the documentation clearer and enhance it to make your programs more readable.
Using Parameter Markers
Our next example is slightly more complicated. It uses what are known as parameter markers to allow dynamic substitution of Python variable information into an SQL statement. This means that the values for parameter markers come from outside the SQL statement. In order to make this work, we have to use some different ibm_db API calls to prepare the SQL statement, substitute the variables, and then execute the statement.
The Modified Code
Remember, the code before this section and after it is the same as in Listing 8-1 with the exception of two Python statements, so be careful in recreating this code if you are not using the packaged code from Apress.
The SQL statement is pretty normal except for the last character in the statement. The question mark (?) identifies a parameter marker. This is where we will substitute a Python variable later in the code. An SQL statement can have as many parameter markers as you need and can contain data or even SQL keywords. In our case, it will contain the specific department number we are looking for.
The next line is a call to ibm_db.prepare(). This will parse the SQL statement and make note of any parameter markers. This must be done prior to substituting the data into the SQL statement. We then check the return code from ibm_db.prepare() to make sure it succeeded before we proceed.
The next statement sets the Python variable we will substitute into the SQL statement. Where this value comes from is entirely up to you. It could be an input parameter to the Python program, it could come from a file, or you could even prompt the user for the value. Just make sure you do the proper error checking to the value prior to using it.
The next statement calls ibm_db.bind_param() to bind the Python variable to the SQL statement. The first parameter to the function identifies the prepared statement output from the previous call to ibm_db.prepare(). The second parameter is the Python variable to be substituted (or bound) in the SQL statement. In this case, it is the department number to be used. We need this in case you have coded more than one parameter marker in the SQL statement. You will need a separate call to ibm_db.bind_param() for each parameter marker. The third parameter specifies whether the marker is an input, output, or input/output variable. The fourth parameter specifies the SQL type of variable that is being passed.
The next set of statements surround our call to ibm_db.execute() for error checking purposes. This function actually executes the prepared SQL statement. The code that follows checks to make sure that the execution succeeded.
After executing the SQL statement, the code after is our calls to the three functions and then printing the results of the SQL statement. This code is unchanged from our previous example.
It is highly recommended that you read the documentation for the ibm_db.prepare() function . There are a large number of parameter types to identify the SQL data types that you should become familiar with.
SQL statements with parameter markers are probably the most used statement types in programs. They are highly flexible and require only a little more code to accommodate in your Python code.
Output from Listing 8-3
Our SQL statement only specified the retrieval of two columns, and there is only one department with the designation B01. The report is small because there is only one department with the number specified, but it gets to the point about how parameter markers can be very useful.
More on Parameter Markers
The next example uses multiple parameter markers to create a selection of values that are used to query the project table. Basically, we want to list all the project names that have specified department numbers.
Using Multiple Parameter Values
Remember, the code before this section and after it is the same as in Listing 8-1 with the exception of two Python statements, so be careful in recreating this code if you are not using the packaged code from Apress.
The select statement for this query contains two parameter values. The first marker will be labeled as 1; the second is labeled as 2. Parameter markers are always labeled from left to right in the SQL statement.
Next, we prepare the SQL statement with a call to ibm_db.prepare() just as all SQL statements with parameter markers need to be. If the call returns False, then we produce an error message and exit the Python program.
The assignments to Python variables that will be substituted into the parameter markers are next in the listing. Again, these can come from anywhere. We assign with them values here just to make what is happening as clear as possible.
Now we call ibm_db.bind_param() twice, once for each parameter marker. Once the value is bound to the SQL prepared statement, it remains bound until another call to ibm_cb.bind_param() is made.
Finally, we call ibm_db.execute() to obtain the query result.
Output from Listing 8-5
The report shows that we have three projects that have the specified department numbers we used as parameter markers, two projects for department 'D01' and one for department ‘B01’. This is another good example of how parameter markers can be very useful in your programs. You can store the needed data in a file or feed it as parameters to the Python program and change the report without any modifications to this Python script.
Producing Multiple Reports with Parameter Markers
The Listing 8-7 shows how to create multiple reports with a single SQL statement with parameter markers. As you will see, this is actually easier than it sounds.
Producing Multiple Reports with One SQL Statement
At first glance, this listing looks a little different from our other examples. The main reason is that we have moved the report printing code into the loop. We do this because we need a report printed for each invocation of the ibm_db.execute() function .
Our SQL statement is slightly more complicated because we have added an ORDER BY clause at the end so that the output is ordered. It still has two parameter markers that specify a range of salaries.
Next, we prepare the SQL statement and test the outcome for errors.
The next statement sets up a Python array of lists that specify the range of salaries we want. There are two ranges specified, and each range will be used in separate invocations of the ibm_db.execute() function .
The rest of the code is a loop that takes a list of salary values to query the employee table. The code works just like the previous examples except that the report printing code has been moved inside the loop so that both queries are able to print their report.
One of the things to note in this example is that we did not have to prepare the SQL statement multiple times. This is by design so that the prepared SQL statement can be used multiple times just as our example does. Rebinding new values to the parameter markers and then executing the statement are all that needs to be done to produce possibly different reports.
Multiple Reports from a Single SQL Statement
We have successfully produced two reports on two different salary ranges and ordered the records by the salary field. The only change we made to the report printing code was to add a newline character at the end of the report so the two reports have some spacing between them.
Using Parameter Markers Without Binding Variables
This example is best used when you have a lot of data to load or update into a table. The ibm_db.execute() function has an additional optional parameter that can be used to pass parameter marker values instead of calling the ibm_db.bind_param() function for each parameter marker.
This use of ibm_db.execute() works best when the rows to be inserted/updated come from a file or another external resource. In our example, we use a file that contains rows to be inserted into the employee table. The file is constructed as a comma-separated values (CSV) file with each row of data representing a new row to be added to the employee table.
Parameter Markers Without Binding Variables
The first statements are the standard Python import statements needed for our program.
The next section of code is our standard setup for accessing a Db2 database, prompting the user for a userid and password, and connecting to the Db2 database.
The next section of code is different from our previous examples. We set up an SQL INSERT statement with parameter markers for each column of data we will insert. In this case, that happens to be all the columns in the employee table. Next, we prepare the statement for eventual execution.
The next block of code is where all the work happens. We open the file containing the information to be inserted into the table first. Then we read it in a line at a time. Next, since the file is a CSV construct, we split the line at each comma. The split pieces have data we do not need in each fragment, so we eliminate the leading and trailing spaces and the single quotes. Finally, we change the Python list of column values into a Python tuple.
Now we can call ibm_db.execute() with our tuple of column values as the second parameter in the function call. We then check to make sure that the insert works and then read in the next line.
The last thing we do is to delete the lines we added to the employee table. This will keep the database in its original state.
Last, we close the database connection.
Output from Listing 8-9
What this example shows is that you can eliminate 14 calls to the ibm_db.bind_param() function with a little work inside a loop. It also eliminates the use of 14 different variables to hold the information and replaces them with a simple Python list and a single tuple.
We should add another note here to possibly clear up an item. Tuples in Python are immutable. It means that once they are created, they cannot be modified or extended with additional members. That is why we had to convert the Python list, once it was ready, to a tuple in one call.
Joining Tables
Db2 supports the joining of tables in queries. There are two types of joins – inner and outer joins. Inner joins have been supported since the inception of Db2, but outer joins are a relatively new concept. We will discuss both types in this section.
Inner Joins
Inner joins have two forms in SQL. The first form of an inner join dates back to the beginning of Db2 and is rather straightforward to code. The second form of an inner join is just as easy to code and is much easier to determine exactly what is being joined and how it is being joined.
The Old Form of an Inner Join
The output from this program will display only the employees working in the department known as “SOFTWARE SUPPORT.” There should only be a total of six employees in that department. The two tables are joined in the workdept column in the employee table and the deptno column in the department table. An additional constraint asks only to see rows where the deptname is equal to “SOFTWARE SUPPORT.”
As you can see, this example is pretty straightforward. Problems happen when the SQL statement has many constraints and the joined columns are not easily spotted in the SQL statement. To resolve this issue and to easily support outer joins, a new clause was added to the SQL statement that explicitly specifies the type of join.
The New Form of an Inner Join
The only thing modified in this example is the SQL statement. Otherwise, the program is unchanged. The SQL statement has a new clause – the INNER JOIN clause and the subclause ON. These explicitly state that an inner join is being made on the two tables specified. There is no WHERE clause as the ON clause replaces it in this case.
The output from this program is exactly the same as the previous program. The reason both examples are shown here is that there are still a large number of programs still using the old form of an inner join and it is important to recognize and deal with these programs as needed.
Outer Joins
What makes an outer join different from an inner join is its ability to not only show you result rows similar to the inner join but also rows where the join columns from both tables are set to NULL. Thus, it displays rows that can never be joined together because one of the columns has an invalid value.
This is actually a rarely used feature of Db2, and thus we will not attempt to show an example here. For more information, refer to the IBM Db2 Knowledge Center on the Web.
Inserts, Updates, and Deletes
In this section, we will look at SQL insert, update, and delete statements and how they relate to Python and parameter markers. We actually saw delete statements in the previous section’s example, but here we will discuss all these statements in more detail.
Insert, Update, and Delete Example
The example listing starts out the same as all of our examples, with one exception. In order to update the salary, which internally is a decimal field, we need to import the decimal module. This way we can keep the adjustment consistent with the SQL field.
The first task is to insert a new record into the employee table. We use parameter fields in an INSERT statement. That is what all the question marks are in the SQL statement. We then call ibm_db.prepare() to prepare the statement.
Next, we create the tuple for the data to be inserted. Then, we call ibm_db.execute() to insert the new row into the database.
The next task is to update the record we just inserted. We create the SQL UPDATE statement with a single parameter marker for the new salary and then prepare the statement. The next statement converts the current salary to a decimal field as well as increases it by 10%. The result of this is a new field that is also a decimal field. We then bind the new salary to the UPDATE SQL statement and execute the statement.
Just to make sure the update succeeded and to prove to ourselves that it worked, we fetch the data from the database with a SELECT statement and display the results. The results display the employee number, the old salary, and the new salary.
Last, we delete the new row to get the database back to its original starting state.
This example is a little convoluted, but it is an example of all the SQL data manipulation statements. This example can also be used as a starting point for many of the types of activities you will encounter almost every day.
Output from Listing 8-13
It is important to note that the calculation of the 10% increase is exactly correct and does not suffer from the inaccuracies from a floating-point calculation. By using the decimal package to perform the calculation, we have ensured the correct increase was applied.
Some Other ibm_db APIs
In this section, we will look at some other ibm_db package APIs that you may have occasion to use. These are not data manipulation statements, but instead can provide information about various aspects of the database and the processing environment of your Python program.
It should be noted that this does not cover all the remaining APIs in the ibm_db package. The remaining APIs are rarely used and are sufficiently documented so they can be easily incorporated in your programs.
Some Miscellaneous ibm_db APIs
As always, the program has the same starting code as our other examples. The first test is the ibm_db.active() API. This API determines if the connection passed as a parameter is still active. While not usually important in most programs, it is used in programs that use the ibm_db.pconnect() API.
The next API used is the ibm_db.autocommit(). This API can both get and set the AUTOCOMMIT flag for the specified connection.
The next API is the ibm_db.client_info(). This API returns information about the client side of the connection. It lists the code pages used, the driver names and versions, and the SQL standard conformance.
Next, the ibm_db.column_priviliges() queries tables about the privileges assigned to specific columns. These privileges may or may not exist. The tables in the sample database usually do not have special privileges assigned to them, so the API does not return any data from them.
The ibm_db.columns() API is used to query the metadata that has been assigned to a column in a table. The sample database has no metadata assigned to columns that we have been able to determine.
The last API we test is the ibm_db.commit() API. This API forces a COMMIT to the database at the point it is called. This should work whether the AUTOCOMMIT flag is on or not.
Output from the Listing 8-15 Program
This output from is pretty simple. Mostly, just one line results from the API being tested. The client info API has more data, all of it of interest to the programmer who requires the information.
Creating Database Objects
The ibm_db library can also help you create database objects such as tables, indexes, and tablespaces. It can also remove existing database objects when necessary. These actions are done through the CREATE and DROP SQL statements.
In addition, this section will cover two more ibm_db APIs, the stmt_error and the stmt_errormsg. These APIs are used to report error conditions and explanations. They can be used after the prepare(), exec_immediate(), and callproc() APIs and contain information that will help you to diagnose the problem with your SQL statement.
Creating a Sample Table
There are a few things to note about this example. First, the table is meaningless except as an example. It is not tied to any other table in the sample database. It is just an example of some of the column data types available to the user by Db2.
Second, the try/except block adds some nice exception processing. It looks for a non-zero return code from the exec_immidiate() API, and if not found it executes the except block of code.
Third, the except block has a call to the stmt_errormsg() API, which will print out the error message associated with the error in the SQL statement.
Fourth, there is no formatting code in this example because it does not return a result table, just a simple return code.
The C01 column is an example of an incrementing column. Each time a new row is inserted or altered, the database will generate a value to be placed in this column. This column is also the primary key for the table as defined by the last clause in the SQL statement.
The C02 is a character string that always has 50 characters associated with it. When you assign a character string to this column that is shorter than 50 characters, the system will pad the string on the right with blanks until it is 50 characters long. If you try to add a string longer than 50 characters, it will be truncated to 50 characters.
The C03 column is a variable character string. This type of string is not padded on the right with blanks. Instead, the actual length of the string is recorded. But if the string is longer than 70 characters, it will be truncated to 70 characters.
The C04 column is a fixed decimal number with a length of 15 numeric values with 2 decimal places.
The C05 column is a floating-point field that can hold a total of 21 numeric characters.
The C06 column is a variable graphic field with a maximum of 1,000,000 bytes.
The C07 column is a variable graphic field with a maximum of 200 bytes.
The C08 column is a binary LOB with a length of 1,000,000 bytes.
The C09 column is a field that contains a data value.
The C10 column is a field that contains a time value.
The C11 column is a field that contains a timestamp value. This field contains both a date and a time value concatenated together to form an instance of time and date.
The C12 column is an XML field. This field actually is a pointer to the file system that contains the XML data.
The C13 column is a Boolean field for simple yes/no values.
Removing a Table
This program is very similar to the previous one except that it uses the DROP SQL statement to remove the table we created at the beginning of this section.
Obtaining Attributes of an Existing Table
Obtaining the Column Attributes of an Existing Table
There are a number of attributes available for a column. Some of these will not be applicable depending on the data type defined on the column or through not being defined. The main attribute you will be interested in is the DATA TYPE or the SQL DATA TYPE, which determines the kind of data stored in the column. There are specific attributes that only apply to certain types of data, that is, the SCALE attribute for instance only applies to the DECIMAL data type.
Output of Listing 8-19
Each column along with all attributes is shown in the complete output file. Listing 8-20 is just a small excerpt of the complete listing.
The Listing 8-14 Python program is very useful in a number of circumstances such as discovering if NULLs are allowed in a column, if there is a DEFAULT VALUE specified for a column, the SIZE attribute that can provide a clue as to the maximum size of a column, and many other attributes.
Obtaining Attributes of a Result Set
Unlike obtaining the attributes of an existing Db2 table, a result set is a temporary table that holds the result of a query. The reason we have this API is that a result set may be a joining of two or more tables and some columns may be modified in the join in such a way that their attributes are modified by the join process. Thus, it may be hard to determine the actual attributes on a joined column except thru trial and error.
Obtaining the Attributes of a Result Set
This example is somewhat similar to the Listing 8-19 program except that there are fewer attributes available. This is mostly due to the nature of a result set, which is mostly for display purposes in a Python program.
Output from Listing 8-21
The output here is similar to Listing 8-14. The addition of the DISPLAY SIZE attribute is extremely valuable as this is the number of characters needed to properly display the column data.
ibm_db_dbi and Python
The ibm_db_dbi module is actually a Python script, but it can be imported just like a Python module. The module follows the PEP 249 Python Database API Specification v2.0, and this makes your programs portable across different databases – at least that is the general idea. The specification for this module is somewhat loose, and thus it leaves a lot of room for additions, which may not be portable to other databases. This is the case for ibm_db_dbi.
An ibm_db_dbi Example Python Program
The code in this example is pretty easy to follow. What is really noticeable is the reduced amount of Python code that was needed to produce the same output as Figure 1-1. This is somewhat misleading as the ibm_db_dbi module, which is also Python code, is doing a lot of the work we did for ourselves in Listing 8-1. Thus, about the same amount of Python code is being executed when the module and our program code are taken together.
Using Parameter Markers with ibm_db_dbi
We are just showing the changed statements needed in Listing 8-9 that utilize parameter markers. This changes the program to match the output of Listing 8-3. Note that the parameters are passed on the execute function as a tuple.
Once again, most of the code is the same as in the previous example. This again shows that using the ibm_db_dbi module , we can leverage it to reduce the code in our Python programs. Just be aware that you should try as hard as possible to not use code that cannot be ported.
Where Is the ibm_db Module Going?
In this chapter we have covered the ibm_db module in depth, but where is it going? A careful analysis of the module source code reveals that there are some incompatibilities with the Db2 APIs. The developers acknowledge that these problems should be fixed and are in the process of figuring out what to do. They also acknowledge the documentation for the module is lacking enough examples for many Python developers.
These and other module problems will certainly be fixed in future versions, but currently they do not pose too many problems. The module is certainly usable as is as we have shown in this book. But what can be done to improve things so that Db2 has an increased user base on Windows, Linux, and Unix? Currently, the IBM developers are creating Python modules that allow programs that use a generic database API to use Db2 as the main database by creating an interface from the program’s generic interface to the ibm_db module. This will allow Db2 to store the objects needed by the program.
So far, the developers have developed four such interfaces, which we will discuss in the following.
The ibm_db_dbi Module
The ibm_db_dbi interface has been discussed in the previous section, but it is worth mentioning here. This interface is included when you install the ibm_db module. It is based on the PEP 248 specification. PEP 249 describes a generic interface that should support almost any native database query interface. The ibm_db_dbi interface fully supports this specification.
The previous section has an example of how to use the ibm_db_dbi interface. This interface calls APIs in the ibm_db interface to gain access to a Db2 database. But it is important to note that if your database changes in the future, the only change needed by your Python program is to modify the import statement so that it points to the interface file used by the new database.
By using a common generic database interface, your program becomes more portable and also much easier to maintain. The disadvantage to using a common database interface is that some of the more advanced features of a native database interface are lost to the programmer. So weigh these choices carefully when choosing your program’s interface to a database.
The Django Database Interface
The Django system is a very powerful mechanism for building web-based pages. It has many useful features and is used by a large percentage of the web programmers around the world. Django also has a generic database interface that a database supplier can use to produce a translation to the API the database supports. This is very similar to the way the PEP 248 interface works. Db2 supplies the ibm_db_django module that performs the translations necessary to access Db2 from Django.
Django settings.py File Extract
The generic Django database API is fully supported by the ibm_db_django module, so no special coding is needed in your Python application. However, you may need a Db2 administrator to establish the database on the Db2 server if you do not have permission to do so.
Django by default executes without transactions, that is, in auto-commit mode. This default is generally not what you want in web applications. You should remember to turn on transaction support in Django.
To learn more about Django, you should visit the www.djangoproject.com/ website.
The SQLAlchemy Adapter
SQLAlchemy is an object-relational adapter. It transforms object information in a Python program and maps it to a relational database to allow an object to be saved from one execution of the program to the next. The transform is performed via a set of well-known patterns so that reliability of the stored object is persistent.
The SQLAlchemy toolkit enjoys wide use in the Python universe because it uses well-established rules in the transform process. These tools are well understood and have a long history of use in other object-oriented languages as well.
CLI Configuration File Extract
Once the CLI configuration file has the proper settings, you are ready to start using the SQLAlchemy module in your program to create persistent copies of Python program objects to be stored in Db2.
To learn more about SQLAlchemy, you should visit the www.sqlalchemy.org/ website.
The Alembic Adapter
The Alembic project is a subproject of the SQLAlchemy project. It is a migrations tool that allows the objects stored in an SQLAlchemy relational database to be migrated to another relational database. Whatever the reason may for using a different relational database than what is currently being used by you project, Alembic will allow you to migrate all your data to a new relational database, that is, migrate an SQLite SQLAlchemy database to Db2.
While this tool is not used on a daily basis in most environments, it is available when you need it.
This will install the latest version of the ibm_db_alembic and ibm_db modules on your machine.
To learn more about Alembic, you should visit the https://alembic.sqlalchemy.org/ website.
The Future
The ibm_db module and its associated subprojects have made a really good start in allowing Python access to the Db2 environment. There are a number of possibilities for increasing this coverage, but at the time this book was written, there is one thing holding the new projects back – lack of developers. This is the same problem that prevents many open source projects from becoming all they could be. However, the ibm_db project has a slight advantage in that there is a small dedicated number of developers from IBM that are trying to move the project forward. But they need your help and support. So, if you have the time and inclination, please volunteer for the project.
Summary
In this chapter, we have introduced the ibm_db package and APIs. We have shown all the data manipulation SQL statements as well as many of the miscellaneous APIs. We have also introduced how to use parameter markers and the different ways that Python data can be bound to the statement that uses it.
Hopefully, the information and examples included in this chapter will give you a firm grasp on how you can use and manipulate a Db2 database. You also should be able to make better use of the Appendix information.