IOS - 關于移動端SQLite,你想知道的都有

KirstenGumm 8年前發布 | 13K 次閱讀 SQLite

一、SQLite簡介

SQLite,是一款輕型的數據庫,是遵守 ACID 的關系型數據庫管理系統,它包含在一個相對小的C庫中。它是D.RichardHipp建立的公有領域項目。它的設計目標是嵌入式的,而且目前已經在很多嵌入式產品中使用了它,它占用資源非常的低,在嵌入式設備中,可能只需要幾百K的內存就夠了。它能夠支持Windows/Linux/Unix等等主流的操作系統,同時能夠跟很多程序語言相結合,比如 Tcl、C#、PHP、Java等,還有ODBC接口,同樣比起Mysql、PostgreSQL這兩款開源的世界著名數據庫管理系統來講,它的處理速度比他們都快。

二、SQLite優勢

  • 1、占用資源低
  • 2、速度快
  • 3、與其他數據庫相比,更適配移動平臺、嵌入式平臺

三、SQLite支持的存儲類型有:

1、INTEGER    - 整形
 2、blob       - 二進制
 3、real       - 浮點型
 4、text       - 字符串
 5、NULL       - 空

注意: 在SQLite中大小寫不區分,也就是AA = aA = Aa = aa

四、SQLite學習之DDL

DDL(Data Definition Language):數據定義語言,用來創建數據庫中的各種對象-----表、視圖、

索引、同義詞、聚簇等

  • 創建表
    CREATE TABLE 表名 (字段名 字段類型,字段名1 字段類型1,...);
  • 刪除表
    DROP TABLE 表名;

DDL - 創建表:

<br />

CREATE TABLE T_Person(id INTEGER, name TEXT,age INTEGER); 在這里我們通常有兩種書寫格式,假設語句不是很長的情況下, 可以寫成一行,但是如果語句過長就不利于閱讀,所以有了下面的格式: CREATE TABLE T_Person ( id INTEGER, name TEXT, age INTEGER );</code></pre>

通過上述代碼我們就可以創建一個表了,但是如果在執行一次上面的語句, 就會發現報錯了,

錯誤:文件已存在 Error : table T_Person already exists

所以我們創建的時候需要判斷表是不是存在

于是有了下面的創建語句:

CREATE TABLE IF NOT EXISTS T_Person
(
    id INTEGER, 
    name TEXT,
    age INTEGER
);

其中

IF NOT EXISTS : 如果不存在
上面創建的語句翻譯就是:
創建一個表,如果不存在的話就創建

DDL - 刪除表:

DROP TABLE T_Person;

五、SQLite學習之DML

DML(Data Manipulation Language)數據庫操作語句:

關鍵字有insert,update,delete

分別對應:插入、更新、刪除

  • 插入數據
    INSERT INTO 表名(字段...) VALUES(值...);
  • 更新數據
    UPDATE 表名 SET 字段名=值,...;
  • 刪除數據
    DELETE FROM 表名;

DML - 插入數據:

INSERT INTO T_Person1 (name,age) VALUES('zs',20);

在現實生活中我們可能會遇到這樣一種情況: 在一個班里,有可能有兩個人的姓名完全一致,這個時候我們 就需要進行區分,就像每個人都有一個身份證號,且唯一</code></pre>

這個時候如何區分?

如果想保證數據唯一:

這個時候就需要主鍵: PRIMARY KEY ,所以我們要修改我們的創建表的語句

修飾主鍵的方法有兩種:

  • 方法一:
    CREATE TABLE T_Person
    (
      id INTEGER PRIMARY KEY, 
      name TEXT,
      age INTEGER
    );
  • 方法二:
    CREATE TABLE IF NOT EXISTS T_Person1
    (
      id INTEGER, 
      name TEXT,
      age INTEGER,
      PRIMARY KEY (id)
    );
    這個時候我們再次執行插入語句
    INSERT INTO 
    T_Person1 (id,name,age) 
    VALUES(1,'zs',20);
    .
    第一次:Affected rows : 1, Time: 0.00sec
    第二次:Error : UNIQUE constraint failed: T_Person1.id
    從上面的結果可以看出,id不能相同,那怎么樣才能保證ID不相同,
    又不輸入id這個屬性呢?因為人輸入,可能會存在差錯,交給機器做最好。
    于是我們要用到個新的關鍵字: AUTOINCREMENT 自增
    所以我們還要在修改一次創建語句:
    CREATE TABLE IF NOT EXISTS T_Person1
    (
      id INTEGER PRIMARY KEY AUTOINCREMENT, 
      name TEXT,
      age INTEGER
    );
    現在我們就可以肆無忌憚的執行下面這條插入語句了
    INSERT INTO 
    T_Person1 (name,age) 
    VALUES('zs',20);
    下面是執行了5次的之后的表:

執行了5次之后

現在我們完全可以不用管理ID這個字段,并且現在每一條數據都是唯一的。

但是在某些情況下還是會有不完善的地方,比如下面這條插入語句:

INSERT INTO 
T_Person1 (age) 
VALUES(35);

然后我們來查看一下表:

插入了一條姓名為空、年齡是35的數據

這樣子看似乎沒有問題,但是結合實際情況來看,假設這是一個班級的數據,我不希望我的學生連名字都沒有,這個不像話。

然后沒錯,又要使用一個新的關鍵字: NOT NULL 不為空

然后再次更新表的創建語句:

CREATE TABLE T_Person1 (
     id INTEGER PRIMARY KEY AUTOINCREMENT,
     name TEXT NOT NULL,
     age INTEGER
);

然后我們再次執行上面的語句

INSERT INTO 
T_Person1 (age) 
VALUES(35);
錯誤提示:Error : NOT NULL constraint failed: T_Person1.name

這個時候就會報錯:提示我們名字不能為空

于是我們要寫成:

INSERT INTO 
T_Person1 (name,age) 
VALUES('xiaoming',35);
提示:Affected rows : 1, Time: 0.00sec

再次查看表:

插入數據

然后我們在介紹一個屬性: DEFAULT 默認值

使用方法就是在字段名后面

age INTEGER DEFAULT 15
表示定義了一個age 字段 默認是15

這個時候我們的創建表語句如下:

CREATE TABLE T_Person1 (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    age INTEGER DEFAULT 15
);

然后我們插入數據:

INSERT INTO T_Person1 (name) VALUES('zs');
INSERT INTO T_Person1 (name,age) VALUES('ls',18);
INSERT INTO T_Person1 (name,age) VALUES('zs',25);
INSERT INTO T_Person1 (name) VALUES('zl');

表如下:

數據表圖

通過上面的了解我們就知道如何插入數據,并且設置字段了。

DML - 更新數據:

UPDATE T_Person1 SET name='qq';
執行這行語句后會發現所有的名字都變成了qq

更新多個字段

UPDATE T_Person1 set name='qq',age=20;

如圖:

更新數據之后

在上面的代碼中我們已經完成了對數據庫的更新,但是卻不是我們想要的結果,上面的是對整個數據庫都進行了更新,如果我們只想對某個數據更新改如何解決呢?后面會講到

DML-刪除:

DELETE FROM T_Person1;
執行完上面語句之后查看打印:
Affected rows : 4, Time: 0.00sec 影響了四行數據

然后我們再來看表

空空如也

這個時候我們就已經完成了對DML的學習,但是這些還不夠,比如我們更新數據的時候是對整個表進行更新,

刪除也是把整個表進行刪除,如果我們想對指定的數據進行操作,我們需要學習一個新的關鍵字:

WHERE 條件

WHERE

SQLite的 WHERE 子句用于指定從一個表或多個表中獲取數據的條件。

如果滿足給定的條件,即為真(true)時,則從表中返回特定的值。您可以使用 WHERE 子句來過濾記錄,只獲取需要的記錄。

SQLite的運算符有四種:算數、比較、邏輯以及位運算符

算數運算符:

+    加法 - 把運算符兩邊的值相加    a + b 將得到 30

  • 減法 - 左操作數減去右操作數 a - b 將得到 -10
  • 乘法 - 把運算符兩邊的值相乘 a * b 將得到 200 / 除法 - 左操作數除以右操作數 b / a 將得到 2 % 取模 - 左操作數除以右操作數后得到的余數 b % a will give 0</code></pre>

    比較運算符

    ==    檢查兩個操作數的值是否相等,如果相等則條件為真。    (a == b) 不為真。
    =    檢查兩個操作數的值是否相等,如果相等則條件為真。    (a = b) 不為真。
    !=    檢查兩個操作數的值是否相等,如果不相等則條件為真。    (a != b) 為真。
    <>    檢查兩個操作數的值是否相等,如果不相等則條件為真。    (a <> b) 為真。
    >    檢查左操作數的值是否大于右操作數的值,如果是則條件為真。    (a > b) 不為真。
    <    檢查左操作數的值是否小于右操作數的值,如果是則條件為真。    (a < b) 為真。
    =    檢查左操作數的值是否大于等于右操作數的值,如果是則條件為真。    (a >= b) 不為真。
    <=    檢查左操作數的值是否小于等于右操作數的值,如果是則條件為真。    (a <= b) 為真。
    !<    檢查左操作數的值是否不小于右操作數的值,如果是則條件為真。    (a !< b) 為假。
    !>    檢查左操作數的值是否不大于右操作數的值,如果是則條件為真。    (a !> b) 為真。

    邏輯運算符:

    AND        AND 運算符允許在一個 SQL 語句的 WHERE 子句中的多個條件的存在。
    BETWEEN    BETWEEN 運算符用于在給定最小值和最大值范圍內的一系列值中搜索值。
    EXISTS     EXISTS 運算符用于在滿足一定條件的指定表中搜索行的存在。
    IN         IN 運算符用于把某個值與一系列指定列表的值進行比較。
    NOT IN     IN 運算符的對立面,用于把某個值與不在一系列指定列表的值進行比較。
    LIKE       LIKE 運算符用于把某個值與使用通配符運算符的相似值進行比較。
    GLOB       GLOB 運算符用于把某個值與使用通配符運算符的相似值進行比較。GLOB 與 LIKE 不同之處在于,它是大小寫敏感的。
    NOT        NOT 運算符是所用的邏輯運算符的對立面。比如 NOT EXISTS、NOT BETWEEN、NOT IN,等等。**它是否定運算符。**
    OR         OR 運算符用于結合一個 SQL 語句的 WHERE 子句中的多個條件。
    IS NULL    NULL 運算符用于把某個值與 NULL 值進行比較。
    IS         IS 運算符與 = 相似。
    IS NOT     IS NOT 運算符與 != 相似。
    ||         連接兩個不同的字符串,得到一個新的字符串。
    UNIQUE     UNIQUE 運算符搜索指定表中的每一行,確保唯一性(無重復)。

    位運算符:

    & 與
    | 或
    p    q    p & q    p | q
    0    0    0        0
    0    1    0        1
    1    1    1        1
    1    0    0        1

    在了解了WHERE之后呢我們就可以對數據庫進行指定某條刪除、更新等操作了

    先向數據庫中 插入一些數據

    INSERT INTO T_Person1 (name,age) VALUES('aa',20);
    INSERT INTO T_Person1 (name,age) VALUES('bb',18);
    INSERT INTO T_Person1 (name,age) VALUES('cc',24);
    INSERT INTO T_Person1 (name,age) VALUES('dd',22);
    INSERT INTO T_Person1 (name,age) VALUES('ee',19);
    INSERT INTO T_Person1 (name,age) VALUES('ff',22);
    INSERT INTO T_Person1 (name,age) VALUES('gg',19);
    INSERT INTO T_Person1 (name,age) VALUES('hh',18);

    然后數據表中數據如下:

    數據圖

    DML-更新/刪除指定數據

    UPDATE 
    T_Person1 
    set 
    name='ff',age=20 
    WHERE 
    name='bb';

表示我要更新一個姓名叫做bb的人數據,并且把他的名字設置為qq、年齡設置為20歲 Affected rows : 1, Time: 0.00sec 提示已經影響了一條數據</code></pre>

此時查看表如下:

更新了之后

如果你足夠細心,你就發現了現在有兩個人名字都叫ff了,如果我現在只想對第一個姓名叫ff的人更新數據

我們可以這樣子寫:

UPDATE 
    T_Person1 
set 
    name='ee',age=19 
WHERE 
    name='ff' AND age=20;

然后表現在的數據如下:

更新數據之后

OK,通過上面的語句我們完成了只對第一個名字叫ff的人更新數據,但是現在我想對

第二個姓名為ee進行更新,就很尷尬了,數據庫中有兩個姓名都叫ee的并且年齡都是19歲,

到了這里我們定義id為唯一的作用就發揮出來了,此時我們只需要更新

指定id即可

UPDATE 
    T_Person1 
set 
    name='bb',age=28 
WHERE 
    id=9;

更新之后如圖:

更新之后

OK,通過上面的代碼我們就可以知道如何對指定的數據進行更新了,下面我們簡單的說下刪除指定數據.

DELETE FROM 
    T_Person1 
WHERE 
    name='gg';

如圖:

刪除之后

如果我想刪除多條數據呢?

比如刪除20歲以上的

DELETE FROM 
    T_Person1 
WHERE 
    age>20;

Affected rows : 4, Time: 0.00sec 影響了四行,應該是刪除了四行, 我們查看更新之后的表</code></pre>

表:

刪除之后

七、SQLite學習之DQL:

DQL(Data Query Language)數據查詢語言

關鍵字:Select,同時也是使用頻率最高的

查詢數據

SELECT 字段名,... FROM 表名;

先插入一下數據進去

INSERT INTO T_Person1 (name,age) VALUES('ab',28);
INSERT INTO T_Person1 (name,age) VALUES('hg',25);
INSERT INTO T_Person1 (name,age) VALUES('ab',24);
INSERT INTO T_Person1 (name,age) VALUES('df',22);
INSERT INTO T_Person1 (name,age) VALUES('fd',23);
INSERT INTO T_Person1 (name,age) VALUES('yt',28);
INSERT INTO T_Person1 (name,age) VALUES('oi',21);
INSERT INTO T_Person1 (name,age) VALUES('qw',33);
INSERT INTO T_Person1 (name,age) VALUES('gf',19);
INSERT INTO T_Person1 (name,age) VALUES('kl',18);
INSERT INTO T_Person1 (name,age) VALUES('lj',23);
INSERT INTO T_Person1 (name,age) VALUES('rt',25);
INSERT INTO T_Person1 (name,age) VALUES('tr',28);
INSERT INTO T_Person1 (name,age) VALUES('qw',26);
INSERT INTO T_Person1 (name,age) VALUES('xx',24);
INSERT INTO T_Person1 (name,age) VALUES('zx',25);
INSERT INTO T_Person1 (name,age) VALUES('mn',24);
INSERT INTO T_Person1 (name,age) VALUES('vb',25);

然后可以看到表數據如下:

數據表如圖

OK,在填充了數據之后,我們開始查找

SELECT * FROM T_Person1;
在這里*代表通配符,所有的字段

如圖:

查找之后

現在我們不想看到那么多數據,假設我們只顯示age

SELECT age FROM T_Person1;

如圖所示

單個字段

查詢多個字段: 這里字段的輸入順序就和顯示的列名數據一致

SELECT age,name FROM T_Person1;

如圖:

多個字段

OK,需求總是要變來變去的,這個時候我們想查詢年齡大于22歲的數據,并且顯示所有的信息

SELECT * FROM T_Person1 WHERE age>22;

如圖:

條件查詢

然后我們想找名字為ab的人,不要顯示id

SELECT name,age FROM T_Person1 WHERE name='ab';

如圖:

條件查詢二

如果你看到了這里,那么恭喜你,你已經知道了如何創建/刪除表,以及對表的增刪改查,同時還了解了WHERE條件語句,到這里基本上你已經可以自己管理數據庫了。

擴展知識 - 動態添加字段

繼續上面的表,這個時候老師分配任務啦,給每個人100塊的啟動資金,然后一個月后來查看他們是讓100塊變成了0塊還是變成了更多,這個時候上面就來話了,你給我添加一個字段進去,保存他們的金錢額度。

但是這個需求在項目開始之初是沒有考慮到的,這就比較坑爹了,原來的數據庫文件的內容不能刪除,又要新增一個字段……愁死我了。

方法有很多種,這里不作介紹了

只是來介紹一下動態添加字段這個方法

ALTER TABLE 表名 ADD 字段名 字段類型;

未插入字段之前的表:

未插入之前

插入一個字段:money

ALTER TABLE 
  T_Person1 
ADD 
  money real DEFAULT 100.0;

插入之后

OK,到這里完美解決了之前的問題

注意:再插入一個字段之前,講道理我們是要看下里面有沒有這個字段的

比如你正在上廁所,突然有個人就進來把你趕出去了,占了你的坑,此時的你肯定是在暴怒狀態,正常的應該是:先看下里面有沒有人,有人了就換一個,沒人然后在進去占一個坑……

所以我們需要判斷一下是不是可以插入這個字段

SQLITE_API const unsigned char *SQLITE_STDCALL sqlite3_column_text(sqlite3_stmt*, int iCol);

通過上面的方法會返回給我們一個C字符串數組判斷這個數組是不是有值,如果有了就不能插入了

為此我特地的又運行了一次

Error : duplicate column name: money
提示說有兩個都叫money的列了

擴展知識 - AS(起別名)

可以暫時把表或列重命名為另一個名字,這被稱為 別名 。使用表別名是指在一個特定的 SQLite 語句中重命名表。重命名是臨時的改變,在數據庫中實際的表的名稱不會改變。

列別名用來為某個特定的 SQLite 語句重命名表中的列。

比如:給字段起別名

SELECT 
  name as xingming,
  age as nianling 
FROM 
  T_Person1 
WHERE 
  age>25;

如圖:

字段別名

給表起別名:

SELECT 
one.name as one_name,
one.age as one_age 
FROM 
T_Person1 as one 
WHERE age>25;

如圖:

表別名

多表查詢:

先創建一個T_Person2表,然后插入一下數據

CREATE TABLE IF NOT EXISTS 
    T_Person2(
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    age INTEGER DEFAULT 20,
    money REAL DEFAULT 100.0
);

INSERT INTO T_Person2 (name,age) VALUES('asdf',28); INSERT INTO T_Person2 (name,age) VALUES('hsdfg',25); INSERT INTO T_Person2 (name,age) VALUES('afdfb',24); INSERT INTO T_Person2 (name,age) VALUES('dfasdf',22); INSERT INTO T_Person2 (name,age) VALUES('ffdfd',23); INSERT INTO T_Person2 (name,age) VALUES('yfdft',28); INSERT INTO T_Person2 (name,age) VALUES('ocvi',21); INSERT INTO T_Person2 (name,age) VALUES('qwvc',33); INSERT INTO T_Person2 (name,age) VALUES('gvcvf',19); INSERT INTO T_Person2 (name,age) VALUES('kcvcl',18); INSERT INTO T_Person2 (name,age) VALUES('lvj',23); INSERT INTO T_Person2 (name,age) VALUES('rvcdst',25); INSERT INTO T_Person2 (name,age) VALUES('tr43',28); INSERT INTO T_Person2 (name,age) VALUES('qwgh',26); INSERT INTO T_Person2 (name,age) VALUES('xgfdx',24); INSERT INTO T_Person2 (name,age) VALUES('hfgzx',25); INSERT INTO T_Person2 (name,age) VALUES('mgfhn',24); INSERT INTO T_Person2 (name,age) VALUES('vhgb',25);</code></pre>

這個時候,T_Person1里面有的字段T_Person2里面也有,就想兩個班級里面的字段

都有姓名,年齡等數據。

別名這個時候就可以很方便的區分

SELECT 
    one.name as one_name,
    one.age as one_age,
    two.name as two_name,
    two.age as two_age 
FROM 
    T_Person1 as one,
    T_Person2 as two 
WHERE 
    one.age>30 AND two.age>30;

如圖:

如圖

寫別名的方式還有一種,但是不推薦,直接加個空格

SELECT name xingming,age nianling 
FROM T_Person2;

如圖:

別名

擴展知識 - 排序

ORDER BY ,用于對數據進行排序

考慮這么一種情況,當你把數據信息輸入進去,而數據本身是雜亂無章的,這個時候你需要排序,比如:name、age字段來排序。

DESC : 降序

ASC:升序

單個字段排序

SELECT

* 

FROM T_Person2 ORDER BY age;</code></pre>

如圖:根據age升序

單個字段排序

多個字段排序

SELECT

* 

FROM T_Person2 ORDER BY name,age;</code></pre>

如圖:根據name升序,在根據age升序

多個字段排序

通過上面的語句我們發現在不寫明是什么排序的情況下默認是升序,也就是 ASC

通過寫上ASC來證明:

SELECT

* 

FROM T_Person2 ORDER BY name ASC,age ASC;</code></pre>

如圖:

下面根據age字段進行降序

SELECT 
    *
FROM
    T_Person2
ORDER BY
    age DESC;

如圖:

age降序

最后我們在實現一個根據name升序,age降序的

先別著急,因為我們數據庫中沒有相同姓名的,所以我們先插入兩條數據

插入數據

INSERT INTO T_Person1(name,age) VALUES('aa',18);
INSERT INTO T_Person1(name,age) VALUES('aa',19);

檢索

SELECT 
    *
FROM
    T_Person1
ORDER BY
    name ASC,age DESC;

如圖:

檢索如圖

擴展知識 - 數量

快速查詢有多少條數據或者查詢某個字段有多少條數據

SELECT COUNT(字段) FROM 表名;

查詢有多條數據:

SELECT COUNT(*) FROM T_Person1;

如圖

檢索

檢索 age 字段條數:

SELECT COUNT(age) FROM T_Person1;

age

擴展知識 - 分頁取數據

Limit 常用來對數據進行分頁,比如每頁固定顯示 n 條數據

SELECT 字段... FORM 表名 LIMIT a,b;
a:表示跳過多少條數據
b:從a之后開始取多少條數據

在網絡請求的時候我們經常可以向服務器說明,從哪一頁開始,取多少條,類似這樣子的操作很頻繁。

舉例:每頁取10條數據

  • 第1頁:... LIMIT 0,10;
  • 第2頁:... LIMIT 10,10;
  • 第3頁:... LIMIT 20,10;
  • ...
  • 第n頁:... LIMIT 10*(n-1),10;

    于是我們可以得出一個公式:

    m:每次取多少

    n:頁

    m*(n-1),m

注意:LIMIT 10 = LIMIT 0,10,兩個語句相等

代碼:取10條數據,從0開始

SELECT * FROM T_Person1 LIMIT 10;

如圖:

limit

如果我們數據庫中沒有那么多的情況下,就會把剩下的全部都取出來

比如: T_Person1 中我們只有 23 條數據,在上面檢索出來過

執行:

SELECT * FROM T_Person1 LIMIT 20,10;

如圖:

limit 20,10

OK,進一步增加難度,我要取得age>20的前面10條數據

SELECT * 
FROM T_Person1 
WHERE age>20 
LIMIT 10;

檢索age大于20的數據,取十條

然后我們在聯合排序提取數據:

SELECT *
FROM T_Person1
ORDER BY age DESC
LIMIT 10;

如圖

根據age進行排序(降序),取前面十條

對比查看數據是不是正確

對比

通過兩個圖比較,發現取出來的數據確實是正確的。

文中一些比較簡短的語句其實沒比較分行分的那么清楚,只是筆者為了能讓人閱讀起來更加方便,有寫筆者也沒有進行分行,不過閱讀起來應該還是比較簡單的。

OK,如果你堅持看完了,希望或多或少能給你帶來一些小小的幫助。

筆者寫這個也花了一點時間,如果能讓您復習或者有幸讓你更了解SQLite的話,就不枉費這些時間了。

最后厚著臉皮求個喜歡,那是我最大的動力。后面會更新如何在Swift3.0的中使用。

 

來自:http://www.jianshu.com/p/4bc34f982fee

 

 本文由用戶 KirstenGumm 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!