= SQLite =
== 장점 ==
* ACID(Atomic, Consistent, Isolate, Durable) 보증 (시스템오류나 전원이 갑자기 꺼진 경우에도)
* Setting 절차없이 그냥 바로 사용할 수 있다.
* SQL92의 대부분을 지원한다. 다음 목록은 지원하지 않는다.
- FOREIGN KEY constraints
- Complete trigger support
- Complete ALTER TABLE support
- Nested transactions (1개의 Active Tranjection만을 지원)
- RIGHT and FULL OUTER JOIN (Left Join은 지원)
- Writing to VIEWs (View는 Read Only이다)
- GRANT and REVOKE (client/server 모델이 아니라 지원할 수 없다)
* 단일 파일에 데이터베이스의 모든것을 포함한다. (백업이나 이전하고 싶으면 파일 하나만 이동하면 된다)
* byte order에 관계없이 데이터 파일의 공유가 가능 (Mac,Intel,PowerPC등등에서도 그냥 카피만 하면 된다)
* 2테라바이트 (2^41)크기의 데이터 파일 생성지원
* String이나 BLOB 의 길이 한계는 메모리에 의해서만 영향받는다
* 효율적인 메모리 사용 : 모든 설정을 다 포함하여 250KB, 기본기능만 포함하면 150KB이내
* 많은 일반적인 명령을 실행하는데 PostgreSql과 Mysql보다 최소 2배이상 명령에 따라서 10-20배 이상 빠르다. (라고 주장하지만 실제는 SQLite가 불리한 상황에서 5~10%정도 느린것같다. 빠른경우는 빠르다...)
* 하나의 구조체와 3개의 함수만 사용하는 정도로 sqlite를 사용하는 C/C++ 코드를 만들어 낼 수 있다. (코딩해보면 절대적으로 쉽다. BDB에 비해 생산성과 버그방지 소스코드 유지보수에 절대적으로 유리하다)
* TCL, Perl, PHP, .Net, Java, Python, SmallTalk, Ruby등의 다양한 언어지원 (C밖에 안써봤다ㅜ.ㅠ)
* 다른 라이브러리등의 도움없이 작동된다. libsqlite.so와 sqlite 2개의 파일이면 작동 환경을 만들 수 있다.
* [http://www.sqlite.org/copyright.html Public Domain 라이센스]를 가진다. (수정,배포 등등이 완전 자유롭다)
* 다른 라이브러리를 전혀 필요로 하지 않는다. (포팅이나 이전이 쉽다)
== Command Line Program 사용 ==
test.db라는 DB 생성
$ ./sqlite3 test.db
SQLite version 3.3.5
Enter ".help" for instructions
sqlite>
tb11이라는 테이블 생성, 테이블에 insert, select
sqlite> create table tbl1(one varchar(10), two smallint);
sqlite> insert into tbl1 values('hello!',10);
sqlite> insert into tbl1 values('goodbye', 20);
sqlite> select * from tbl1;
hello!|10
goodbye|20
sqlite>
db의 테이블 리스트 보기
sqlite> .tables
tbl1
sqlite>
cmdline 종료
sqlite> .q
$
db sql dump
$ echo '.dump' | sqlite test.db
BEGIN TRANSACTION;
CREATE TABLE tbl1(one varchar(10), two smallint);
INSERT INTO "tbl1" VALUES('hello!', 10);
INSERT INTO "tbl1" VALUES('goodbye', 20);
COMMIT;
$ echo '.dump' | sqlite test.db | gzip -c >testdb.dump.gz
$
== 기본적인 C API ==
=== sqlite3_open ===
int sqlite3_open(
const char *filename, /* Database filename (UTF-8) */
sqlite3 **ppDb /* OUT: SQLite db handle */
);
DB File을 오픈
=== sqlite3_exec ===
int sqlite3_exec(
sqlite3*, /* An open database */
const char *sql, /* SQL to be executed */
sqlite_callback, /* Callback function */
void *, /* 1st argument to callback function */
char **errmsg /* Error msg written here */
);
SQL문을 실행
=== sqlite3_close ===
int sqlite3_close(sqlite3*);
열려진 DB 파일을 close
=== sqlite3_mprintf ===
char *sqlite3_mprintf(const char*,...);
char *sqlite3_vmprintf(const char*, va_list);
DB의 insert문 등에서 사용할 수 없는 ' 같은 케릭터가 포함될때 SQL용으로 사용할 수 있는 케릭터로 변환시켜주는 sprintf 함수 내부적으로 malloc을 사용하기 때문에 sqlite3_free()로 free해줘야 한다.
=== sqlite3_free ===
void sqlite3_free(void*);
메모리 Free
sqlite3_mprintf(), sqlite3_vmprintf() 의 리턴값 sqlite3_exec() 의 에러값을 Free할때는 sqlite3_free()를 사용한다.
=== sqlite3_get_table ===
int sqlite3_get_table(
sqlite3*, /* An open database */
const char *sql, /* SQL to be executed */
char ***resultp, /* Result written to a char *[] that this points to */
int *nrow, /* Number of result rows written here */
int *ncolumn, /* Number of result columns written here */
char **errmsg /* Error msg written here */
);
SQL의 실행 결과를 받아오는 함수 resultp에 내부적으로 malloc하여 가져오기 때문에 사용후 sqlite3_free_table()을 사용해야 한다.
=== sqlite3_free_table ===
void sqlite3_free_table(char **result);sqlite3_get_table()의 결과값을 free시켜주는 함수.
== C API 사용 예 ==
=== DB Open ===
db open, timeout 500ms으로 설정, 속도를 빠르게 해주기 위한 옵션 설정.
/* OPEN DATABASE */
ret = sqlite3_open("cache_data/cache_db.sqlite3", &pDb);
if (ret != SQLITE_OK)
{
PRINT_LOG(stdout, "OPEN ERR:%s\n", sqlite3_errmsg(pDb));
return -1;
}
sqlite3_busy_timeout(pDb, 500);
ret = sqlite3_exec(pDb,
"PRAGMA synchronous=OFF;
PRAGMA count_changes=OFF;
PRAGMA temp_store=memory;",
NULL, NULL, &errmsg);
=== 테이블 생성 ===
table과 index를 생성
int create_sqlite_table(void)
{
int ret;
sqlite3 *pDb;
char *errmsg;
ret = sqlite3_open("cache_data/cache_db.sqlite3", &pDb);
if (ret != SQLITE_OK)
{
PRINT_LOG(stdout, "OPEN ERR:%s\n", sqlite3_errmsg(pDb));
return -1;
}
ret = sqlite3_exec(pDb,
"CREATE TABLE local_search_cache ( key TEXT PRIMARY KEY,
data TEXT, date TEXT)",
NULL, NULL, &errmsg);
if (ret != SQLITE_OK)
{
printf("Write Error: %s\n", errmsg);
sqlite3_free(errmsg);
return -1;
}
ret = sqlite3_exec(pDb,
"CREATE INDEX date_idx ON local_search_cache ( date DESC
)",
NULL, NULL, &errmsg);
if (ret != SQLITE_OK)
{
printf("Write Error: %s\n", errmsg);
sqlite3_free(errmsg);
return -1;
}
sqlite3_close(pDb);
return 0;
}
=== 데이터 읽기 ===
데이터를 읽고 필드 1개를 업데이트
int read_cache(void *pDb, char *strkey, int key_len, char *strdata, int
*data_len)
{
int ret;
char *buf;
char **resultp;
int nrow,ncol;
char *errmsg;
/* DATA가 있는지 확인 */
buf = sqlite3_mprintf(
"SELECT key,data,date FROM local_search_cache WHERE key='%q';", strkey);
ret = sqlite3_get_table(pDb, buf, &resultp, &nrow, &ncol, &errmsg);
sqlite3_free(buf);
if (ret != SQLITE_OK)
{
PRINT_LOG(stderr, "Read SELECT Error (%s)", errmsg);
sqlite3_free(errmsg);
strdata[0] = '\0';
*data_len = 0;
return -1;
}
/* DATA가 없으면 */
if (nrow ==0)
{
//PRINT_LOG(stderr, "Read NOTFOUND strkey(%s)\n", strkey);
sqlite3_free_table(resultp);
strdata[0] = '\0';
*data_len = 0;
return -1;
}
/* DATA가 있으면 리턴 */
ret = strlen(resultp[4]);
if (strdata)
snprintf(strdata, ret+1, "%s", resultp[4]);
if (data_len)
*data_len = ret;
sqlite3_free_table(resultp);
/* DATA가 UPDATE access history */
buf = sqlite3_mprintf(
"BEGIN;UPDATE local_search_cache SET date=%d WHERE key='%q';COMMIT;"
, (int)time(NULL), strkey);
ret = sqlite3_exec(pDb, buf, NULL, NULL, &errmsg);
sqlite3_free(buf);
if (ret != SQLITE_OK)
{
//PRINT_LOG(stderr, "Read UPDATE ACCESS HISTORY Error (%s)", errmsg);
}
return 0;
}
=== 데이터 쓰기 ===
데이터를 쓰고 일정 사이즈 이상이면 1개를 삭제
int write_cache(void *pDb, char *strkey, int key_len, char *strdata, int *data_l
en)
{
int ret;
char *buf;
char *errmsg;
/* DATA가 없으면 새로 추가 있으면 UPDATE */
buf = sqlite3_mprintf(
"BEGIN;REPLACE INTO local_search_cache (key, data, date)
values ('%s', '%s', %d);", strkey, strdata, (int)time(NULL));
ret = sqlite3_exec(pDb, buf, NULL, NULL, &errmsg);
sqlite3_free(buf);
if (ret != SQLITE_OK)
{
PRINT_LOG(stderr, "Write REPLACE Error: %s\n", errmsg);
sqlite3_free(errmsg);
return -1;
}
buf = sqlite3_mprintf(
"DELETE FROM local_search_cache WHERE
(SELECT COUNT(key)FROM local_search_cache)>%ld
AND key=(SELECT key FROM local_search_cache WHERE
date=(SELECT MIN(date) FROM local_search_cache) LIMIT 1);
COMMIT;"
, cache_size);
ret = sqlite3_exec(pDb, buf, NULL, NULL, &errmsg);
sqlite3_free(buf);
if (ret != SQLITE_OK)
{
PRINT_LOG(stderr, "Write DELETE Error: %s\n", errmsg);
sqlite3_free(errmsg);
return -1;
}
return 0;
}
출처 : http://luzluna.tistory.com/1
[출처] [펌]SQLIte 설명 및 예제코드|작성자 착한아이태훈