BCC32Cを使ってみた

フリーウエア利用2    SQLite

ホーム プログラミング メニュー         次へ
概要

SQLite(エスキューライト)は、C言語で利用できる組み込み用のSQLデータベースエンジンです。SQLiteのHPで以下のように紹介されています。

「C言語のライブラリでできた、小型・高速の組み込み型のSQLデータベースエンジンであり、高信頼性とフルSQL機能を持っている。SQLiteは、すべてのスマホ、PCに実装可能であり、アプリに制約なく組み込める。SQLiteデータベース・ファイルは、プラットフォームに依存せず、過去のデータも読み込み可能で、開発者は将来にわたって使い続けることができる。
SQLiteデータベース・ファイルはシステム間で大容量のファイルの転送に使われる。データのアーカイブ・ファーマットとしても使われ、1テラ以上のSQLiteのデータベースも存在する」

Embarcadero C++ Compiler で利用する場合の手順、プログラムへの組込み方を紹介します。

ソフトの入手方法、ライブラリの作成方法

1)ソフトの入手
ソフトは、SQLitのHP(https://www.sqlite.org/download.html)からダウンロードします。
SQLiteを紹介したサイトがあります(例 https://www.dbonline.jp/sqlite/)ので、具体的な操作は、そちらを参照ください。
2020年4月現在で、バージョンは、Version 3.31.1 (2020-01-27)で、取得すべきファイルは以下になります。

@sqlite-dll-win32-x86-3310100.zip  (32-bit DLL (x86) for SQLite) 
ここに、splite3.dllが含まれています。このDLLから、ライブラリファイル(.Lib)を作成します。64ビット版もあるのですが、C++コンパイラが32ビット版ですので32ビット版を使います。
Asqlite-tools-win32-x86-3310100.zip  
ここには、SQLiteを操作するコマンドライン・ツールである、Sqlite3.exeが含まれます。ファイルの確認、テーブルの確認、データ内容の確認を行うので、必要です。
Bsqlite-autoconf-3310100.tar.gz
こちらは、種々のプログラム・ソースコードがあります、Embarcadero C++ のプログラムを開発を行うにあたって、ヘッダ・ファイル(SQLite3.h)を使います。

必要なファイルを特定のフォルダ(例:C:\borland\program\freeware2 )に保管します。

2)著作権
SQLiteのソースコードは、パブリックドメインで、ヘッダー・ファイルに、以下が書かれています。
  「作者はソースコードの著作権を放棄し、その記載の代わりに祈りを記します。
    あなたが、善を行い、悪を行わないことを
    また、自分自身への許しをみつけ、他人を許すことを
    そして、自由に共有し、自分が得たもの以上を取らないことを祈ります」
有用なソフトの公開を感謝します。更新が都度行われますので、このHPでは、SQLiteのヘッダ・ファイル、dllは、置いていません、作者のサイトから取得お願いします。

3)ライブラリの作成
Embarcadero C++ Compilerのコマンドライン ツールのimplib.exeを使って、上記のSQLite3.dllからライブラリ(sqlite3.lib)を作成します。
実行結果は以下の@です。

@ライブラリ作成


サンプルプログラム 

1)動作確認プログラム(sqlite_01.c)
ヘッダーファイル(SQLite.h)をインクルードし、SQLite.libを組み込んだ実行ファイルを作成します。内容は、SQLITEのバージョン(定数 SQLITE_VERSION)を表示するだけのものです。
ソースプログラムがA、コンパイル結果はB、プログラムの実行結果はCです。
コンパイル方法は、これ以降のサンプルプログラムでは「SQLite_0X」のXをソース・ファイル名に合わせて変更すれば良いので、以下は省略しています。

Aソースファイル

// -------------------------------------------------
// sqlite_01.c  SQLite テストプログラム1
//    ・「sqlite3.h」の include
//    ・「sqlite3.lib」の リンク
//    2020/04/10 Kimio Nakamura
// -------------------------------------------------

#include <stdio.h>
#include "sqlite3.h"


// =========================================================================
//   Name     : int main(void)
//   Usage    : メイン関数
//   Parameter: なし
//   Return   : 
// =========================================================================
int main(void)
{
        fprintf(stdout, "SQLite version = %s\n", SQLITE_VERSION);

        return 0;
}

Bコンパイル結果



C実行結果

   2)SQLiteのデータベース・ファイルの作成

SQLiteのAPIである、sqlite3_open関数を使用して、新規のデータベース・ファイル(ファイル名、batting.db)を作成します。ここでは、サイズが0の空のファイルが作成されます)
ソースプログラムが@、プログラムの実行結果はAです。

  【データベース・ハンドル】 sqlite3 *db
   ・機能 SQLiteデータベースに接続するために使う。 
  【関数名】int sqlite3_open( const char *filename , sqlite3 **db);
      int sqlite3_open_v2( const char *filename , sqlite3 **db , int flags , const char *zVfs );
   ・機能 SQLiteデータベースを作成、オープンする。 
   ・引数  *filename  :ファイル名(UTF-8)
         **db   :SQLite データベースハンドル
        flags :SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE オープン・なければ作成
            SQLITE_OPEN_READONLY
            SQLITE_OPEN_READWRITE   
        *zVfs : 使用する VFS モジュール名( 指定しない場合はNULL)
   ・戻り値  SQLITE_OK  :OK
          その他は現エラー
   ・備考   sqlite3_open_v2()は、オープン・作成のモードを持つ。
          sqlite3_open()は、「SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE」で設定。
  【関数名】int sqlite3_close(sqlite3 *db )
      int sqlite3_close_v2(sqlite3 *db)
   ・機能 SQLiteデータベースをクローズする。 
   ・引数 sqlite3 *db データベースハンドル
   ・戻り値  SQLITE_OK  :0(OK)
          その他は現エラー
   ・備考   


@ソースプログラム(sqlite_02.c)

// -------------------------------------------------
// sqlite_02.c  SQLite テストプログラム2
//    ・ファイル作成
//    2020/04/10 Kimio Nakamura
// -------------------------------------------------

#include <stdio.h>
#include <string.h>
#include "sqlite3.h"

// =========================================================================
//   Name     : int main(void)
//   Usage    : メイン関数
//   Parameter: なし
//   Return   : 
// =========================================================================
int main(void)
{
        sqlite3 *db;            
        char *db_name= "batting.db";
        int rc;                         // 結果
        
   // データベースファイルを新規生成 or オープン
        rc = sqlite3_open(db_name, &db);
        fprintf(stdout, "Open status:[%s] [%s]\n", db_name, sqlite3_errmsg(db));
        return 0;
}


A実行結果


   3)テーブルの作成

作成した、データベース・ファイル(batting.db)にSQL文(create table テーブル名 (テーブル定義))を実行してテーブルを設定します。sqlite3_exec関数の2番目の引数にSQL文を指定して、実行します。
ここでは、自作ソフトの紹介1-2と同様にプロ野球の打撃成績を例にしたテーブルを作成します。
ソースプログラムが@、プログラムの実行結果はAです。保管できる日本語のコードはunicodeとなりますが、元のデータがWindowsのSJISコードで、変換が必要となるので、英語(1バイトコード)の名前とチーム名を使っています。

  【関数名】int sqlite3_exec( sqlite3 *db , const char *sql ,
         int (*callback ) ( void* , int , char** ,char** ), void * , char **errmsg );

   ・機能 SQLiteデータベースにSQL文を実行する。 
   ・引数 sqlite3 *db :データベースハンドル
       *sql  :SQL文
       callback:コールバック関数 、必要なければNULLとする。
       void* :コールバック関数の第1引数に渡す。
       **errmsg :エラーメッセージ
   ・戻り値  SQLITE_OK  :0(OK)、エラーメッセージはNULLとなる。
          その他は現エラー
   ・備考   


@ソースプログラム(sqlite_03.c)

// -------------------------------------------------
// sqlite_03.c  SQLite テストプログラム3
//    ・テーブル作成
//    2020/04/12 Kimio Nakamura
// -------------------------------------------------


//  ===== テーブル  CL_batting_2019 ====
//      順位   no INTEGER
//      選手   name TEXT
//      球団   team TEXT
//      打率   batting_average REAL
//      打数   at_bat INTEGER
//      安打   hit INTEGER
//      本塁打 home_run INTEGER
//      打点   run INTEGER
//      三振   strikeout INTEGER
//      併殺打 double_play INTEGER
//      長打率 extra_base_percentage REAL
//      出塁率 on_base_percentage REAL
//


#include <stdio.h>
#include <string.h>
#include "sqlite3.h"

// =========================================================================
//   Name     : int main(void)
//   Usage    : メイン関数
//   Parameter: なし
//   Return   : 
// =========================================================================
int main(void)
{
        sqlite3 *db;            //
        char *db_name = "batting.db";
        char *table_name = "batting_2019";
        char *table = "no INTEGER,  name TEXT, team TEXT,"  
                batting_average REAL, "
                "at_bat INTEGER, hit INTEGER , home_run INTEGER ," 
                run INTEGER , strikeout INTEGER , double_play INTEGER," 
                extra_base_percentage REAL ,on_base_percentage REAL";

        char *error_message;
        char sql_statement[2000];
        int rc;                         // 結果
        
                        // データベースファイルをオープン
        
        rc = sqlite3_open( db_name , &db);
        fprintf(stdout, "Open/Create status:[%s] [%s]\n", db_name, 
                                                          sqlite3_errmsg(db));

                        // テーブル作成、SQLステートメントを作成

        sprintf(sql_statement, "create table %s(%s)", table_name, table);

              // SQLステートメントを実行
        rc = sqlite3_exec(db, sql_statement, NULL, NULL, &error_message);
        
        if(rc == SQLITE_OK){
                 fprintf(stdout, "Exec(Ceate Table):%s\n", sqlite3_errmsg(db));
        }
        else fprintf(stdout, "ERROR(Ceate Table):%s\n", error_message);
        sqlite3_close(db);                                      // クローズ
        
        return 0;
}
A実行結果



   4)データ登録

データベース・ファイル(batting.db)にSQL文(insert into テーブル名 values(レコード・データ))をsqlite3_exec関数で実行して、データベースに登録します。
ソースプログラムが@で、プログラムの実行結果がAです。正常に登録できたので、エラーメッセージが「null」になっています。


@ソースプログラム(sqlite_04.c)
// -------------------------------------------------
// sqlite_04.c  SQLite テストプログラム4
//    ・データ入力
//    2020/04/17 Kimio Nakamura
// -------------------------------------------------

#include <stdio.h>
#include <string.h>
#include "sqlite3.h"

typedef struct
{
    long    no;                        //    1 順位  
    char    name[30];                  //    2 選手  
    char    team[30];                  //    3 球団  
    double    batting_average;         //    4 打率  
    long    at_bat;                    //    5 打数  
    long    hit;                       //    6 安打  
    long    home_run;                  //    7 本塁打
    long    run;                       //    8 打点  
    long    strikeout;                 //    9 三振  
    long    double_play;               //    10 併殺打
    double    extra_base_percentage;   //    11 長打率
    double    on_base_percentage;      //    12 出塁率
    
}BATTING;

BATTING    batting[50] = {
    {1 ,"Suzuki,Seiya","(C)",0.335 ,499 ,167 ,28 ,87 ,81 ,3 ,0.565 ,0.453},
    {2 ,"Viciedo,Dayan","(D)",0.315 ,534 ,168 ,18 ,93 ,88 ,22 ,0.496 ,0.374},
    {3 ,"Itoi,Yoshio","(T)",0.314 ,382 ,120 ,5 ,42 ,63 ,10 ,0.416 ,0.403},
    {4 ,"Oshima,Yohei","(D)",0.312 ,558 ,174 ,3 ,45 ,78 ,5 ,0.38 ,0.376},
    {5 ,"Sakamoto,Hayato","(G)",0.312 ,555 ,173 ,40 ,94 ,123 ,9 ,0.575 ,0.396},
    {6 ,"Nishikawa,Ryoma","(C)", 0.297 ,535 ,159 ,16 ,64 ,81 ,9 ,0.441 ,0.336},
    {7 ,"Aoki,Norichika","(S)", 0.297 ,489 ,145 ,16 ,58 ,72 ,13 ,0.442 ,0.385},
    {8 ,"Takahashi,Shuhei","(D)", 0.293 ,430 ,126 ,7 ,59 ,70 ,10 ,0.43 ,0.345},
    {9 ,"Maru,Yoshihiro","(G)",0.292 ,535 ,156 ,27 ,89 ,125 ,15 ,0.495 ,0.388},
    {10,"Abe,Toshiki","(D)",0.291 ,447 ,130 ,7 ,59 ,82 ,9 ,0.405 ,0.337},
    {11,"Kamei,Yoshiyuki","(G)",0.284 ,450 ,128 ,13 ,55 ,91 ,6 ,0.44 ,0.346},
    {12,"Miyazaki,Toshiro","(DB)",0.284 ,433 ,123 ,15 ,49 ,35 ,13 ,0.443 ,0.334},
    {13,"Balentien,Wladimir","(S)",0.28 ,410 ,115 ,33 ,93 ,117 ,11 ,0.554 ,0.363},
    {14,"Kamizato,Kazuki","(DB)",0.279 ,427 ,119 ,6 ,35 ,121 ,7 ,0.407 ,0.323},
    {15,"Aizawa,Tsubasa","(C)",0.277 ,376 ,104 ,12 ,63 ,81 ,6 ,0.439 ,0.387},
    {16,"Takai,Yuhei","(S)",0.273 ,447 ,122 ,12 ,56 ,71 ,4 ,0.396 ,0.327},
    {17,"Tsutsugo,Yoshitomo","(DB)",0.272 ,464 ,126 ,29 ,79 ,141 ,5 ,0.511 ,0.388},
    {18,"Chikamoto,Koji","(T)",0.271 ,586 ,159 ,9 ,42 ,110 ,2 ,0.375 ,0.313},
    {19,"Yamada,Tetsuto","(S)",0.271 ,520 ,141 ,35 ,98 ,121 ,14 ,0.56 ,0.401},
    {20,"Soto,Neftali","(DB)",0.269 ,516 ,139 ,43 ,108 ,98 ,14 ,0.554 ,0.348},
    {21,"Nakamura,Yuhei","(S)",0.269 ,372 ,100 ,5 ,36 ,64 ,11 ,0.384 ,0.373},
    {22,"Itohara,Kento","(T)",0.267 ,491 ,131 ,2 ,45 ,70 ,7 ,0.336 ,0.353},
    {23,"Umeno,Ryutaro","(T)",0.266 ,433 ,115 ,9 ,59 ,83 ,16 ,0.393 ,0.326},
    {24,"Okamoto,Kazuma","(G)",0.265 ,555 ,147 ,31 ,94 ,132 ,15 ,0.485 ,0.343},
    {25,"Kikuchi,Ryosuke","(C)",0.261 ,547 ,143 ,13 ,48 ,102 ,5 ,0.406 ,0.313},
    {26,"Oyama,Yusuke","(T)",0.258 ,538 ,139 ,14 ,76 ,98 ,12 ,0.401 ,0.312},
    {27,"Kyoda,Yota","(D)",0.249 ,507 ,126 ,3 ,40 ,91 ,10 ,0.314 ,0.302},
    {28,"Lopez,Jose","(DB)",0.241 ,551 ,133 ,31 ,84 ,107 ,18 ,0.461 ,0.295},
    {29,"Maeda,Yamato","(DB)",0.237 ,438 ,104 ,0 ,37 ,75 ,7 ,0.285 ,0.3},
    {30,"Murakami,Munetaka","(S)",0.231 ,511 ,118 ,36 ,96 ,184 ,9 ,0.481 ,0.332}};

// =========================================================================
//   Name     : int main(void)
//   Usage    : メイン関数
//   Parameter: なし
//   Return   : 
// =========================================================================
int main(void)
{
    sqlite3 *db;        //
    char *db_name = "batting.db";
    char *table_name = "batting_2019";

    char *error_message;
    char sql_statement[2000];

    int rc;                // 結果

    int i;

            // データベースファイルをオープン
    
    rc = sqlite3_open( db_name , &db);
    fprintf(stdout, "Open/Create status:[%s] [%s]\n", db_name, sqlite3_errmsg(db));

            // データ入力
    for(i=0 ; i<30; i++){
        sprintf(sql_statement,"insert into %s values(%ld,'%s','%s',%lf,%ld,%ld,
                                                            %ld,%ld,%ld,%ld,%lf,%lf)",
                table_name, 
                batting[i].no , batting[i].name , batting[i].
                team,batting[i].batting_average , batting[i].at_bat, batting[i].hit ,
                batting[i].home_run , batting[i].run, batting[i].strikeout , 
                batting[i].double_play ,batting[i].extra_base_percentage , 
                batting[i].on_base_percentage);  

        rc =sqlite3_exec(db, sql_statement, 0, 0, &error_message);
        fprintf(stdout ,"%d %d %s\n",i , rc , error_message);
    }

    return 0;
}

A実行結果


   4)データ表示

データベース・ファイル(batting.db)からSQL文(select * from テーブル名)をsqlite3_exec関数で実行して、データベースを検索します。結果を得るための3番目の引数にcallback関数を登録します。callback関数には、取得したデータを表示する処理を入れておきます。

ソースプログラムが@、プログラムの実行結果はAです。実行結果から分かるように、1件検索したらcallback関数が呼ばれます。

 【関数名】int callback (void*  , int argc , char **argv , char **col );
   ・機能 sqlite3_execの中で呼び出される関数を設定できる。 
   ・引数  void*   :sqlite3_execの4番目の引数が渡される。
         argc   :件数
         **argv :検索された内容(argc 分)
         **col  :列名(argc 分)
   ・戻り値  0(OK)
          0以外の場合は、中断し、sqlite3_execでSQLITE_ABORT(4)が返す。
   ・備考  



Bは、SQLiteコマンドライン・ツール(sqlite3.exe)を使って、これまで実行した内容が、データベースに正しく反映されているか調べます。「.open」コマンド、「.databases」コマンドでデータベース・ファイルのオープン、ファイル名を調べます。「.schema」コマンドで、テーブル内容を表示します。SQL文(select * from batting_2019;)で、内容を表示します。


@ソース・プログラム(sqlite_05.c)
// -------------------------------------------------
// sqlite_05.c  SQLite テストプログラム5
//    ・データ表示
//
//    2020/04/19 Kimio Nakamura
// -------------------------------------------------

#include <stdio.h>
#include <string.h>
#include "sqlite3.h"

// =========================================================================
//   Name     : int callback(void *NotUsed, int argc, char *argv[], char *ColName[])
//   Usage    : 抽出結果が返るコールバック関数
//   Parameter: 1番目:未使用、2番目:argc データ数、3番目 *argv[] データ
//       4番目:*ColName[] カラム名
//   Return   : 
// =========================================================================

int callback(void *NotUsed, int argc, char *argv[], char *ColName[]){
        int i;
        for(i = 0; i < argc; i++){
                fprintf(stdout , "%-25s = %s\n", ColName[i], argv[i]);
        }
        fprintf(stdout , "\n");
        return 0;
}

// =========================================================================
//   Name     : int main(void)
//   Usage    : メイン関数
//   Parameter: なし
//   Return   : 
// =========================================================================
int main(void)
{
        sqlite3 *db;
        char *db_name = "batting.db";
        char *table_name = "batting_2019";

        char sql_statement[2000];
        char *error_message;
        int rc;                         // 結果

                        // データベースファイルをオープン
        
        rc = sqlite3_open( db_name , &db);
        fprintf(stdout, "Open status:[%s] [%s]\n", db_name, sqlite3_errmsg(db));

                        // テーブルの全項目を列挙

        sprintf( sql_statement, "select * from %s", table_name);
        rc = sqlite3_exec(db, sql_statement, callback, 0, &error_message);
        fprintf(stdout, "select status:[%d] [%s]\n", rc, error_message);

        return 0;
}
A実行結果


BSQLite.exeでの確認


   5)データ表示2

5)のデータ表示と同様の内容ですが、sqlite3_exec関数の4番の引数に、検索データを保管する構造体のアドレスを引き渡します。このアドレスは、callback関数の1番目の引数に引き渡されます。
callback関数の中で、引き渡された構造体アドレスを使って、検索した情報を保管する。
@がソースプログラム、プログラムの実行結果はAです。

@ソース・プログラム(sqlite_13.c)

// -------------------------------------------------
// sqlite_13.c  SQLite テストプログラム
//    ・データ読み込み・・・行単位、callbackを使う
//     sql3_exec 関数から callback関数に渡されて
//     きたアドレスを使う。
//    2020/05/05 Kimio Nakamura
// -------------------------------------------------

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "sqlite3.h"

#define MAX_REC 100     // batting 構造体の最大数

typedef struct
{
    long    no;                        //    1 順位  
    char    name[30];                //    2 選手  
    char    team[30];                //    3 球団  
    double    batting_average;        //    4 打率  
    long    at_bat;                 //    5 打数  
    long    hit;                     //    6 安打  
    long    home_run;                //    7 本塁打
    long    run;                    //    8 打点  
    long    strikeout;                //    9 三振  
    long    double_play;             //    10 併殺打
    double    extra_base_percentage;    //    11 長打率
    double    on_base_percentage;        //    12 出塁率
    
}BATTING;

BATTING batting[MAX_REC];

int batting_table_num = 12;            // batting テーブルの項目数
int batting_rec_num ;                // batting 検索件数

//------------------------プロトタイプ宣言-----------------

// =========================================================================
//   Name     : int callback(void * , int argc, char *argv[], char *ColName[])
//   Usage    : 抽出結果が返るコールバック関数
//   Parameter: 1番目:void *、2番目:argc データ数、3番目 *argv[] データ
//       4番目:*ColName[] カラム名
//   Return   :  0  OK
// =========================================================================
int callback_select3( void *tb, int argc, char *argv[], char *ColName[]){

    int i ;
    BATTING *ptb[MAX_REC];
    
    for (i= 0; i<MAX_REC ; i++){
        ptb[i] = tb + i * sizeof(BATTING);
    }

    for(i = 0; i < argc; i++){

        if( strcmp( ColName[i], "no") == 0  )
            ptb[batting_rec_num]->no = atol(argv[i]); 
        else if    ( strcmp( ColName[i], "name") == 0 ) 
            strcpy(ptb[batting_rec_num]->name , argv[i]);
        else if    ( strcmp( ColName[i], "team") == 0 ) 
            strcpy(ptb[batting_rec_num]->team , argv[i]);
        else if    ( strcmp( ColName[i], "batting_average") == 0 ) 
            ptb[batting_rec_num]->batting_average = atof( argv[i] );
        else if    ( strcmp( ColName[i], "at_bat") == 0 ) 
            ptb[batting_rec_num]->at_bat = atol( argv[i] );
        else if    ( strcmp( ColName[i], "hit") == 0 ) 
            ptb[batting_rec_num]->hit = atol( argv[i] );
        else if    ( strcmp( ColName[i], "home_run") == 0 ) 
            ptb[batting_rec_num]->home_run = atol( argv[i] );
        else if    ( strcmp( ColName[i], "run") == 0 ) 
            ptb[batting_rec_num]->run = atol( argv[i] );
        else if    ( strcmp( ColName[i], "strikeout") == 0 ) 
            ptb[batting_rec_num]->strikeout = atol( argv[i] );
        else if    ( strcmp( ColName[i], "double_play" ) == 0 ) 
            ptb[batting_rec_num]->double_play = atol( argv[i] );
        else if    ( strcmp( ColName[i], "extra_base_percentage") == 0 ) 
            ptb[batting_rec_num]->extra_base_percentage = atof( argv[i] );
        else if    ( strcmp( ColName[i], "on_base_percentage") == 0 ) 
            ptb[batting_rec_num]->on_base_percentage = atof( argv[i] );
    }

    batting_rec_num++;    
    return 0;
}

// =========================================================================
//   Name     : int main(void)
//   Usage    : メイン関数
//   Parameter: なし
//   Return   : 
// =========================================================================
int main(void)
{
    sqlite3 *db;
    char *db_name = "batting.db";
    char *table_name = "batting_2019";

    char sql_statement[2000];
    char *error_message;
    int rc;                // 結果
    int i=1;

            // データベースファイルをオープン
    
    rc = sqlite3_open( db_name , &db);
    fprintf(stdout, "Open/Create status:[%s] [%s]\n", 
                            db_name, sqlite3_errmsg(db));

            // テーブルの全項目を列挙

    batting_rec_num =0;

    sprintf( sql_statement, "select * from %s", table_name);

    rc = sqlite3_exec(db, sql_statement, callback_select3 , 
                                    &batting[0] , &error_message);

    fprintf(stdout, "select status:[%d] [%s]\n", rc, error_message);

    for (i=0; i < batting_rec_num ; i++){
        fprintf(stdout,"%2d %2ld %20s %5s %1.3lf %3ld %3ld %3ld 
                                    %3ld %3ld %3ld %1.3lf %1.3lf\n",
            i, 
            batting[i].no , batting[i].name , batting[i].team,
            batting[i].batting_average , 
            batting[i].at_bat,batting[i].hit , batting[i].home_run , 
            batting[i].run, 
            batting[i].strikeout , batting[i].double_play ,
            batting[i].extra_base_percentage , 
            batting[i].on_base_percentage);  
    }

    rc = sqlite3_close( db );

    return 0;
}


A実行結果


   6)データ登録、表示・・UTF8

SQLiteのデータタイプは、INTEGER(整数)、REAL(実数)、TEXT(文字型)、BLOB(入力したまま)です。TEXT型はUNICODE(UTF-16、UTF-8)となり、Windowsで使われるSJISは、UTF8に変換して使います。変換にはNKF(Network KANJI Filter)を使います。NKFは「フリーウェアの利用3、NKF」を参照ください。

SQLiteデータベース(batting_utf8.db)を作成、テーブルをbatting_utf8_2019で作成し、データの登録、読み込んで表示するまでを行います。
@が、ソースプログラム、Aが、プログラムの実行結果です。

@ソースプログラム(sqlite_08.c)

// -------------------------------------------------
// sqlite_08.c  SQLite テストプログラム
//    ・データ入力・・・SJIS->UTF8
//    2022/02/05 Kimio Nakamura
// -------------------------------------------------

#include <stdio.h>
#include <string.h>
#include "sqlite3.h"
#include "nkf32.h"

typedef struct
{
    long    no;                        //    1 順位  
    char    name[30];                //    2 選手  
    char    team[30];                //    3 球団  
    double    batting_average;        //    4 打率  
    long    at_bat;                 //    5 打数  
    long    hit;                     //    6 安打  
    long    home_run;                //    7 本塁打
    long    run;                    //    8 打点  
    long    strikeout;                //    9 三振  
    long    double_play;             //    10 併殺打
    double    extra_base_percentage;    //    11 長打率
    double    on_base_percentage;        //    12 出塁率
    
}BATTING;

BATTING    batting[50] = {
 {1 , "鈴木 誠也" ,"(広)" , 0.335 , 499 , 167 , 28 , 87 , 81 , 3 , 0.565 , 0.453},
 {2 , "ビシエド" , "(中)" , 0.315 , 534 , 168 , 18 , 93 , 88 , 22 , 0.496 , 0.374},
 {3 , "糸井 嘉男" , "(神)" , 0.314 , 382 , 120 , 5 , 42 , 63 , 10 , 0.416 , 0.403},
 {4 , "大島 洋平" , "(中)" , 0.312 , 558 , 174 , 3 , 45 , 78 , 5 , 0.38 , 0.376},
 {5 , "坂本 勇人" , "(巨)" , 0.312 , 555 , 173 , 40 , 94 , 123 , 9 , 0.575 , 0.396},
 {6 , "西川 龍馬" , "(広)" , 0.297 , 535 , 159 , 16 , 64 , 81 , 9 , 0.441 , 0.336},
 {7 , "青木 宣親" , "(ヤ)" , 0.297 , 489 , 145 , 16 , 58 , 72 , 13 , 0.442 , 0.385},
 {8 , "高橋 周平" , "(中)" , 0.293 , 430 , 126 , 7 , 59 , 70 , 10 , 0.43 , 0.345},
 {9 , "丸 佳浩" , "(巨)" , 0.292 , 535 , 156 , 27 , 89 , 125 , 15 , 0.495 , 0.388},
 {10 , "阿部 寿樹" , "(中)" , 0.291 , 447 , 130 , 7 , 59 , 82 , 9 , 0.405 , 0.337},
 {11 , "亀井 善行" , "(巨)" , 0.284 , 450 , 128 , 13 , 55 , 91 , 6 , 0.44 , 0.346},
 {12 , "宮ア 敏郎" , "(デ)" , 0.284 , 433 , 123 , 15 , 49 , 35 , 13 , 0.443 , 0.334},
 {13 , "バレンティン" , "(ヤ)" , 0.28 , 410 , 115 , 33 , 93 , 117 , 11 , 0.554 , 0.363},
 {14 , "神里 和毅" , "(デ)" , 0.279 , 427 , 119 , 6 , 35 , 121 , 7 , 0.407 , 0.323},
 {15 , "會澤 翼" , "(広)" , 0.277 , 376 , 104 , 12 , 63 , 81 , 6 , 0.439 , 0.387},
 {16 , "雄平" , "(ヤ) ", 0.273 , 447 , 122 , 12 , 56 , 71 , 4 , 0.396 , 0.327},
 {17 , "筒香 嘉智" , "(デ)" , 0.272 , 464 , 126 , 29 , 79 , 141 , 5 , 0.511 , 0.388},
 {18 , "近本 光司" , "(神)", 0.271 , 586 , 159 , 9 , 42 , 110 , 2 , 0.375 , 0.313},
 {19 , "山田 哲人" , "(ヤ)" , 0.271 , 520 , 141 , 35 , 98 , 121 , 14 , 0.56 , 0.401},
 {20 , "ソト" , "(デ)" , 0.269 , 516 , 139 , 43 , 108 , 98 , 14 , 0.554 , 0.348},
 {21 , "中村 悠平" , "(ヤ)" , 0.269 , 372 , 100 , 5 , 36 , 64 , 11 , 0.384 , 0.373},
 {22 , "糸原 健斗" , "(神)" , 0.267 , 491 , 131 , 2 , 45 , 70 , 7 , 0.336 , 0.353},
 {23 , "梅野 隆太郎" , "(神)" , 0.266 , 433 , 115 , 9 , 59 , 83 , 16 , 0.393 , 0.326},
 {24 , "岡本 和真" , "(巨)" , 0.265 , 555 , 147 , 31 , 94 , 132 , 15 , 0.485 , 0.343},
 {25 , "菊池 涼介" , "(広)" , 0.261 , 547 , 143 , 13 , 48 , 102 , 5 , 0.406 , 0.313},
 {26 , "大山 悠輔" , "(神)" , 0.258 , 538 , 139 , 14 , 76 , 98 , 12 , 0.401 , 0.312},
 {27 , "京田 陽太" , "(中)" , 0.249 , 507 , 126 , 3 , 40 , 91 , 10 , 0.314 , 0.302},
 {28 , "ロペス" , "(デ)" , 0.241 , 551 , 133 , 31 , 84 , 107 , 18 , 0.461 , 0.295},
 {29 , "大和" , "(デ)" , 0.237 , 438 , 104 , 0 , 37 , 75 , 7 , 0.285 , 0.3},
 {30 , "村上 宗隆" , "(ヤ)" , 0.231 , 511 , 118 , 36 , 96 , 184 , 9 , 0.481 , 0.332}
};

// =========================================================================
//   Name     : int callback(void *NotUsed, int argc, char *argv[], char *ColName[])
//   Usage    : 抽出結果が返るコールバック関数
//   Parameter: 1番目:未使用、2番目:argc データ数、3番目 *argv[] データ
//       4番目:*ColName[] カラム名
//   Return   : 
// =========================================================================

int callback(void *NotUsed, int argc, char *argv[], char *ColName[]){
    int i;
    
                                // SJIS 変換用
    char sjis_temp[200];

            // NKF(SJIS-UTF-8変換設定)
            
    SetNkfOption("-s");

    
    for(i = 0; i < argc; i++){
        
        if( strcmp( ColName[i] , "name" )==0 || strcmp( ColName[i] , "team" )==0) {

            NkfConvert( sjis_temp , argv[i] );
            fprintf(stdout , "%-25s = %s\n", ColName[i], sjis_temp );
        }
        else fprintf(stdout , "%-25s = %s\n", ColName[i], argv[i]);
    }
    fprintf(stdout , "\n");
    return 0;
}

// =========================================================================
//   Name     : int main(void)
//   Usage    : メイン関数
//   Parameter: なし
//   Return   : 
// =========================================================================
int main(void)
{
    sqlite3 *db;        //
    char *db_name = "batting_utf8.db";
    char *table_name = "batting_utf8_2019";

    char *error_message;
    char sql_statement[2000];

    char *table = "no INTEGER,  name TEXT, team TEXT,  batting_average REAL, "
          "at_bat INTEGER, hit INTEGER , home_run INTEGER , run INTEGER , "
          "strikeout INTEGER , double_play INTEGER, extra_base_percentage REAL ,"
          "on_base_percentage REAL";

    int rc;                // 結果
    int i;

                                // UTF 変換用
    char utf8_name[200];
    char utf8_team[200];


            // データベースファイルをオープン
    
    rc = sqlite3_open( db_name , &db);
    fprintf(stdout, "Open/Create status:[%s] [%s]\n", db_name, sqlite3_errmsg(db));

    sprintf(sql_statement, "create table %s(%s)", table_name, table);

    // SQLステートメントを実行
    rc = sqlite3_exec(db, sql_statement, NULL, NULL, &error_message);
    
    if(rc == SQLITE_OK) fprintf(stdout, "Exec(Ceate Table):%s\n", sqlite3_errmsg(db));
    else fprintf(stdout, "ERROR(Ceate Table):%s\n", error_message);

            // NKF(SJIS-UTF-8変換設定)
            
    SetNkfOption("-w");

            // データ入力
    for(i=0 ; i<30; i++){

        NkfConvert( utf8_name , batting[i].name);
        NkfConvert( utf8_team , batting[i].team);
        
        sprintf(sql_statement,"insert into %s values(%ld,'%s','%s',%lf,%ld,%ld,
                                                       %ld,%ld,%ld,%ld,%lf,%lf)",
                table_name, 
                batting[i].no , utf8_name , utf8_team , 
                batting[i].batting_average , batting[i].at_bat,
                batting[i].hit , batting[i].home_run , batting[i].run, 
                batting[i].strikeout , batting[i].double_play ,
                batting[i].extra_base_percentage , batting[i].on_base_percentage);  
        rc =sqlite3_exec(db, sql_statement, 0, 0, &error_message);
        fprintf(stdout ,"%d %d %s\n",i , rc , error_message);
    }

            // テーブルの全項目を列挙・表示

    sprintf( sql_statement, "select * from %s", table_name);
    rc = sqlite3_exec(db, sql_statement, callback, 0, &error_message);
    fprintf(stdout, "select status:[%d] [%s]\n", rc, error_message);

    rc = sqlite3_close( db );

    return 0;
}


A実行結果(部分)



SQLiteについては、次に続きます。

戻る 次へ