IBM i で Python を使ってみよう!!(3)- SQL でデータベースにアクセス -

今回は、前回の記事で最後に表示させた画面から、SQL を受け取って実行できるようにしてみましょう。

今回も「Sample web application with Python」を参考にしています。


SQL の実行

さっそくプログラムを見てみましょう。システム名やユーザープロフィール、パスワードなどは適宜変更してください。

sample_sql.py

from bottle import request, get, post, static_file, route, run

import ibm_db

port_number=8889

host_location='nodejs'

file_name='sql.html'

db_name = '*LOCAL'
username = 'USRPRF'
password = 'PASSWORD'

 
@route('/sample')

def sample():
    return static_file(file_name, root='/home/python/')  


@route('/query', method='POST')

def query_ibm_db():

    html_result = ""

    # html table styling
    html_result += "<style>table, th, td {border: 1px solid black;border-collapse: collapse;}"
    html_result += "th, td {padding: 5px;text-align: left;width: 200px;}tr:nth-child(even) {background-color: #f3f3f3;}"
    html_result += "tr:nth-child(odd) {background-color:#fff;}th {background-color: #008ABF;color: white}</style>"


    conn = ibm_db.connect(db_name, username, password)

    if conn:

      # statement = request.forms.get('sql')
      statement = request.forms.decode('utf-8').get('sql')
      print ("SQL:", statement)

      # result_set = ibm_db.exec_immediate(conn, statement)
      try:
         result_set = ibm_db.exec_immediate(conn, statement)
      except:
         print ("SQL not completed:" , ibm_db.stmt_errormsg())
      else:
         print ("SQL completed.")

      num_columns = ibm_db.num_fields (result_set)

      html_result += "<table><tr>"

      # create table headers from column names
      for num in range(0, num_columns):
        html_result += "<th>" + ibm_db.field_name(result_set, num) + "</th>"       

      html_result += "</tr>"

      # insert results into table
      while (ibm_db.fetch_row(result_set)):

        html_result += "<tr>" 

        for num in range(0, num_columns):

          result = ibm_db.result(result_set, num)

          html_result += "<td>" + str(result) + "</td>"

        html_result += "</tr>"
      
      html_result += "</table>" 

      ibm_db.close(conn)

      return html_result 
       

    else:

      return "<p>Connection Failed.</p>"


run(host=host_location, port=port_number, debug=True)

↓のように実行します。

SQL を入力して実行してみましょう。

こんなかんじで結果が表示されます。


SQL アクセスの処理の流れ

SQL の受け取り、実行、結果の取得といった処理の流れを見ていきましょう。

DB への接続

Import で指定した ibm_db の connect メソッドで DB2 for i に接続します。

import ibm_db
    conn = ibm_db.connect(db_name, username, password)

SQL の実行

connect が成功したら、HTML ファイルのフォームから SQL コマンドを受け取り、実行します。

    if conn:

      # statement = request.forms.get('sql')
      statement = request.forms.decode('utf-8').get('sql')
      print ("SQL:", statement)

      # result_set = ibm_db.exec_immediate(conn, statement)
      try:
         result_set = ibm_db.exec_immediate(conn, statement)
      except:
         print ("SQL not completed:" , ibm_db.stmt_errormsg())
      else:
         print ("SQL completed.")

# でコメントアウトしているところは「Sample web application with Python」でのオリジナルのコードです。

最初の変更は、get('sql') の実行前に decode('utf-8') を挿入しているところですね。
これをしないと WHERE 句の一部に日本語を使うような場合(LIKE や = など)に対応できません。

二つ目の変更は、try 〜 except 〜 else ブロックを導入し、SQL の実行が失敗した場合にエラーを表示させるようにしたこと、になります。

実行結果の取り出し

結果の行に含まれるカラム数を取得し、

      num_columns = ibm_db.num_fields (result_set)

ヘッダーとなるように各カラム名からなる行を生成します。ここ ↓ を作っているところですね。

      html_result += "<table><tr>"

      # create table headers from column names
      for num in range(0, num_columns):
        html_result += "<th>" + ibm_db.field_name(result_set, num) + "</th>"       

      html_result += "</tr>"

続けて SQL テーブル内の値を一行づつ HTML 上で表として組み立てます。

      while (ibm_db.fetch_row(result_set)):

        html_result += "<tr>" 

        for num in range(0, num_columns):

          result = ibm_db.result(result_set, num)

          html_result += "<td>" + str(result) + "</td>"

        html_result += "</tr>"
      
      html_result += "</table>" 

DB 接続の切断

DB への接続を切断し、結果を返します。

      ibm_db.close(conn)

      return html_result 

この ibm_db と DB2 への SQL アクセスのための API は DB2 ファミリーで共通のものになっています。

各 API の詳細やプログラミング例などについては、DB2 for LUW のマニュアルになりますが「ibm_db を使用した Python でのアプリケーション開発」あたりが参考になるでしょう。

ちなみに、日本語の出力は可能です。CCSID 5026 のデータでも ↓ のようにきちんとデータ変換をしてくれます。ただし、現時点では問題がちょっとあるんですけどね…

[Top Pageに戻る]

Ads by TOK2