1. 程式人生 > >Sqlite中sql高階用法整理

Sqlite中sql高階用法整理

一、主鍵約束

PRIMARY KEY 約束唯一標識資料庫表中的每個記錄。

  • 在一個表中可以有多個 UNIQUE 列,但只能有一個主鍵。

  • 在設計資料庫表時,主鍵是很重要的。主鍵是唯一的 ID。
    我們使用主鍵來引用表中的行。

  • 可通過把主鍵設定為其他表的外來鍵,來建立表之間的關係。

  • 由於”長期存在編碼監督”,在 SQLite 中 主鍵值 可 以是 NULLL,這是與其他資料庫不同的地方。NULL 與沒有數 據是不一樣的,它代表著未知的資料。

  • 一個表只能有一個主鍵,它可以由一個或多個欄位組成。當多個欄位作為主鍵,它們被稱為複合鍵。
  • 如果一個表在任何欄位上定義了一個主鍵,那麼在這些欄位上不能有兩個記錄具有相同的值。

==注意:在做排序操作時,升序NULL排最前面,降序NULL排最後面。==

二、ALTER TABLE 語句

ALTER TABLE 語句用於在已有的表中新增、修改或刪除列。

SQL ALTER TABLE 語法如下:

如需在表中新增列,請使用下列語法:

ALTER TABLE table_name
ADD column_name datatype

要刪除表中的列,請使用下列語法:

ALTER TABLE table_name 
DROP COLUMN column_name

註釋:某些資料庫系統不允許這種在資料庫表中刪除列的方式 (DROP COLUMN column_name)。SQLite 支援 ALTER TABLE 的有限子集。在 SQLite 中,ALTER TABLE 命令允許使用者重命名錶,或向現有表新增一個新的列。重新命名列,刪除一列,或從一個表中新增或刪除約束都是不可能的。

要改變表中列的資料型別,請使用下列語法:

ALTER TABLE table_name
ALTER COLUMN column_name datatype

三、連線

SQL 定義了三種主要型別的連線:

  • 交叉連線 - CROSS JOIN
  • 內連線 - INNER JOIN
  • 外連線 - OUTER JOIN

1.交叉連線

  交叉連線(CROSS JOIN)把第一個表的每一行與第二個表的每一行進行匹配。如果兩個輸入表分別有 x 和 y 列,則結果表有 x+y 列。由於交叉連線(CROSS JOIN)有可能產生非常大的表,使用時必須謹慎,只在適當的時候使用它們。

下面是交叉連線(CROSS JOIN)的語法:

SELECT ... FROM table1 CROSS JOIN table2 ...

2.內連線

  內連線(INNER JOIN)根據連線謂詞結合兩個表(table1 和 table2)的列值來建立一個新的結果表。查詢會把 table1 中的每一行與 table2 中的每一行進行比較,找到所有滿足連線謂詞的行的匹配對。當滿足連線謂詞時,A 和 B 行的每個匹配對的列值會合併成一個結果行。
  內連線(INNER JOIN)是最常見的連線型別,是預設的連線型別。INNER 關鍵字是可選的。
  
下面是內連線(INNER JOIN)的語法:

SELECT ... FROM table1 [INNER] JOIN table2 ON conditional_expression ...

為了避免冗餘,並保持較短的措辭,可以使用 USING 表示式宣告內連線(INNER JOIN)條件。這個表示式指定一個或多個列的列表:

SELECT ... FROM table1 JOIN table2 USING ( column1 ,...)...

  自然連線(NATURAL JOIN)類似於 JOIN…USING只是它會自動測試存在兩個表中的每一列的值之間相等值:

SELECT ... FROM table1 NATURAL JOIN table2...

3.外連線(難點)

  外連線(OUTER JOIN)是內連線(INNER JOIN)的擴充套件。雖然 SQL 標準定義了三種類型的外連線:LEFT、RIGHT、FULL,但 SQLite 只支援 左外連線(LEFT OUTER JOIN)。
  外連線(OUTER JOIN)宣告條件的方法與內連線(INNER JOIN)是相同的,使用 ON、USING 或 NATURAL 關鍵字來表達。最初的結果表以相同的方式進行計算。一旦主連線計算完成,如果左表的某行在右表中沒有匹配行,則在相關聯的結果集行中右表的所有選擇列表列均為空值。 這裡這麼說,可能不是很好理解,我們先看看做外連線的語法,接著看一個例項幫助理解。
  
下面是左外連線(LEFT OUTER JOIN)的語法:

SELECT ... FROM table1 LEFT OUTER JOIN table2 ON conditional_expression ...

下面看一個具體的例子:

a表 :

id name
1 張三
2 李四
3 王五

b表:

id job parent_id
1 23 1
2 34 2
3 34 4

查詢語句:

select   a.*,b.*   from   a   left   join   b     on   a.id=b.parent_id`  

結果為:

a.id a.name b.id b.job b.parent_id`
1 張三 1 23 1
2 李四 2 34 2
3 王武

四、觸發器(Trigger)

  SQLite 的觸發器是資料庫的回撥函式,它會自動執行/指定的資料庫事件發生時呼叫。
  它會在指定的資料庫事件發生時自動執行/呼叫。以下是關於 SQLite 的觸發器(Trigger)的要點:
  

  • SQLite 的觸發器(Trigger)可以指定在特定的資料庫表發生 DELETE、INSERT 或 UPDATE時觸發,或在一個或多個指定表的列發生更新時觸發。

  • SQLite 只支援 FOR EACH ROW 觸發器(Trigger),沒有 FOR EACH STATEMENT觸發器(Trigger)。因此,明確指定 FOR EACH ROW 是可選的。

  • WHEN 子句和觸發器(Trigger)動作可能訪問使用表單 NEW.column-name 和 OLD.column-name的引用插入、刪除或更新的行元素,其中 column-name 是從與觸發器關聯的表的列的名稱。

NEW 與 OLD 詳解
NEW 和 OLD用來表示觸發器的所在表中,觸發了觸發器的那一行資料。
具體地:
在 INSERT 型觸發器中,NEW 用來表示將要(BEFORE)或已經(AFTER)插入的新資料;
在 UPDATE 型觸發器中,OLD 用來表示將要或已經被修改的原資料,NEW 用來表示將要或已經修改為的新資料;
在 DELETE 型觸發器中,OLD 用來表示將要或已經被刪除的原資料;
使用方法: NEW.columnName (columnName 為相應資料表某一列名)
另外,OLD 是隻讀的,而 NEW 則可以在觸發器中使用 SET 賦值,這樣不會再次觸發觸發器,造成迴圈呼叫(如每插入一個學生前,都在其學號前加“2013”)。

  • 如果提供 WHEN 子句,則只針對 WHEN 子句為真的指定行執行 SQL 語句。如果沒有提供 WHEN 子句,則針對所有行執行 SQL 語句。

  • BEFORE 或 AFTER 關鍵字決定何時執行觸發器動作,決定是在關聯行的插入、修改或刪除之前或者之後執行觸發器動作。

  • 當觸發器相關聯的表刪除時,自動刪除觸發器(Trigger)。

  • 要修改的表必須存在於同一資料庫中,作為觸發器被附加的表或檢視,且必須只使用 tablename,而不是database.tablename。

  • 一個特殊的 SQL 函式 RAISE() 可用於觸發器程式內丟擲異常。
    建立 觸發器(Trigger) 的基本語法如下:
CREATE OR REPLACE TRIGGER TG_NAME

  BEFORE | AFTER

  INSERT OR DELETE OR UPDATE [OF COL1,COL2,...]

  ON 表名

  [FOR EACH ROW]

  [WHEN 條件]

  DECLARE

  ...

  BEGIN

  ....

  EXCEPTION

  ...

  END;

註釋: A) FOR EACH ROW 代表行級觸發器.

  B) WHEN: 只有符合該條件的時候才進行觸發.

  C) 可以通過INSERTING,DELETING,UPDATING來識別INSERT,DELETE,UPDATE操作.

  D) 用new 和old(稱為偽記錄)來訪問資料變更前後的值。

  E) 觸發器中的操作與觸發事件(INSERT,UPDATE,DELETE)一起進行COMMIT和ROLLBACK;

以下是在 UPDATE 操作上在表的一個或多個指定列上建立觸發器(Trigger)的語法:

CREATE  TRIGGER trigger_name [BEFORE|AFTER] UPDATE OF column_name 
ON table_name
BEGIN
 -- Trigger logic goes here....
END;

例項

  讓我們假設一個情況,我們要為被插入到新建立的 COMPANY 表(如果已經存在,則刪除重新建立)中的每一個記錄保持審計試驗:

sqlite> CREATE TABLE COMPANY(
   ID INT PRIMARY KEY     NOT NULL,
   NAME           TEXT    NOT NULL,
   AGE            INT     NOT NULL,
   ADDRESS        CHAR(50),
   SALARY         REAL
);

  為了保持審計試驗,我們將建立一個名為 AUDIT 的新表。每當 COMPANY 表中有一個新的記錄項時,日誌訊息將被插入其中:

sqlite> CREATE TABLE AUDIT(
    EMP_ID INT NOT NULL,
    ENTRY_DATE TEXT NOT NULL
);

  在這裡,ID 是 AUDIT 記錄的 ID,EMP_ID 是來自 COMPANY 表的 ID,DATE 將保持 COMPANY 中記錄被建立時的時間戳。所以,現在讓我們在 COMPANY 表上建立一個觸發器,如下所示:

sqlite> CREATE TRIGGER audit_log AFTER INSERT 
ON COMPANY
BEGIN
   INSERT INTO AUDIT(EMP_ID, ENTRY_DATE) VALUES (new.ID, datetime('now'));
END;

五、檢視(View)

  檢視(View)只不過是通過相關的名稱儲存在資料庫中的一個 SQLite 語句。檢視(View)實際上是一個以預定義的 SQLite 查詢形式存在的表的組合。

  • 檢視(View)可以包含一個表的所有行或從一個或多個表選定行。
  • 檢視(View)可以從一個或多個表建立,這取決於要建立檢視的 SQLite 查詢。
  • 檢視(View)是一種虛表,允許使用者實現以下幾點:
    1. 使用者或使用者組查詢結構資料的方式更自然或直觀。
    2. 限制資料訪問,使用者只能看到有限的資料,而不是完整的表。
    3. 彙總各種表中的資料,用於生成報告。
    4. SQLite 檢視是隻讀的,因此可能無法在檢視上執行 DELETE、INSERT 或 UPDATE 語句。但是可以在檢視上建立一個觸發器,當嘗試 DELETE、INSERT 或 UPDATE 檢視時觸發,需要做的動作在觸發器內容中定義。

建立檢視:

  SQLite 的檢視是使用 CREATE VIEW 語句建立的。SQLite 檢視可以從一個單一的表、多個表或其他檢視建立。
  CREATE VIEW 的基本語法如下:

CREATE [TEMP | TEMPORARY] VIEW view_name AS
SELECT column1, column2.....
FROM table_name
WHERE [condition];

  您可以在 SELECT 語句中包含多個表,這與在正常的 SQL SELECT 查詢中的方式非常相似。如果使用了可選的 TEMP 或 TEMPORARY 關鍵字,則將在臨時資料庫中建立檢視。

sqlite記憶體資料庫、臨時資料庫

  • 記憶體資料庫: 在SQLite中,資料庫通常是儲存在磁碟檔案中的。然而在有些情況下,我們可以讓資料庫始終駐留在記憶體中。在建立並開啟資料庫後,不會有任何磁碟檔案被生成,取而代之的是,一個新的資料庫在純記憶體中被成功建立了。由於沒有持久化,該資料庫在當前資料庫連線被關閉後就會立刻消失。
  • 臨時資料庫: 和記憶體資料庫一樣,在連線關閉後,臨時資料庫將自動消失,其底層檔案也將被自動刪除。儘管磁碟檔案被建立用於儲存臨時資料庫中的資料資訊,但是實際上臨時資料庫也會和記憶體資料庫一樣通常駐留在記憶體中,唯一不同的是,當臨時資料庫中資料量過大時,SQLite為了保證有更多的記憶體可用於其它操作,因此會將臨時資料庫中的部分資料寫到磁碟檔案中,而記憶體資料庫則始終會將資料存放在記憶體中。

六、索引(Index)

  索引(Index)是一種特殊的查詢表,資料庫搜尋引擎用來加快資料檢索。簡單地說,索引是一個指向表中資料的指標。一個數據庫中的索引與一本書後邊的索引是非常相似的。
   引有助於加快 SELECT 查詢和 WHERE 子句,但它會減慢使用 UPDATE 和 INSERT 語句時的資料輸入。索引可以建立或刪除,但不會影響資料。
  使用 CREATE INDEX 語句建立索引,它允許命名索引,指定表及要索引的一列或多列,並指示索引是升序排列還是降序排列。
  索引也可以是唯一的,與 UNIQUE 約束類似,在列上或列組合上防止重複條目。
CREATE INDEX 基本命令:

CREATE INDEX index_name ON table_name;

1.單列索引

單列索引是一個只基於表的一個列上建立的索引。基本語法如下:

CREATE INDEX index_name
ON table_name (column_name);

2.唯一索引

  唯一性索引,該索引規則和資料表的唯一性約束的規則相同,即NULL和任何值都不同,包括NULL本身。

  使用唯一索引不僅是為了效能,同時也為了資料的完整性。唯一索引不允許任何重複的值插入到表中。基本語法如下:

CREATE UNIQUE INDEX index_name
on table_name (column_name);

3.組合索引

  組合索引是基於一個表的兩個或多個列上建立的索引。基本語法如下:

CREATE INDEX index_name
on table_name (column1, column2);

  是否要建立一個單列索引還是組合索引,要考慮到您在作為查詢過濾條件的 WHERE 子句中使用非常頻繁的列。如果值使用到一個列,則選擇使用單列索引。如果在作為過濾的 WHERE 子句中有兩個或多個列經常使用,則選擇使用組合索引。

4.隱式索引

  隱式索引是在建立物件時,由資料庫伺服器自動建立的索引。索引自動建立為主鍵約束和唯一約束。

5.DROP INDEX 命令

  一個索引可以使用 SQLite 的 DROP 命令刪除。當刪除索引時應特別注意,因為效能可能會下降或提高。
基本語法如下:

DROP INDEX index_name;

6.什麼情況下要避免使用索引?

  雖然索引的目的在於提高資料庫的效能,但這裡有幾個情況需要避免使用索引。使用索引時,應重新考慮下列準則:
索引不應該使用在較小的表上。
索引不應該使用在有頻繁的大批量的更新或插入操作的表上。
索引不應該使用在含有大量的 NULL 值的列上。
索引不應該使用在頻繁操作的列上。

批註:
在表被刪除的時候,表上附著的觸發器、索引會被刪除,而檢視則不會被刪除