필자가 QT를 이용해서 만들고자 하는 중간예제에 데이터베이스가 필요하게 될것 같아서 사전준비를 해둔다. 필자는 그리 방대한 데이터베이스를 사용할 필요가 없지만 텍스트파일의 관리의 위험성은 원하지 않는다. 가볍게 사용할 수 있는 데이터베이스가 필요했는데, 보통 안드로이드앱에서 가장 많이 사용하는 간단한 데이터베이스인 SQLite가 생각이 났다. 필자가 처음 접했던 데이터베이스가 DB-III Plus였던거 같은데... 그냥 추억이었고, 대학다닐때 Access, MSSQL, MySQL정도를 만저볼수 있었고, 취미생할을 영위하기 위해 최종적으로는 MySQL위주로 써온것 같다. 또한 MySQL의 경우 임베디드에 포팅되 되기 때문에 임베디드 일을 시작하면서부터는 MySQL만 섰다. 어쨋거나, 학교 과제레벨에서야 파일을 이용해서 저장하기도 하지만, 업으로 했을 때 파일을 이용한 저장은 그리 달갑지 않고, 안전한 데이터 저장 수단이 필요하다고 판단될 때 이러한 DB를 이용하게 된다.

     

    1. SQLite 소개

      SQLite는 디스크 저장 기반의 가벼운 데이터베이스 엔진이다. 별도의 프로세스가 필요하지 않으며, SQL 쿼리 언어의 비표준 변형을 사용하여 데이터베이스에 액세스 할 수 있다. SQLite는 소형 임베디드 장치 또는 IoT 장치에 적용하기 적합한 관계형 DB이다.

     

      안드로이드 앱의 경우 내장 DB를 사용할 경우, 안드로이드 시스템에 있는 SQLite를 이용하게 된다. 필자의 경우 예전에 안드로이드는 JNI 기반의 하드웨어 제어등만 해서 굳이 DB와 관련된 기능을 사용해 본적이 딱히 없는 것 같다. 리눅스 기반에서 DB를 이용할 경우에는 대부분 MySQL(MariaDB)를 이용하였기 때문에 말이다. SQLite는 데이터가 파일로 저장되기 때문에, 처리해야 될 양이 많거나 짧은 시간동안 빈번하게 데이터의 트랜젝션이 일어나거나 복잡한 형태의 관계를 가진 DB가 필요한 경우라면 SQLite를 사용하는 것은 좋은 선택이 아닐 수 있다. 이런 경우 서버와 클라이언트 구조를 가진 MySQL(MariaDB)이나 오라클, MSSQL등을 이용하는 것이 좋다. 다만, 개발한 시스템을 판매할 경우에는 라이선스와 같은 부분의 문제를 잘 해결하여야 한다.

     

     

     

    2. SQLite 설치

     이전의 라즈베리파이 운영체제인 라즈비안 또는 최신의 라즈베리파이 OS에서 apt 또는 apt-get 명령을 이용하여 설치가 가능하다.

    2.1. 패키지 저장소 업데이트

      라즈베리파이에 이더넷 케이블 또는 WIFI를 통해 인터넷과 연결될 수 있도록 설정한다. 패키지 다운로드를 위해서 저장소 업데이트를 진행한다.

     

    pi@raspberrypi:~ $ sudo apt update

      

     

    2.2. 라즈베리파이 시스템 업그레이드

      라즈베리파이의 패키지등 업그레이드를 해서 최신 상태로 설정하기 위해 업그레이드를 진행한다. 업그레이드의 경우 별도로 진행하지 않아도 무방한데, 간혹 내가 사용하고자 하는 패키지와 버전에 대한 의존성(같이 설치되어야 구동되는)이 있을 수 있으므로 업그레이드를 하는 것을 추천한다.

     

    pi@raspberrypi:~ $ sudo apt upgrade

     

     

    2.3. SQLite 설치

      SQLite를 설치하기 위해서 아래와 같이 apt를 이용하여 라즈베리파이에 설치할 수 있다.

     

    pi@raspberrypi:~ $ sudo apt install sqlite3

      

     

     

    3. SQLite Command Line Interface (CLI)

      대부분의 DB들은 Command Line Interface(이하, CLI)를 지원한다. 따라서 애플리케이션을 작성해서 연동하기 이전에 기본적인 사용자 설정, 데이터베이스 생성, 테이블 생성등은 이러한 CLI 인터페이스를 이용하기도하고 CLI를 이용할 수 있는 스크립트(파일명.sql)등을 이용하기도 한다. 여기에서는 데이터베이스를 생성과 삭제, 테이블의 생성과 삭제를 위한 기본적인 CLI 에 대해서 이야기 하고자 한다.

     

    3.1. SQLite 실행

      라즈베리파이에 설치된 SQLite를 싱행하기 위해서 다음과 같이 입력하여 선택된 데이터베이스 파일을 통해 SQL문을 작성하여 관리할 수 있다. 아래와 같이 사용할 DB명과 함께 sqlite를 실행한다.

    1) 기존에 사용하지 않은 DB파일명을 입력하면, 테이블을 만드는 순간 입력한 DB파일 이름으로 데이터베이스가 생성.

    2) 기존에 사용하던 파일이면 DB를 사용할 수 있는 상태가 된다.

     

    pi@raspberrypi:~ $ sqlite3 mydb1

     

     

    3.2. 테이블 생성

      사용자가 지정한 데이터베이스가 열리고 CLI 프롬프트(sqlite>)가 표시되면 사용할 DB테이블을 생성할 수 있다. 기본 구조는 다음과 같다.

     

    CREATE TABLE <Table Name> (<Field 1 Name> <Data Type>, … <Field n Name> Mdata Type>);

      

    1) 테이블 생성 예시

    예를들면, 멤버 정보를 담는 테이블을 만든다고 가정하면, 아래와 같이 테이블을 생성할 수 있다.

     

    sqlite> create table members (uid integer, name text, sex integer, age integer, phone text);

     

    members.db 생성

    테이블을 생성했으니, .exit 구문으로 빠져나와 데이터베이스 파일이 생성되었는지 확인해보자.

    생성된 DB 파일 확인

     

    2) 특정 필드의 값을 자동증가 시키는 테이블 생성 예시

      일반적으로 동일할 수 없는 값또는 순차 자동으로 증가하는 형태의 테이블이 필요한 경우 어떻게 처리하면 될까? mysql에서는 autoincrement를 적용하였는데, SQLiteautoincrement를 지원하지만 primary key로 지정해야된다. autoincrement로 설정된 필드는 이후 자동으로 번호가 부여되므로, 데이터를 입력(insert)하지 않아도 된다.어쨋거나 아래의 예시는 id값을 자동으로 증가하도록 테이블을 구성하는 경우의 예시이다.

     

    create table user01 (uid integer primary key autoincrement, name text, sex integer, age integer, phone text);

     

      추가적으로 공백으로 처리되면 안되는 컬럼의 경우 NOT NULL로 처리 가능하다.

     

    3) 생성된 테이블 구조 확인 (.schema)

      테이블을 생성하고난 다음 시간이 흐르게되면 기억이 잘 나지 않는 경우가 대부분이다. 특히 문서화 하지 않았다면 대략 난감해 질 수 있는데, 걱정하지 않아도 된다. .schema(스키마)를 입력하면 테이블의 구조를 확인할 수 있다. 

     

    sqlite> .schema

     

    테이블구조 확인을 위해 .schema 입력

     

     

    3.3. SQLite의 변수타입

      SQL 테이블 생성시 사용할 수 있는 변수의 타입은 아래와 같다. 

    1) INTEGER : 부호가 있는 정수

    2) REAL : 부동 소수점 값 8바이트 IEEE 부동 소수점으로 저장

    3) TEXT : 텍스트 문자

    4) BLOB : Binary Large Object

    5) NULL : 공백

     

     

    3.4. 데이터 입력 (INSERT 구문)

     생성된 테이블에 데이터를 넣는 방법은 insert문을 사용하여 DB에 데이터를 삽입할 수 있다.

     

    INSERT INTO <Table Name> (<Field 1 Name>, …<Field n Name>) VALUES
    (<Value 1>, … <Value n>);

      

    앞서 생성된 테이블에 데이터를 넣어보도록 하자.

     

    sqlite> insert into members (uid, name, sex, age, phone) values (1,”Hong”,1,32, “010-0101-0100”);
    sqlite> insert into members (uid, name, sex, age, phone) values (2,”Park”,1,30, “010-1010-0011”);
    sqlite> insert into members (uid, name, sex, age, phone) values (3,”Kim”,2,27, “010-1110-0111”);

     

    생성된 테이블에 데이터를 입력

     

      만약, DB내에 여러 테이블이 있는 경우, 다른 테이블에 있는 데이이터를 가져올때는 아래와 같은 형태로 SQL문을 구성할 수 있다. 아래의 예시는 vip 테이블에서 age가 40보다 큰 사람의 name, sex, age를 members 테이블의 동일한 필드에 넣는 예시이다. where은 조건문으로 특정 조건을 지정할 때 사용된다. 

     

    sqlite > insert into members (name, sex, age) select name, sex, age from vip where age > 40;

     

    다만 가져와서 저장할 컬럼의 필드 이름은 달라도 속성은 같아야 한다.

     

     

    3.5. 데이터베이스에서 데이터 가져오기 (SELECT 구문)

      위에서 저장한 데이터를 가져와서 출력하려면 SELECT문을 이용한다.

     

    SELECT * FROM <Table Name>;

     

    1) 테이블 내용 전체 출력

      입력했던 데이터들을 출력해보자.  

     

    sqlite> select * from members;
    1|Hong|1|32|010-0101-0100
    2|Park|1|30}010-1010-0011

     

    SELECT 구문을 이용하여 입력된 데이터 전체 출력

     

    2) 조건부 출력 (WHERE 구문)

      다음은 30살 이상의 사람만 출력 해보도록 하자. 

     

    조건식에 맞는 데이터 출력

     

    3.6. 내용변경 (UPDATE 구문)

      UPDATE 문을 이용하여 필드의 값을 변경할 수 있다.

     

    sqlite> update members set name = 'EUM' where uid=2;
    sqlite> select * from members;
    1|Hong|1|32|010-0101-0100
    2|EUM|1|30}010-1010-0011
    3|Kim|2|27|010-1110-0111

    uid가 2번인 레코드의 name필드의 값을 EUM으로 변경

     

      주의할 점은 특정 조건을 지정하지 않으면 테이블의 필드 전체의 데이터가 바뀌어버린다. 데이터가 많은 경우라면 복구 하는게 힘들어지니, 업데이트 할 때에는 항상 조건이 들어가야 된다고 기억해두자.

     

    sqlite> update members set name = "EUM"
    sqlite> select * from members;
    1|Kim|1|32|010-0101-0100
    2|Kim|1|30}010-1010-0011
    3|Kim|2|27|010-1110-0111

     

      만약 부분적으로 특정 필드의 특정값이 있는 경우에 해당하는 필드의 값을 한번에 변경 해야 하는 상황이면 다음과 같이 조건을 만들어서 설정하자. 아래의 SQL 문이 동작하면 name필드가 Kim인 경우 해당 레코드의 name을 Hong으로 변경한다. 

     

    sqlite> update user01 set name = "Hong" where name="Kim"
    sqlite> select * from members;
    1|Hong|1|32|010-0101-0100
    2|EUM|1|30|010-1010-0011
    3|Kim|2|27|010-1110-0111

     

    특정조건이 맞는 항목들의 일괄 변경

     

     

    3.7. 데이터 삭제 (DELETE 구문)

      필드에있는 데이터를 삭제하려면 delete문을 이용한다. 아래의 예시는 1번 레코드를 삭제한다. where 구문 뒤의 조건을 통해서  특정 레코드만 삭제하는 것이 가능하다.

     

    sqlite> delete from members where uid=2;
    sqlite> select * from members;
    1|Hong|1|32|010-0101-0100
    3|Hong|2|27|010-1110-0111

     

    특정 조건의 레코드 삭제

      

     

      테이블 내의 모든 내용을 삭제할 경우에는 조건(where)을 지정하지 않으면 된다. 아래와 같이 명령을 입력하면 아무것도 출력되지 않는 것을 볼 수 있다.

     

    sqlite > delete from members
    sqlite > select * from members;

     

    테이블내의 모든 데이터가 삭제되어 출력할 것이 없다.

       

     

     

    3.8. 테이블 삭제 (DELETE 구문)

      데이터 베이스에서 테이블 전체를 삭제하려면 drop문을 이용하여 제거가 가능하다. DROP 구문은 아래와 같이 형식으로 구성된다

     

    DROP TABLE IF EXISTS <Table Name>;

     

    사용 예시는 아래와 같다.

    sqlite> drop table if exists members;

     

    테이블 삭제 후 확인

     

       

     

    3.9. SQLite CLI 종료

      SQLite를 종료하려면 아래와 같이 .quit.exit를 사용하여 종료할 수 있으며, Ctrl+D (End of File)키 조합으로도 종료가 가능하다.

     

    sqlite > .quit

     

    SQLite 종료

      

     

      생각보다 재미있지 않은가? 우리는 기본중의 기본 그리고 쉽고 편하게 사용할 수 있는 SQLite를 이용하기 때문에 재미있게 사용해볼 수 있었지만, 중 대형의 복잡한 시스템의 데이터베이스는 쿼리 자체도 어렵고, 성능관련한 튜닝도 엄청나게 해야 하는 경우가 많아 유지 및 보수, 관리가 어려운 분야가 DMBS 분야이다.  하지만 우리가 평상적으로 사용하는 대부분의 애플리케이션등은 지금 해본 정도 수준에서 대부분 해결이 가능할 것으로 예상한다.

     

      어쨋거나 이정도만 컨트롤 하는 것으로 하자. 이후에 QT에서 SQLite를 이용하여 간단한 DB를 작성하고 사용하는 프로그램을 작성하는데는 이정도만 알면 될 것 같다. 추가적으로 SQL이나 DBMS(DataBase Management System)등을 배워보고 싶은 독자라면 전문서적을 이용하도록 하자.

    반응형
    • 네이버 블러그 공유하기
    • 네이버 밴드에 공유하기
    • 페이스북 공유하기
    • 카카오스토리 공유하기