BCC32Cを使ってみた

フリーウエア利用2 SQLite その2

ホーム プログラミング メニュー 前へ 次へ
新しい機能

SQLiteでは、SQL文をsqlite3_exec()関数で実行します。一括して処理を行い、個々の結果を扱うために、「callback」関数を介して行うことになります。細かなコントロールが難しいので、3つの関数(sqlite3_prepare()関数、sqlite3_step()関数、sqlite3_finalize()関数)で逐次実行できるようになっています。便利になる分、使う関数が増えます。手順としては、以下のようになります。

  ・sqlite3_stmt stmt    ステートメント・ハンドル宣言
  ・SQL文の設定、外部からの設定ができるようにパラメータ(変数)を埋め込む。      
  ・sqlite3_prepare_v2()    ステートメント・ハンドルに、SQL文を設定する。
  ・sqlite3_bind_*()        SQL文に外部からパラメータ(変数)を代入する。  
  ・sqlite3_step()        SQL文の実行
  ・sqlite3_column_*()     column(列)毎の値の取得を行う。
  ・sqlite3_reset()       ステートメント・ハンドルのクリア
  ・sqlite3_finalize()     ステートメント・ハンドルの破棄

関数、SQL文、パラメータ

  【ステートメント・ハンドル】 sqlite3_stmt* stmt
   ・機能 SQL文の処理と実行のために使う。 
  【SQL文とパラメータ(変数)】 
  SQL文にパラメータ(変数)を埋め込むことができます。
   ・?      他のデータベースエンジンと同様に、変数を複数設定できる。
           (1番目、2番目・・)
   ・?NNN   変数を番号で設定できる。(範囲は1〜最大値)
   ・:AAAA  変数を「:」(コロン)と名前を設定できる。
   ・@AAA  「:AAA」と同様に利用できる。
    例   SELECT * FROM [テーブル名] WHERE no = ? team = ?
         SELECT * FROM [テーブル名] WHERE no = ?1 team = ?2
         SELECT * FROM [テーブル名] WHERE no = :AA team = :BB
  【関数名】int sqlite3_prepare_v2( sqlite3 *db,  const char *zSql, int nByte,
                           sqlite3_stmt **ppStmt, const char **pzTail );
   ・機能 SQL文をコンパイルし、ステートメント・ハンドルに設定する。 
   ・引数 *db     :データベース・ハンドル
        *zSql    :コンパイルするSQL文   
        nByte    :読み込むバイト数、−1でnullまで読みこむ。
        **ppStmt  :ステートメント・ハンドルのアドレス
        **pzTail   :SQL文の読み込んでいない部分のアドレス
   ・戻り値  SQLITE_OK (0)(OK)
          0以外の場合は、エラー
  【関数名】int sqlite3_step( sqlite3_stmt *stmt )
  ・機能 SQL文を1回実行する。 
  ・引数 *dstmt    :ステートメント・ハンドル
  ・戻り値  SQLITE_ROW (100) ・・・select
         SQLITE_DONE (101)・・・insert、update、delete
        以外は、エラー
  【関数名】int sqlite3_bind_int or double( sqlite3_stmt *stmt, 
                           int num , int or doble value ) ;
      int sqlite3_bind_text( sqlite3_stmt *stmt,  int num ,
                            const char *word ,int char_num , void* );

  ・機能 SQL文のパラメータ(変数)に、値(integer、real、text)を設定する。 
  ・引数 *dstmt    :ステートメント・ハンドル
       num      :設定対象のパラメータ(変数)番号   
       volue     :設定する値
       word     :設定する文字列
       char_num  :読み込む文字列、-1で、nullまで読み込む。
       void : SQLITE_TRANSIENT
  ・戻り値  SQLITE_OK (0)(OK)
        0以外の場合は、エラー
  【関数名】int sqlite3_reset( sqlite3_stmt *stmt )
  ・機能 ステートメント・ハンドルをリセットする。
  ・引数 *dstmt    :ステートメント・ハンドル
  ・戻り値  SQLITE_OK (0):直前のsqlite3_step()がSQLITE_ROW(100)または                       SQLITE_DONE (101)
         それ以外はエラー:直前のsqlite3_step()がエラーの場合
  【関数名】int sqlite3_finalize( sqlite3_stmt *stmt )
  ・機能 ステートメント・ハンドルを破棄する。
  ・引数 *dstmt    :ステートメント・ハンドル
  ・戻り値  SQLITE_OK (0):直前の処理がSQLITE_ROW(100)または
                  SQLITE_DONE (101)、SQLITE_OK (0)の場合
         それ以外はエラー:直前の処理がエラーの場合
 【関数名】int sqlite3_column_int( sqlite3_stmt *stmt,  int icol ;
      double sqlite3_column_double( sqlite3_stmt *stmt,   int icol) ;
       const unsigned char sqlite3_column_text( sqlite3_stmt *stmt, int icol );

  ・機能 指定されたcolumn(列)の値(整数、実数)、文字列を取得する。
  ・引数 *dstmt    :ステートメント・ハンドル
        icol    :列番号
  ・戻り値  int , double , char
  【関数名】int sqlite3_bind_parameter_count( sqlite3_stmt *stmt) ;
      int sqlite3_bind_parameter_index( sqlite3_stmt *stmt,
                           const char *par_name ) ;
       const char sqlite3_bind_parameter_name( sqlite3_stmt *stmt, int icol );
   ・機能 パラメータ(変数)を扱うために使う。
   ・引数 *dstmt    :ステートメント・ハンドル
        *col_name  :パラメータ名
        icol       :列番号
   ・戻り値
     sqlite3_bind_parameter_count()    :パラメータ(変数)の数を返す。
     sqlite3_bind_parameter_index()    :設定したパラメータの番号を取得する。
          主に、パラメータを「:AAAA」のように名前で指定した場合に使う。
      sqlite3_bind_parameter_name()   :パラメータ番号を指定して、
                    パラメータ名(例、「:AAAA」)を取得する。
SQLITE、リザルトコード、エラーコード

SQLITE_OK      0 成功

SQLITE_ERROR     1  一般エラー
SQLITE_ABORT     4  コールバック・ルーチンが中止を求める。
SQLITE_BUSY      5  データベース・ファイルがロックされている。
SQLITE_LOCKED    6  テーブルがロックされている。
SQLITE_CANTOPEN  14  データベース・ファイルがオープンできない。
SQLITE_CONSTRAINT 19  制約違反で中断した。
SQLITE_MISMATCH  20 データタイプがあっていない。
SQLITE_MISUSE    21  ライブラリの使い方が正しくない。

SQLITE_ROW     100  sqlite3_step() で次のデータがある。(検索)
SQLITE_DONE    101  sqlite3_step() で操作が完了した。(挿入、更新)


サンプルプログラム

1)挿入、更新、検索
・sqlite3_prepare_v2()関数で、ステートメント・ハンドル(*stmt)にパラメータを含めた「insert」用、「update」用、「select」用のSQL文を紐づけます。パラメータに、sqlite3_bind_*()関数で登録データを設定してデータベース・ファイル(batting_utf8.db)に挿入、更新、検索を行う。
・日本語項目は、SJIS->UTF8変換して登録します。設定には、sqlite3_bind_text文を使います。検索時、「SELECT * FROM batting_utf8_2019 WHERE name = ?2 AND team = ?3」のように使います。。
・ソースプログラムが@、プログラムの実行結果はA(挿入)、B(更新、検索)です。

@ソース・プログラム

// -------------------------------------------------
// sqlite_27.c  SQLite テストプログラム
//    ・prepare,stepを使う
//    ・select , insert , update 処理
//    ・日本語項目はUTF8
//    2022/02/08 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}
};

// --------------- prototype --------------------
    void set_batting_data( sqlite3_stmt * );
    void disp_batting_data( void );

    BATTING batting_data;

// --------------- 共通 -------------------------

    char sql_statement[2000];

    sqlite3_stmt* stmt_select;        // 検索 用 
    sqlite3_stmt* stmt_insert;        // 挿入 用
    sqlite3_stmt* stmt_update;        // 更新 用
    sqlite3_stmt* stmt_disp;        // 表示 用 

// =========================================================================
//   Name     : int main(void)
//   Usage    : メイン関数
//   Parameter: なし
//   Return   : 
// =========================================================================
int main(void)
{

    int i ;
    int rc;                // 結果

    sqlite3 *db;
    char *db_name = "batting_utf8.db";
    char *table_name = "batting_utf8_2019";

    char *error_message;
                                                // データベース定義
    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 ,\
                    PRIMARY KEY(name, team)";

                                                // SQLITE stmt 用の設定

    char *sql_statement_select ="SELECT * FROM batting_utf8_2019 
    WHERE name = ?2 AND team = ?3";
    char *sql_statement_insert = "INSERT INTO batting_utf8_2019 
          VALUES( ?1 , ?2 , ?3 , ?4 , ?5 , ?6 , ?7 , ?8 , ?9 ,?10 , ?11 , ?12 )";
    char *sql_statement_update = "UPDATE batting_utf8_2019 
                       SET at_bat =?5 , hit =?6  WHERE name = ?2 AND team = ?3";
    char *sql_statement_disp   = "SELECT * FROM batting_utf8_2019 ORDER BY no";


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

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

            // データベースファイルを作成

    rc = sqlite3_open_v2( db_name , &db , 
                  SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE , NULL);

            // データベース テーブル作成

    sprintf(sql_statement, "create table %10s(%10s)", table_name, table);
    rc = sqlite3_exec(db, sql_statement, NULL, NULL, &error_message );

            // SQLite statement 設定( 検索 、挿入 、更新 、表示)

    sqlite3_prepare_v2(db, sql_statement_select, -1, &stmt_select, NULL);
    sqlite3_prepare_v2(db, sql_statement_insert, -1, &stmt_insert, NULL);
    sqlite3_prepare_v2(db, sql_statement_update, -1, &stmt_update, NULL);
    sqlite3_prepare_v2(db, sql_statement_disp, -1, &stmt_disp, NULL);

            // 挿入

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

            // NKF(UTF-8変換)

        NkfConvert( utf8_name , batting[i].name);
        NkfConvert( utf8_team , batting[i].team);

        sqlite3_bind_int(stmt_insert, 1, batting[i].no ); 
        sqlite3_bind_text(stmt_insert, 2, utf8_name ,-1,SQLITE_TRANSIENT); 
        sqlite3_bind_text(stmt_insert, 3, utf8_team ,-1,SQLITE_TRANSIENT); 
        sqlite3_bind_double(stmt_insert, 4, batting[i].batting_average ); 
        sqlite3_bind_int(stmt_insert, 5, batting[i].at_bat ); 
        sqlite3_bind_int(stmt_insert, 6, batting[i].hit ); 
        sqlite3_bind_int(stmt_insert, 7, batting[i].home_run ); 
        sqlite3_bind_int(stmt_insert, 8, batting[i].run ); 
        sqlite3_bind_int(stmt_insert, 9, batting[i].strikeout ); 
        sqlite3_bind_int(stmt_insert, 10, batting[i].double_play ); 
        sqlite3_bind_double(stmt_insert, 11, batting[i].extra_base_percentage); 
        sqlite3_bind_double(stmt_insert, 12, batting[i].on_base_percentage); 

        rc = sqlite3_step(stmt_insert);

        if(rc != SQLITE_DONE){
            fprintf(stdout, "INSERT NG:[%d %d]\n", i+1 , rc);
            return 0;
        }
        sqlite3_reset(stmt_insert);
    }
    fprintf(stdout,"順位    選手        球団    打率    打数    安打   
                        本塁打    打点    三振    併殺打    長打率    出塁率\n");  

                // UPDATE  "鈴木 誠也" ,"(広)" があれば、 打数と安打数を0に更新 。 

    NkfConvert( utf8_name , "鈴木 誠也");
    NkfConvert( utf8_team , "(広)");

    sqlite3_bind_text(stmt_select, 2, utf8_name ,-1,SQLITE_TRANSIENT); 
    sqlite3_bind_text(stmt_select, 3, utf8_team ,-1,SQLITE_TRANSIENT); 

    rc = sqlite3_step(stmt_select);

    fprintf(stdout , "== 変更前==\n");
    set_batting_data( stmt_select );
    disp_batting_data();
    fprintf(stdout , "== 変更後==\n");

    if( rc == SQLITE_ROW){

        sqlite3_bind_int(stmt_update, 5, 0 ); 
        sqlite3_bind_int(stmt_update, 6, 0 ); 

        sqlite3_bind_text(stmt_update, 2, utf8_name ,-1,SQLITE_TRANSIENT); 
        sqlite3_bind_text(stmt_update, 3, utf8_team ,-1,SQLITE_TRANSIENT); 

        rc = sqlite3_step(stmt_update);

        if(rc != SQLITE_DONE){
            fprintf(stdout, "UPDATE NG:[%s]\n", sqlite3_errmsg(db));
            return 0;
        }
        sqlite3_reset(stmt_update);

    }
    sqlite3_reset(stmt_select);

                                    //  1件の表示・・・・変更後
    rc = sqlite3_step(stmt_disp);

    if(rc == SQLITE_ROW){
        set_batting_data(stmt_disp);
        disp_batting_data();

    }
    sqlite3_reset(stmt_disp);

    rc = sqlite3_finalize(stmt_select);
    rc = sqlite3_finalize(stmt_insert);
    rc = sqlite3_finalize(stmt_update);
    rc = sqlite3_finalize(stmt_disp);

    rc = sqlite3_close(db);

    return 0;
}

// =========================================================================
//   Name     : void set_batting_data( sqlite3_stmt* )
//   Usage    : 検索データを構造体にセットする。
//   Parameter: なし
//   Return   : なし
// =========================================================================
void set_batting_data( sqlite3_stmt* stmt )
{

    int i = 0;

                                // UTF8 、sjis 変換用
    char utf8_name[200];
    char utf8_team[200];

    char sjis_name[200];
    char sjis_team[200];

    SetNkfOption("-s");


    batting_data.no = sqlite3_column_int(stmt, i++);

    strcpy(utf8_name , (char*) sqlite3_column_text(stmt, i++));
    strcpy(utf8_team , (char*) sqlite3_column_text(stmt, i++));
    
    NkfConvert( sjis_name , utf8_name);
    NkfConvert( sjis_team , utf8_team);

    strcpy(batting_data.name , sjis_name );
    strcpy(batting_data.team , sjis_team );

    batting_data.batting_average = sqlite3_column_double(stmt, i++);
    batting_data.at_bat = sqlite3_column_int(stmt, i++);
    batting_data.hit = sqlite3_column_int(stmt, i++);
    batting_data.home_run = sqlite3_column_int(stmt, i++);
    batting_data.run = sqlite3_column_int(stmt, i++);
    batting_data.strikeout = sqlite3_column_int(stmt, i++);
    batting_data.double_play = sqlite3_column_int(stmt, i++);
    batting_data.extra_base_percentage = sqlite3_column_double(stmt, i++);
    batting_data.on_base_percentage = sqlite3_column_double(stmt, i++);

    return;
}

// =========================================================================
//   Name     : void disp_batting_data(void)
//   Usage    : データを表示する。
//   Parameter: なし
//   Return   : なし
// =========================================================================
void disp_batting_data( void )
{
    fprintf(stdout,"%2ld    %-12s    %-6s    %1.3lf    %3ld    
                  %3ld    %3ld    %3ld    %3ld    %3ld    %1.3lf    %1.3lf\n",
        batting_data.no , batting_data.name , batting_data.team , 
        batting_data.batting_average , batting_data.at_bat,
        batting_data.hit , batting_data.home_run , batting_data.run, 
        batting_data.strikeout , batting_data.double_play ,
        batting_data.extra_base_percentage , 
        batting_data.on_base_percentage);  
    return;
}


A実行結果

2)ROWIDの利用
ROWIDは、SQLiteの各行を識別するために設定されます。(ROWIDを設けないDBも作成できます)ROWIDは「OID」、「_ROWID_」も同じものを指し示しています。
「挿入、更新、検索」と同じ処理を行うソースプログラムが@、プログラムの実行結果はAです。
select文では、「select ROWID, *」で、ROWIDを含めます。Update文では、「update ・・・ where ROWID = ?」のように、行を指定して更新します。

Bソースプログラム(ROWID)

// -------------------------------------------------
// sqlite_28.c  SQLite テストプログラム
//    ・rowid を使う。
//    ・prepare,stepを使う
//    ・select , insert , update 処理
//    ・日本語項目はUTF8
//    2022/02/08 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}
};

// --------------- prototype --------------------
    void set_batting_data( sqlite3_stmt * );
    void disp_batting_data( void );

    BATTING batting_data;

// --------------- 共通 -------------------------

    char sql_statement[2000];

    sqlite3_stmt* stmt_select;        // 検索 用 
    sqlite3_stmt* stmt_insert;        // 挿入 用
    sqlite3_stmt* stmt_update;        // 更新 用
    sqlite3_stmt* stmt_disp;        // 表示 用 

    long rowid;                        // ROWID

// =========================================================================
//   Name     : int main(void)
//   Usage    : メイン関数
//   Parameter: なし
//   Return   : 
// =========================================================================
int main(void)
{

    int i ;
    int rc;                // 結果

    sqlite3 *db;
    char *db_name = "batting_utf8_2.db";
    char *table_name = "batting_utf8_2019";

    char *error_message;
                                                // データベース定義
    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 ,\
                    PRIMARY KEY(name, team)";

                                                  // SQLITE stmt 用の設定

    char *sql_statement_select ="SELECT ROWID , * FROM batting_utf8_2019 
                                   WHERE name like ?2 AND team like ?3";
    char *sql_statement_insert = "INSERT INTO batting_utf8_2019 
        VALUES( ?1 , ?2 , ?3 , ?4 , ?5 , ?6 , ?7 , ?8 , ?9 ,?10 , ?11 , ?12 )";
    char *sql_statement_update = "UPDATE batting_utf8_2019 
                              SET at_bat =?5 , hit =?6  WHERE ROWID = :rowid";
    char *sql_statement_disp ="SELECT ROWID , * FROM batting_utf8_2019 ORDER BY no";

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

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

            // データベースファイルを作成

    rc = sqlite3_open_v2( db_name , &db , 
                    SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE , NULL);

            // データベース テーブル作成

    sprintf(sql_statement, "create table %10s(%10s)", table_name, table);
    rc = sqlite3_exec(db, sql_statement, NULL, NULL, &error_message );

            // SQLite statement 設定( 検索 、挿入 、更新 、表示)

    sqlite3_prepare_v2(db, sql_statement_select, -1, &stmt_select, NULL);
    sqlite3_prepare_v2(db, sql_statement_insert, -1, &stmt_insert, NULL);
    sqlite3_prepare_v2(db, sql_statement_update, -1, &stmt_update, NULL);
    sqlite3_prepare_v2(db, sql_statement_disp, -1, &stmt_disp, NULL);

            // 挿入

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

            // NKF(UTF-8変換)

        NkfConvert( utf8_name , batting[i].name);
        NkfConvert( utf8_team , batting[i].team);

        sqlite3_bind_int(stmt_insert, 1, batting[i].no ); 
        sqlite3_bind_text(stmt_insert, 2, utf8_name ,-1,SQLITE_TRANSIENT); 
        sqlite3_bind_text(stmt_insert, 3, utf8_team ,-1,SQLITE_TRANSIENT); 

        sqlite3_bind_double(stmt_insert, 4, batting[i].batting_average ); 
        sqlite3_bind_int(stmt_insert, 5, batting[i].at_bat ); 
        sqlite3_bind_int(stmt_insert, 6, batting[i].hit ); 
        sqlite3_bind_int(stmt_insert, 7, batting[i].home_run ); 
        sqlite3_bind_int(stmt_insert, 8, batting[i].run ); 
        sqlite3_bind_int(stmt_insert, 9, batting[i].strikeout ); 
        sqlite3_bind_int(stmt_insert, 10, batting[i].double_play ); 
        sqlite3_bind_double(stmt_insert, 11, batting[i].extra_base_percentage); 
        sqlite3_bind_double(stmt_insert, 12, batting[i].on_base_percentage); 

        rc = sqlite3_step(stmt_insert);

        if(rc != SQLITE_DONE){
            fprintf(stdout, "INSERT NG:[%d %d]\n", i+1 , rc);
            return 0;
        }
        sqlite3_reset(stmt_insert);
    }
    fprintf(stdout,"ROWID    順位    選手        球団    打率    打数    
             安打    本塁打    打点    三振    併殺打    長打率    出塁率\n"); 
            
             // UPDATE  "鈴木 誠也" ,"(広)" があれば、 打数と安打数を0に更新 。 

    NkfConvert( utf8_name , "鈴木 誠也");
    NkfConvert( utf8_team , "(広)");

    sqlite3_bind_text(stmt_select, 2, utf8_name ,-1,SQLITE_TRANSIENT); 
    sqlite3_bind_text(stmt_select, 3, utf8_team ,-1,SQLITE_TRANSIENT); 

    rc = sqlite3_step(stmt_select);

    fprintf(stdout , "== 変更前==\n");
    set_batting_data( stmt_select );
    
    disp_batting_data();
    fprintf(stdout , "== 変更後==\n");


    if( rc == SQLITE_ROW){

        sqlite3_bind_int(stmt_update, 5, 0 ); 
        sqlite3_bind_int(stmt_update, 6, 0 ); 

        sqlite3_bind_int(stmt_update, 
              sqlite3_bind_parameter_index(stmt_update , ":rowid"), rowid ); 

        rc = sqlite3_step(stmt_update);

        if(rc != SQLITE_DONE){
            fprintf(stdout, "UPDATE NG:[%s]\n", sqlite3_errmsg(db));
            return 0;
        }
        sqlite3_reset(stmt_update);

    }
    sqlite3_reset(stmt_select);

                                    //  1件の表示・・・・変更後
    rc = sqlite3_step(stmt_disp);

    if(rc == SQLITE_ROW){
        set_batting_data(stmt_disp);
        disp_batting_data();

    }
    sqlite3_reset(stmt_disp);

    rc = sqlite3_finalize(stmt_select);
    rc = sqlite3_finalize(stmt_insert);
    rc = sqlite3_finalize(stmt_update);
    rc = sqlite3_finalize(stmt_disp);

    rc = sqlite3_close(db);

    return 0;
}

// =========================================================================
//   Name     : void set_batting_data( sqlite3_stmt* )
//   Usage    : 検索データを構造体にセットする。
//   Parameter: なし
//   Return   : なし
// =========================================================================
void set_batting_data( sqlite3_stmt* stmt )
{

    int i = 0;
                                // UTF8 、sjis 変換用
    char utf8_name[200];
    char utf8_team[200];

    char sjis_name[200];
    char sjis_team[200];

            // NKF(SJIS-UTF-8変換設定)

    SetNkfOption("-s");

    rowid = sqlite3_column_int(stmt, i++);
    batting_data.no = sqlite3_column_int(stmt, i++);

            // NKF(SJIS変換)
    
    strcpy(utf8_name , (char*) sqlite3_column_text(stmt, i++));
    strcpy(utf8_team , (char*) sqlite3_column_text(stmt, i++));
    
    NkfConvert( sjis_name , utf8_name);
    NkfConvert( sjis_team , utf8_team);

    strcpy(batting_data.name , sjis_name );
    strcpy(batting_data.team , sjis_team );

    batting_data.batting_average = sqlite3_column_double(stmt, i++);
    batting_data.at_bat = sqlite3_column_int(stmt, i++);
    batting_data.hit = sqlite3_column_int(stmt, i++);
    batting_data.home_run = sqlite3_column_int(stmt, i++);
    batting_data.run = sqlite3_column_int(stmt, i++);
    batting_data.strikeout = sqlite3_column_int(stmt, i++);
    batting_data.double_play = sqlite3_column_int(stmt, i++);
    batting_data.extra_base_percentage = sqlite3_column_double(stmt, i++);
    batting_data.on_base_percentage = sqlite3_column_double(stmt, i++);

    return;
}

// =========================================================================
//   Name     : void disp_batting_data(void)
//   Usage    : データを表示する。
//   Parameter: なし
//   Return   : なし
// =========================================================================
void disp_batting_data( void )
{
    fprintf(stdout,"%2ld    %2ld    %-12s    %-6s    %1.3lf    %3ld    %3ld  
                         %3ld    %3ld    %3ld    %3ld    %1.3lf    %1.3lf\n",
        rowid ,  
        batting_data.no , batting_data.name , batting_data.team , 
        batting_data.batting_average , batting_data.at_bat,
        batting_data.hit , batting_data.home_run , batting_data.run, 
        batting_data.strikeout , batting_data.double_play ,
        batting_data.extra_base_percentage , batting_data.on_base_percentage);  
    return;
}



C実行結果


戻る 次へ