Skip to the content.

SQL簡介

SQL是結構化查詢語言Structured Query Language的縮寫

維基百科

這篇只針對SQLite喔,有些語法可能不適用

每次要用SQLite語法時都還要查老半天,應該是下次要用SQLite時已經不知道過了幾百年了,所以把常用的語法整理到這頁要找比較方便

SQLite官網

資料庫介紹

資料表(Table) 可以想像成是Microsoft Excel中的一張工作表。一張資料表會由許多「欄位」(Column)和「資料列」(Row)組成,用來儲存某一類型的資料

資料庫(Database) 通常會包含多張彼此有關聯的資料表

例如:購物網站可能會有的資料表會有

這些資料表組合起來,就能儲存和管理購物網站所需要的資料

主鍵(Primary key) 具有唯一性,是資料表中用來辨識每一筆資料的欄位

以上述購物網站的Users資料表為例,”會員編號”就可以作為主鍵的條件。不可重複且可辨識該使用者

因此主鍵有2個特性

外鍵(Foreign key) 是用來建立與其他資料表有關聯的欄位

以上述購物網站的Orders資料表為例,”訂購人”的欄位可以是對應User資料表中的”會員編號”,如此便把Orders資料表與Users資料表互相關聯

總結來說:

.NET環境安裝SQLite套件

Visual Studio

打開NuGet套件管理視窗

搜尋:SQLite

安裝「System.Data.SQLite」

其他還有像是System.Data.SQLite.Core、System.Data.SQLite.Linq的東西可以安裝

我目前還沒用到,所以就沒裝了

""

.NET指令環境(終端機、VSCode)

終端機進入到專案資料夾中

輸入指令:dotnet add package System.Data.SQLite

""

Nuget網頁

常用指令

SQLite也有資料庫管理軟體喔

SQLiteStudio有提供建立、刪除、修改等基本功能,因此就算不是寫程式也是可以用來儲存資料。另外也有SQL語法編輯器可使用SQL指令執行,就像是個輕便而且不用安裝的MySQL呢

SQLiteStudio下載

範例資料庫,點我下載

開啟SQL編輯器的方式如下圖

"開啟SQL編輯器的方式"

SQLite資料型態

建立資料表

CREATE TABLE MyTable (_AI INTEGER PRIMARY KEY AUTOINCREMENT,DateTime DATETIME,Topic TEXT,Message TEXT);

可以加上IF NOT EXISTS來判斷資料表是否存在,不存在才建立

CREATE TABLE IF NOT EXISTS MyTable (_AI INTEGER PRIMARY KEY AUTOINCREMENT,DateTime DATETIME,Topic TEXT,Message TEXT);

使用 CREATE TABLE 可以建立一個新的資料表。加上 IF NOT EXISTS 的判斷,可以確保只有在該表不存在時才會執行建立操作,避免重複建立相同名稱的資料表而導致錯誤

在上述SQL指令中:

建立表格的執行結果如下圖所示:

Image

UPDATE sqlite_sequence SET seq=0 WHERE NAME="MyTable"

此指令可設定AUTOINCREMENT的值(正常操作下不建議使用)

取得欄位資料

PRAGMA table_info('MyTable')

上述指令可以查詢在MyTable資料表內各欄位的資料

執行結果如下:

Image

插入資料

INSERT OR IGNORE INTO `MyTable` VALUES (NULL,DATETIME('NOW', 'LOCALTIME'),'Topic資料','Message資料')

使用INSERT將資料插入到MyTable的資料表中,並指定各個欄位的值。

在上述SQL指令中:

修改資料

UPDATE `MyTable`
SET `Topic` = '新的Topic值', `Message` = '新的Message值'
WHERE `AI` = 1

使用 UPDATE 修改資料表中的資料,並透過 SET 指定要修改的欄位和值。

在上述 SQL 指令中:

查詢資料

列出所有資料

SELECT * FROM "Mytable"

列出MyTable中所有資料

列出特定欄位

SELECT `Topic`,`Message` FROM `MyTable`

從MyTable中列出Topic及Message欄位的所有資料

SELECT的執行結果如下圖所示:

Image

加入條件搜尋

WHERE

SELECT * FROM 'MyTable' WHERE `Topic`='Run'

從MyTable中篩選出Topic欄位是’Run’的所有資料

SELECT-WHERE的執行結果如下圖所示:

Image

LIKE

SELECT * FROM 'MyTable' WHERE `Message` LIKE '%測試%'

從MyTable中篩選出Message欄位中的值包含”測試”的項目

在SQL中LIKE是模糊配對的操作,可以搜尋特定格式的資料,上述例子中的%是代表萬用字元,因此可以解讀為資料中包含”測試”的所有資料

題外話

SELECT-LIKE的執行結果如下圖所示:

Image

PL/SQL

最近工作開始使用PL/SQL,之後應該會常常用到。

同樣都是SQL一份子就不開新頁了,把工作上可能會用到的語法整理在這裡。畢竟久久沒用,幾百年後要用可能也忘了。我也懶惰再去四處查

簡介

PL/SQL是Procedural Language/SQL的縮寫,是Oracle所提供的一種程式語言,可以在SQL的基礎上加入變數、條件判斷、迴圈等程式語法,讓SQL不再只是下指令,而是可以依照自己的需求寫出一個可以執行的流程

維基百科

基本架構

PL/SQL與一般SQL相比,多了程式語言的架構

基本架構會是:

DECLARE
 // 定義變數
BEGIN
 // 程式內容
EXCEPTION
 // 例外處理
END;

命名區塊與匿名區塊

PL/SQL的程式區塊可以分為命名區塊(Named Block)與匿名區塊(Anonymous Block)

命名區塊

命名區塊是有名字的PL/SQL程式區塊,可以儲存在Oracle資料庫中,之後需要時再執行

常見的命名區塊:

Procedure

CREATE OR REPLACE PROCEDURE MyProgram
AS
BEGIN
 DBMS_OUTPUT.PUT_LINE('Hello PL/SQL');
END;

我定義了一支名叫”MyProgram”的程序,日後需要時便能直接呼叫它來執行

EXEC MyProgram

※ OR REPLACE表示如果不存在該程序就建立新的,存在就覆寫

Function

Function與Procedure最大的差別是在執行完畢後,會回傳一個值

CREATE OR REPLACE FUNCTION AddNumber(num1 NUMBER,num2 NUMBER)
RETURN NUMBER
AS
BEGIN
 RETURN num1 + num2;
END;

我定義了一支叫做AddNumber的Function,並傳入兩個數字num1和num2。RETURN NUMBER表示這個Function最後會回傳一個NUMBER型別的值

匿名區塊

逆名區塊就是沒有名字的PL/SQL程式區塊。通常是寫好就直接執行,執行完就結束,不會把這個程式區塊保存下來

通常是處理臨時性、一次性的資料,或是想快速執行一段PL/SQL就會使用匿名區塊

Label/GOTO

PL/SQL也支援Label與GOTO,可以透過Label指定一個標籤,再透過GOTO跳到該標籤的位置執行

BEGIN
 GOTO MyLabel;
 
 DBMS_OUTPUT.PUT_LINE('這行會被跳過');
 
 <<MyLabel>>
 DBMS_OUTPUT.PUT_LINE('跳到這裡');
END;

※不過這種寫法和其他程式語言一樣,如果大量使用GOTO讓程式到處跳轉,會讓程式的可讀性與可維護性變差

判斷

用來比較條件的結果,決定程式接下來應採取的行動,這種功能就稱為「判斷」。PL/SQL主要可以使用IF與CASE來進行判斷

IF

IF是基本條件的判斷

IF 條件 THEN
 // 條件為true時執行
END IF;

如果要加上不成立的狀況,則可增加ELSE區塊

IF 條件 THEN
 // 條件為true時執行
ELSE
 // 條件為false時執行
END IF;

如果需要多種條件判斷,則可使用ELSEIF

IF 條件1 THEN
 // 條件1true時執行
ELSEIF 條件2 THEN
 // 條件2true時執行
.
.
.
ELSE
 // 條件為false時執行
END IF;

CASE

CASE主要用於多選一的判斷,當有多種條件要判斷時,使用CASE會比巢狀IF更好閱讀。ChatGPT講的我不知道

CASE 條件
 WHEN (結果1) THEN
  // 條件與結果1相符時執行
 WHEN (結果2) THEN
  // 條件與結果2相符時執行
 WHEN (結果3) THEN
  // 條件與結果3相符時執行
.
.
.
 ELSE
  // 條件與所有結果都不相符時執行
END;

迴圈

一樣的事情重複做。PL/SQL常見的迴圈是LOOP、WHILE與FOR

LOOP

LOOP是最基本的迴圈,會一直重複執行,直到使用EXIT才會離開迴圈

LOOP
 // 要重複執行的程式

 EXIT WHEN 條件;
END LOOP;

※LOOP沒有終止條件,因此如果沒有使用EXIT會變成無窮迴圈

WHILE

WHILE也是迴圈的一種,但在每次重複執行前會判斷條件是否成立,成立才會繼續重複執行

WHILE 條件 LOOP
 // 要重複執行的程式
END LOOP;

FOR

FOR迴圈包含一個迴圈計數器,適合用在知道要執行幾次的情況。不過需要注意的是PL/SQL的迴圈計數器是由系統自己管理,而不是由程式設計師設計一個增加或減少的規則。

ChatGPT跟我補充,PL/SQL的是稱為 迴圈變數 (loop variable)而不像其他程式語言的 迴圈計數器 (loop counter),由於是系統自己管理迴圈變數的關係,PL/SQL中的FOR迴圈只支援遞增或遞減,無法像是其他語言使用i+=2之類的規則。

FOR 迴圈變數 IN 起始值 .. 結束值 LOOP
 // 要重複執行的程式
END LOOP;

游標(Cursor)

游標可以理解為”指向查詢結果中資料位置的指標”

通常使用SELECT查詢資料表時,可能會一次取出很多筆資料,如果要一筆一筆處理資料便可使用游標。使用游標前後要透過OPEN與CLOSE進行開關,再搭配FETCH讀取出一筆一筆的資料(我對游標的機制的感覺像是C#的foreach)

DECLARE
 CURSOR MyCursor IS
  SELECT Topic,Message
  FROM MyTable;
BEGIN
 FOR logData IN MyCursor LOOP
  DBMS_OUTPUT.PUT_LINE(logData.Topic);
 END LOOP;
END

※使用FOR迴圈搭配游標時,OPEN、FETCH和CLOSE會由系統自動處理,不需要自己寫

對照一下C#的foreach

foreach(var logData in MyCursor)
{
    Debug.WriteLine(logData.Topic);
}

PL/SQL分為隱含游標(Implicit Cursor)與明確游標(Explicit Cursor)

明確游標 即是由使用者自行宣告與管理的游標(上述例子中的MyCursor)

隱含游標 則是由PL/SQL系統中自動建立與管理的游標。平時執行INSERT、UPDATE、DELETE或SELECT INTO時,即使沒有宣告游標,系統仍會在背後使用游標進行處理

與SQLite語法差異

SELECT

INSERT

PRIMARY KEY

取得時間