顯示具有 sqlite3 標籤的文章。 顯示所有文章
顯示具有 sqlite3 標籤的文章。 顯示所有文章

2022年5月26日 星期四

Go 開發筆記 - 使用 database/sql 通用介面存取資料庫,以 SQLite3 為例

在 Golang 的世界,有定義資料庫存取的通用介面 database/sql ,但貌似官方沒有提供實作而是讓廣大的鄉民開發,並且標記哪些套件是有通過 go-sql-test 驗證的,因此,大部分就是挑哪些有標記的,或是直接看 github 有多熱門也行。

相關文件:
以下就連續動作,筆記一下。

程式碼:

package main

import (
    "log"
    "database/sql"
    _ "github.com/mattn/go-sqlite3"
)

func main() {
    db, err := sql.Open("sqlite3", "/tmp/sqlite3.db")
    if err != nil {
        log.Fatalln(err)
    }
    defer db.Close()

    //
    // http://go-database-sql.org/modifying.html
    //
    // via db.Exec with checking the error message only
    if _, err := db.Exec(`
        CREATE TABLE IF NOT EXISTS account (
            uid INTEGER PRIMARY KEY AUTOINCREMENT,
            username VARCHAR(64) NULL
        );
    `); err != nil {
        log.Println(err)
    }

    // Insert via db.Prepare
    if stmt, err := db.Prepare("INSERT INTO account(username) VALUES(?)"); err == nil {
        if res, err := stmt.Exec("changyy.org"); err != nil {
            log.Println("Insert Exec Error:", err)
        } else if lastId, err := res.LastInsertId() ; err != nil {
            log.Println("Get LastInsertId Error:", err)
        } else if rowCount, err := res.RowsAffected() ; err != nil {
            log.Println("Get RowsAffected Error:", err)
        } else {
            log.Println("Insert Done, Last Insert Id:", lastId, ", RowsAffected: ", rowCount)

            // Update via db.Prepare
            if stmt, err := db.Prepare("UPDATE account SET username = ? WHERE uid = ?"); err != nil {
                log.Println("Update Prepqre Error:", err)
            } else if res, err := stmt.Exec("blog.changyy.org", lastId); err != nil {
                log.Println("Update Exec Error:", err)
            } else if rowCount, err := res.RowsAffected() ; err != nil {
                log.Println("Get RowsAffected Error:", err)
            } else {
                log.Println("Update RowsAffected: ", rowCount)
            }
        }
    } else {
        log.Println("Prepqre Insert Error:", err)
    }

    //
    // http://go-database-sql.org/retrieving.html
    // https://pkg.go.dev/database/sql#DB.Query
    //
    // via db.Query with sql.Rows and error mesasge
    rows, err := db.Query("SELECT * FROM account")
    if err != nil {
        log.Println(err)
    } else {
        defer rows.Close()
        log.Println("Result:")
        for rows.Next() {
            var id int
            var username string
            if err := rows.Scan(&id, &username) ; err == nil {
                log.Println(id, username)
            } else {
                log.Println(err)
            }
        }
        if err := rows.Err() ; err != nil {
            log.Println(err)
        }
    }
}

執行:

% go run main.go    
2022/05/25 20:44:26 Insert Done, Last Insert Id: 1 , RowsAffected:  1
2022/05/25 20:44:26 Update RowsAffected:  1
2022/05/25 20:44:26 Result:
2022/05/25 20:44:26 1 blog.changyy.org

% file /tmp/sqlite3.db
/tmp/sqlite3.db: SQLite 3.x database, last written using SQLite version 3038005, file counter 3, database pages 3, cookie 0x1, schema 4, UTF-8, version-valid-for 3

% sqlite3 /tmp/sqlite3.db .schema
CREATE TABLE account (
            uid INTEGER PRIMARY KEY AUTOINCREMENT,
            username VARCHAR(64) NULL
        );
CREATE TABLE sqlite_sequence(name,seq);

2018年10月20日 星期六

[SQL] 在 SQLite3 環境中,使用 Regular Expression @ Ubuntu 16.04

$ sudo apt-get install sqlite3-pcre
$ file /usr/lib/sqlite3/pcre.so
/usr/lib/sqlite3/pcre.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=0afc1236e89d4a8b99746f231049101172714c2c, stripped
$ sqlite3
SQLite version 3.11.0 2016-02-15 17:29:24
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite> SELECT date();
2018-10-19
sqlite> SELECT date() AS d WHERE d REGEXP '[0-9]';
Error: no such function: REGEXP
sqlite> .load /usr/lib/sqlite3/pcre.so
sqlite> SELECT date() AS d WHERE d REGEXP '[0-9]';
2018-10-19
sqlite> SELECT date() AS d WHERE d REGEXP '^[0-9]$';
sqlite> SELECT date() AS d WHERE d REGEXP '^[0-9]+$';
sqlite> SELECT date() AS d WHERE d REGEXP '^[0-9\-]+$';
2018-10-19

2014年8月10日 星期日

iOS 開發筆記 - 透過 CocoaPods - FMDB / FMDatabase 管理 SQLite Databases

好久沒用 C/C++ 處理 SQLite 的操作,原本有意直接在 Objective-C 一樣寫 C 來處理,但想起來最近一直把玩 CocoaPods ,就搜尋一下,發現 FMDB 還滿多的推薦的,且 github.com/ccgus/fmdb 上頭也有很猛的人數 XD 就下海來使用 FMDB 啦!

主要看中 FMDB 的特色:提供 Data Sanitization 機制!就是寫 PHP 時,會透過 mysql_real_escape_string 來處理 raw data ,避免資料格式破壞 SQL 語法。

把玩筆記:

#import "FMDatabase.h"
// $ vim Podfile
// pod 'FMDB'

- (void)insert {
// Documents/test.db
NSString *dbPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0] stringByAppendingPathComponent:@"test.db"];
BOOL needInitTable = ![[NSFileManager defaultManager] fileExistsAtPath:dbPath];
FMDatabase *db = [FMDatabase databaseWithPath:dbPath];
if ([db open]) {
// init table
if (needInitTable && ![db executeStatements:@"CREATE TABLE IF NOT EXISTS t (id VARCHAR(8), number INT)"]) {
NSLog(@"table init error");
return;
}

// insert data
if (![db executeUpdate:@"INSERT OR IGNORE INTO t (id, number) VALUES ( :id, :number )" withParameterDictionary:@{
@"id" : @"id_data",
@"number": @(12345)
}] ) {
NSLog(@"insert error");
}
[db close];
}
}

- (NSArray *)query {
// Documents/test.db
NSString *dbPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0] stringByAppendingPathComponent:@"test.db"];
BOOL needInitTable = ![[NSFileManager defaultManager] fileExistsAtPath:dbPath];
FMDatabase *db = [FMDatabase databaseWithPath:dbPath];
if (!needInitTable) {
if ([db open]) {
NSMutableArray *output = [[NSMutableArray alloc] init];
FMResultSet *rs = [db executeQuery:"SELECT id, number FROM test;"];
while ([rs next]) {
// records to NSArray
NSMutableDictionary *item = [[NSMutableDictionary alloc] init];

item[@"id"] = [rs stringForColumn:@"id"];
item[@"number"] = @([rs intForColumn:@"number");

[output addObject:item];
}
[db close];
return output;
}
}
return @[];
}