2010年4月28日 星期三

[C] 使用 SQLite 教學筆記 - 簡單的 C 語言程式範例

好久沒用 databases 囉!前一次自己使用已經是三、四年前的事了,碩班都是自己維護甚至用 C 語言開發資料的處理部分。回到正題,SQLite 是一套很簡潔的資料庫,適用於不少地方,細節請參考:Appropriate Uses For SQLite


相關學習文章:



此篇僅筆記如何使用,附上完整的範例程式:


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

#define CMD_CREATE_TABLE    "CREATE TABLE IF NOT EXISTS MyTable( column1 int, column2 char(20) );"
#define CMD_INSERT_ITEM        "INSERT INTO MyTable VALUES( 1 , 'Hello World' );"
#define CMD_QUERY        "SELECT * FROM MyTable;"

int Callback_ShowList( void *context, int count, char **values, char ** columnName )
{
    int i;
    context = NULL;
    for( i=0 ; i<count ; ++i )
        printf( "\t\t%s = %s\n" , columnName[i] , values[i] ? values[i] : "NULL" );
    printf( "\n" );
    return SQLITE_OK;
}

int main( int argc , char* argv[] )
{
    char *error_report = NULL;
    sqlite3 *db = NULL;

    if( argc < 2 )
    {
        fprintf( stderr , "Usage> %s sqlite_db_file\n" , argv[0] );
        exit(1);
    }

    printf( "1> Open a database\n" );
    if( sqlite3_open( argv[1] , &db ) != SQLITE_OK )
    {
        fprintf( stderr , "\t> Cannot open databases: %s\n" , sqlite3_errmsg(db) );
        sqlite3_close( db );
        exit(1);
    }
    else
        printf( "\t> Finish\n" );

    printf( "2> Create a table\n" );
    if( sqlite3_exec( db , CMD_CREATE_TABLE , Callback_ShowList , NULL , &error_report ) != SQLITE_OK )
    {
        fprintf( stderr , "\t> CMD: %s , Error: %s\n" , CMD_CREATE_TABLE , error_report );
        sqlite3_close(db);
        exit(1);
    }
    else
        printf( "\t> Finish\n" );

    printf( "3> Insert a data\n" );
    if( sqlite3_exec( db , CMD_INSERT_ITEM , Callback_ShowList , NULL , &error_report ) != SQLITE_OK )
    {
        fprintf( stderr , "\t> CMD: %s , Error: %s\n" , CMD_INSERT_ITEM , error_report );
        sqlite3_close(db);
        exit(1);
    }
    else
        printf( "\t> Finish\n" );

    printf( "4> Query\n" );
    if( sqlite3_exec( db , CMD_QUERY , Callback_ShowList , NULL , &error_report ) != SQLITE_OK )
    {
        fprintf( stderr , "\t> CMD: %s , Error: %s\n" , CMD_QUERY , error_report );
        sqlite3_close(db);
        exit(1);
    }
    else
        printf( "\t> Finish\n" );


    if( argc > 2 )
    {
        printf( "N> Do argv[2] ...\n" );
        if( sqlite3_exec( db , argv[2] , Callback_ShowList , NULL , &error_report ) != SQLITE_OK )
        {
            fprintf( stderr , "\t> CMD: %s, Error: %s\n" , argv[2] , error_report );
            sqlite3_close(db);
            exit(1);
        }
        else
            printf( "\t> Finish\n" );
    }
    return 0;
}


流程:


依序是建立資料庫、資料表、新增資料、查詢和最後如果有另外傳參數的話,幫你執行一下!


編譯:


此例在 Mac OS 10.6.2
$ gcc -lsqlite3 main.c


成果:


$ ./a.out 1 "select * from sqlite_master;"
1> Open a database
        > Finish
2> Create a table
        > Finish
3> Insert a data
        > Finish
4> Query
                column1 = 1
                column2 = Hello World

        > Finish
N> Do argv[2] ...
                type = table
                name = MyTable
                tbl_name = MyTable
                rootpage = 2
                sql = CREATE TABLE MyTable( column1 int, column2 char(20) )

        > Finish


9 則留言:

  1. 您好,
    想請教如果我同一個table裡有a,b,c三個欄位,我想列出a,c兩欄位內容不相同的資料該如何下語法,我用select * table where a<>c,可是資料沒有跑出來,相同語法在ms-sql上是可以執行的,謝謝。

    回覆刪除
    回覆
    1. Hi, 我的認真跟你一樣 XD

      不然就試試看 SELECT * FROM table WHERE a != c;

      刪除
    2. select * table where a<>c和SELECT * FROM table WHERE a != c 我是都嘗試過沒資料跑出來。您還有其他想法可以提供參考嗎? 還是SQLITE不支援相同表格的欄位直接比對.我是都用varchar格式

      刪除
    3. 我測試 OK:

      sqlite> CREATE TABLE test ( a varchar(50), b varchar(30) );
      sqlite> INSERT INTO test (a,b) VALUES ('1','2') , ('2','2'), ('3','2'), ('4','3');
      sqlite> SELECT * FROM test WHERE a != b;
      1|2
      3|2
      4|3

      或許你該留意欄位型態等等的

      測試環境:Mac OSX 10.10.5
      $ sqlite3 --version
      3.8.11.1 2015-07-29 20:00:57 cf538e2783e468bbc25e7cb2a9ee64d3e0e80b2f

      刪除
    4. 我是用firefox的sqlite manager做指令測試,謝謝,也許我該找找其他工具試試。

      刪除
    5. 祝好運啦 :D

      SQLite 整個開發過程都是很猛的(豐富的 Unit Test),估計可能有什麼地方遺漏了。

      PS. 剛才發現第一則打錯字 XD "我認知跟你一樣“

      刪除
    6. 謝謝大大,我找到問題了,建table我是用firefox的sqlite manager,他可以用varchar不指定長度,所以我沒指定欄位的長度,所以sqlite可以讓我建table但是像上面的語法就沒辦法正常抓出資料

      刪除
    7. 感謝分享啊!又學到一課了! :D

      刪除
    8. 更正,上面講的是錯的,實際我測試當a有值而b我故意不填值,也就是INSERT INTO test (a) VALUES ('1') ,這樣的資料內容才是真正跑不出來的原因,而不是varchar不給長度.

      刪除