Oracle PL/SQL 入門

正則表達式

字符類別

類別 描述
\d 任意數字(等同于[0-9])
\D 任意非數字字符(等同于[^0-9])
\w 任意字母或數字(等同于[a-zA-Z0-9])
\W 任意非字母或數字字符(等同于[^a-zA-Z0-9])
\s 任意空白字符
\S 任意非空白字符

重復元字符

元字符 描述
* 0個或多個匹配
+ 1個或多個匹配(等價于{1,})
? 0個或1個匹配(等價于{0,1})
{n} 具體的匹配次數
{n,} 不少于指定的匹配次數
{n,m} 匹配的范圍

錨元字符

描述
^ 文本的開頭
$ 文本的末尾

^有兩種用法:在字符集內(使用[和]定義),使用它來對字符集取反;否則,將把它用于指示字符串的開頭。

/* SELECT prod_name, vend_id
FROM products; */

SELECT DISTINCT vend_id -- DISTINCT 關鍵字用法
FROM products;

SELECT prod_id, prod_price, prod_name
FROM products
ORDER BY prod_price DESC;

SELECT prod_name, prod_price
FROM products
WHERE prod_price BETWEEN 5 AND 10
ORDER BY prod_name;

SELECT prod_name, prod_price
FROM products
WHERE vend_id = 1002 OR vend_id = 1003
ORDER BY prod_name;

SELECT prod_name, prod_price
FROM products
-- WHERE (vend_id = 1002 OR vend_id = 1003) AND prod_price >= 10
WHERE vend_id IN (1002,1003) AND prod_price >= 10 -- 可以使用IN
ORDER BY prod_name;

SELECT prod_id, prod_name
FROM products
WHERE prod_name LIKE '_ ton anvil%';

SELECT prod_name
FROM products
WHERE REGEXP_LIKE (prod_name, '.000') -- 正則函數
ORDER BY prod_name;

SELECT prod_name
FROM products
WHERE REGEXP_LIKE(prod_name, '1000|2000|3000')
ORDER BY prod_name;

SELECT prod_name
FROM products
WHERE REGEXP_LIKE(prod_name,'[1-5] ton')
ORDER BY prod_name;

SELECT vend_name
FROM vendors
WHERE REGEXP_LIKE(vend_name, '\.'); -- 用轉義符"\"搜索"."

SELECT prod_name
FROM products
-- WHERE REGEXP_LIKE(prod_name, '\(\d sticks?\)')
WHERE REGEXP_LIKE(prod_name, '\d{4}')
ORDER BY prod_name;

常用文本操作函數

函數 描述
Length() 返回字符串的長度
Lower() 把字符串轉換成小寫形式
LPad() 在字符串左邊填充空格
LTrim() 從字符串左邊修剪掉空白
RPad() 在字符串右邊填充空格
RTrim() 從字符串右邊修剪掉空白
Soundex() 返回字符串的SOUNDEX值
SubString() 返回字符串內的字符
Upper() 把字符串轉換成大寫形式

常用的日期和時間操作函數

函數 描述
Add_Month() 給日期添加月份(也可以減去月份)
Extract() 從日期和時間中減去年、月、日、時、分或秒
Last_Day() 返回月份的最后一天
Months_Between() 返回兩個月份之間的月數
Next_Day() 返回指定日期后面的那一天
Sysdate() 返回當前日期和時間
To_Date() 把字符串轉換成日期

常用的數值操作函數

函數 描述
Abs() 返回數字的絕對值
Cos() 返回指定角度的三角余弦值
Exp() 返回指定數字的指數值
Mod() 返回除法運算的余數
Sin() 返回指定角度的三角正弦值
Sqrt() 返回指定數字的平方根
Tan() 返回指定角度的三角正切值

SQL聚合函數

函數 描述
AVG() 返回列的平均值
COUNT() 返回列中的行數
MAX() 返回列的最大值
MIN() 返回列的最小值
SUM() 返回列的值匯總
  • 可以使用COUNT()的兩種方式是:

    • 使用COUNT(*)統計表中的行數,無論列包含的是數值還是NULL值;
    • 使用COUNT(column)統計在特定列中具有值(忽略NULL值)的行數。
  • GROUP BY子句必須出現在WHERE子句的后面和ORDER BY子句的前面。

  • HAVING與WHERE的區別:
    WHERE過濾發生在數據分組之前,而HAVING過濾則發生在數據分組之后。這是一個重要的區別,被WHERE子句刪除的行不會包括在分組中。這可能會改變計算值,基于HAVING子句中使用的那些值,它反過來又可能影響哪些分組將會被過濾。

ORDER BY與GROUP BY的比較

ORDER BY GROUP BY
對生成的輸出進行排序 對行進行分組,不過輸出可能沒有采用分組順序
可能使用任意列(甚至包括沒有選擇的列) 只可能使用所選的列或表達式列,并且一定會使用所有選擇的列表達式
從來都不是必需的 如果結合使用列(或表達式)與聚合函數,則是必需的

SELECT子句和它們的順序

子句 描述 是否必需
SELECT 要返回的列或表達式
FROM 要從中檢索數據的表 是(Oracle)
WHERE 行級過濾
GROUP BY 分組規范 僅當按分組計算聚合值時是必需的
HAVING 分組級過濾
ORDER BY 輸出的排列順序

查詢示例

SELECT RTRIM(vend_name) || ',(' || RTRIM(vend_country) || ')'
AS vend_title
FROM vendors
ORDER BY vend_name;

SELECT prod_id, quantity, item_price,
       quantity * item_price AS expanded_price
FROM orderitems
WHERE order_num = 20005;

SELECT cust_id, order_num
FROM orders
WHERE order_date = TO_DATE('2015-02-01', 'yyyy-mm-dd');
SELECT cust_id, order_num
FROM orders
WHERE order_date>= TO_DATE('2015-02-01', 'yyyy-mm-dd')
   AND order_date< TO_DATE('2015-02-02', 'yyyy-mm-dd');
   
SELECT cust_id, order_num
FROM orders
-- 檢索order_date在2015年和2月的所有行
WHERE Extract(Year FROM order_date) = 2015
   AND Extract(Month FROM order_date) = 2;
   
SELECT AVG(prod_price) AS avg_price
FROM products
WHERE vend_id = 1003;

SELECT COUNT(*) AS num_cust
FROM customers;

SELECT COUNT(cust_email) AS num_cust
FROM customers;

SELECT SUM(quantity) AS items_ordered
FROM orderitems
WHERE order_num = 20005;

SELECT SUM(item_price*quantity) AS total_price
FROM orderitems
WHERE order_num = 20005;

SELECT COUNT(*) AS num_items,
       MIN(prod_price) AS price_min,
       MAX(prod_price) AS price_max,
       AVG(prod_price) AS price_avg
FROM products;

SELECT vend_id, COUNT(*) AS num_prods 
FROM products
GROUP BY vend_id; -- GROUP BY 聚合分組

SELECT cust_id, COUNT(*) AS orders
FROM orders
GROUP BY cust_id
HAVING COUNT(*) >= 2; -- HAVING用于過濾分組 等同于過濾行的 WHERE

/* 列出具有2件或更多產品并且價格在10以上(含10)的所有供應商 */
SELECT vend_id, COUNT(*) AS num_prods
FROM products
WHERE prod_price >= 10
GROUP BY vend_id
HAVING COUNT(*) >= 2;

/* 檢索總價在50以上(含50)的所有訂單的訂單號和訂單總價,并按訂單總價對輸出進行排序 */
SELECT order_num, SUM(quantity * item_price) AS order_total
FROM orderitems
GROUP BY order_num
HAVING SUM(quantity * item_price) >= 50
ORDER BY order_total;

/* 子查詢:查詢訂購商品TNT2的所有顧客的信息,下面有連接表方法查詢 */
SELECT cust_name, cust_contact
FROM customers
WHERE cust_id IN (SELECT cust_id
                  FROM orders
                  WHERE order_num IN (SELECT order_num
                                      FROM orderitems
                                      WHERE prod_id = 'TNT2'));

SELECT cust_name,
       cust_state,
       (SELECT COUNT(*)
       FROM orders
       WHERE orders.cust_id = customers.cust_id) AS orders -- orders為計算字段
FROM customers
ORDER BY cust_name;

/* 表的連接,必須使用完全限定的列名(用點號把表和列分隔開) */
SELECT vend_name, prod_name, prod_price
FROM vendors, products
WHERE vendors.vend_id = products.vend_id
ORDER BY vend_name, prod_name;
-- 等同于下面的內連接,WHERE更簡化,INNER更清晰
SELECT vend_name, prod_name, prod_price
FROM vendors INNER JOIN products
ON vendors.vend_id = products.vend_id
ORDER BY vend_name, prod_name;

-- 顯示了訂單號20005中的商品
SELECT prod_name, vend_name, prod_price, quantity
FROM orderitems, products, vendors
WHERE products.vend_id = vendors.vend_id
   AND orderitems.prod_id = products.prod_id
   AND order_num = 20005;

/* 使用連接表:查詢訂購商品TNT2的所有顧客的信息,上面有子查詢方法 */
-- WHERE連接表
SELECT cust_name, cust_contact
FROM customers, orders, orderitems
WHERE customers.cust_id = orders.cust_id
   AND orderitems.order_num = orders.order_num
   AND prod_id = 'TNT2';
-- FROM子句,INNER JOIN ON實現
SELECT cust_name, cust_contact
FROM customers
INNER JOIN orders ON customers.cust_id = orders.cust_id
INNER JOIN orderitems ON orderitems.order_num = orders.order_num
WHERE prod_id = 'TNT2';

表別名和列別名

列別名使用 AS:

SELECT RTrim(vend_name) || ', (' || RTrim(vend_country) || ')'
  AS vend_title
FROM vendors
ORDER BY vend_name;

表別名如下:

SELECT cust_name, cust_contact
FROM customers c, orders o, orderitems oi
WHERE c.cust_id = o.cust_id
  AND oi.order_num = o.order_num
  AND prod_id = 'TNT2';

注意:只在查詢執行期間使用表別名。與列別名不同,表別名永遠不會返回給客戶。

/* 查詢商品ID為DTNTR的商品的同一個供應商制造的所有產品 */
-- 子查詢方法
SELECT prod_id, prod_name 
FROM products
WHERE vend_id = (SELECT vend_id
                 FROM products
                 WHERE prod_id = 'DTNTR')
ORDER BY prod_id;
/* 自連接 */
-- 連接表 WHERE
SELECT p1.prod_id, p1.prod_name
FROM products p1, products p2
WHERE p1.vend_id = p2.vend_id
    AND p2.prod_id = 'DTNTR'
ORDER BY prod_id;
-- 連接表 INNER JOIN ON
SELECT p1.prod_id, p1.prod_name
FROM products p1
INNER JOIN products p2 ON p1.vend_id = p2.vend_id
WHERE p2.prod_id = 'DTNTR'
ORDER BY prod_id;

/* 自然連接 */
SELECT c.*, o.order_num, o.order_date,   -- c.*為customers表中所有列
            oi.prod_id, oi.quantity, OI.item_price
FROM customers c, orders o, orderitems oi
WHERE c.cust_id = o.cust_id
   AND oi.order_num = o.order_num
   AND prod_id = 'FB';
   
SELECT c.*, o.order_num, o.order_date,
            oi.prod_id, oi.quantity, OI.item_price
FROM customers c
INNER JOIN orders o ON c.cust_id = o.cust_id
INNER JOIN orderitems oi ON oi.order_num = o.order_num
WHERE prod_id = 'FB';   

/* 外連接:檢索所有顧客及其訂單 */
SELECT c.cust_id, o.order_num
FROM customers c
INNER JOIN orders o ON c.cust_id = o.cust_id;
-- 檢索所有顧客的列表,包括那些沒有下訂單的顧客
SELECT customers.cust_id, orders.order_num
FROM customers
LEFT OUTER JOIN orders ON customers.cust_id = orders.cust_id;

與將兩個表中的行相關聯的內連接不同,外連接還包括沒有相關行的行。
當使用OUTER JOIN語法時,必須使用RIGHT或LEFT關鍵字指定要包括所有行的表(RIGHT用于OUTER JOIN右邊的表,LEFT則用于左邊的表)。前面的示例在FROM子句中使用LEFT OUTER JOIN從左邊的表(customers表)中選擇所有的行。要從右邊的表中選擇所有的行,可以使用RIGHT OUTER JOIN

外連接類型:
有兩種基本的外連接形式:左外連接和右外連接,它們之間的唯一區別是相關聯的表的順序。換句話說,可以把左外連接轉變成右外連接,只需在FROM或WHERE子句中顛倒表的順序即可。因此,可以互換地使用兩類外連接,而要使用哪種外連接則取決于方便性。

/* 檢查所有顧客的列表以及每位顧客下的訂單數量 */
-- 內連接
SELECT customers.cust_name,
       COUNT(orders.order_num) AS num_ord
FROM customers
INNER JOIN orders ON customers.cust_id = orders.cust_id
GROUP BY customers.cust_name;
-- 外連接
SELECT customers.cust_name,
       COUNT(orders.order_num) AS num_ord
FROM customers
LEFT OUTER JOIN orders ON customers.cust_id = orders.cust_id
GROUP BY customers.cust_name;

/* 組合查詢 UNION */
/* 價格在5以下的所有產品,包括由供應商1001和1002制造的所有產品,不管價格 */
SELECT vend_id, prod_id, prod_price
FROM products
WHERE prod_price <= 5
UNION
SELECT vend_id, prod_id, prod_price
FROM products
WHERE vend_id IN (1001,1002)
ORDER BY vend_id, prod_price;

SELECT vend_id, prod_id, prod_price
FROM products
WHERE prod_price <= 5
  OR vend_id IN (1001,1002);

使用UNION ALL,Oracle將不會消除重復的行。

INSERT 插入的用法

/* INSERT語句用法示例 */
-- 下面是依賴列順序的,強烈不推薦
INSERT INTO Customers
VALUES(10006,
       'Pep E. LaPew',
       '100 Main Street',
       'Los Angeles',
       'CA',
       '90046',
       'USA',
       NULL,
       NULL);
-- 推薦寫法
INSERT INTO customers(cust_id,
                      cust_name,
                      cust_address,
                      cust_city,
                      cust_state,
                      cust_zip,
                      cust_country)
VALUES(10006,
       'Pep E. LaPew',
       '100 Main Street',
       'Los Angeles',
       'CA',
       '90046',
       'USA');
       
       
-- 使用INSERT SELECT把custnew中的所有數據導入到customers中       
INSERT INTO custnew(cust_id,
                    cust_contact,
                    cust_email,
                    cust_name,
                    cust_address,
                    cust_city,
                    cust_state,
                    cust_zip,
                    cust_country)
SELECT cust_id,
       cust_contact,
       cust_email,
       cust_name,
       cust_address,
       cust_city,
       cust_state,
       cust_zip,
       cust_country
FROM custnew;

UPDATE更新數據

-- 更新顧客10005的電子郵件
UPDATE customers
SET cust_email = 'elmer@fudd.com'
WHERE cust_id = 10005;

-- 更新多列數據
UPDATE customers
SET cust_name = 'The Fudds',
    cust_email = 'elmer@fudd.com'
WHERE cust_id = 10005;

-- 更新為空值(刪除列)
UPDATE customers
SET cust_email = NULL
WHERE cust_id = 10005;

UPDATE語句需要結束于一個WHERE子句,它告訴Oracle要更新哪一行,否則更新所有行。

DELETE刪除數據的使用

-- 從customers表中刪除單獨一行
DELETE FROM customers
WHERE cust_id = 10006;

DELETE不接受列名或者通配符,它將刪除整行,而不是刪除列。要刪除特定的列,可以使用UPDATE語句。
永遠不要執行不帶有WHERE子句的UPDATE或DELETE,除非確實打算更新和刪除每一行。

創建表

---------------------------------------------
-- Create customers table
---------------------------------------------
CREATE TABLE customers
(
  cust_id   int      NOT NULL ,
  cust_name char(50) NOT NULL ,
  cust_address char(50)  NULL ,
  cust_city    char(50)  NULL ,
  cust_state   char(5)   NULL ,
  cust_zip     char(10)  NULL ,
  cust_country char(50)  NULL ,
  cust_contact char(50)  NULL ,
  cust_email   char(255) NULL
);


---------------------------------------------
-- Create orderitems table
---------------------------------------------
CREATE TABLE orderitems
(
  order_num  int          NOT NULL ,
  order_item int          NOT NULL ,
  prod_id    char(10)     NOT NULL ,
  quantity   int          DEFAULT 1 NOT NULL , -- 設置默認值
  item_price decimal(8,2) NOT NULL
);

ALTER TABLE更新表定義

-- 向表中添加一列
ALTER TABLE vendors
ADD vend_phone CHAR(20);

-- 刪除添加列
ALTER TABLE vendors
DROP COLUMN vend_phone;

-- 定義主鍵
----------------------
-- Define primary keys
----------------------
ALTER TABLE customers ADD CONSTRAINT pk_customers
                      PRIMARY KEY (cust_id);
ALTER TABLE orderitems ADD CONSTRAINT pk_orderitems
                       PRIMARY KEY (order_num, order_item);
ALTER TABLE orders ADD CONSTRAINT pk_orders
                   PRIMARY KEY (order_num);
ALTER TABLE products ADD CONSTRAINT pk_products
                     PRIMARY KEY (prod_id);
ALTER TABLE vendors ADD CONSTRAINT pk_vendors
                    PRIMARY KEY (vend_id);
ALTER TABLE productnotes ADD CONSTRAINT pk_productnotes
                         PRIMARY KEY (note_id);      
                         
-- 定義外鍵
---------------------------------------------
-- Define foreign keys
---------------------------------------------
ALTER TABLE orderitems
      ADD CONSTRAINT fk_orderitems_orders FOREIGN KEY (order_num)
      REFERENCES orders (order_num);
ALTER TABLE orderitems
      ADD CONSTRAINT fk_orderitems_products
      FOREIGN KEY (prod_id) REFERENCES products (prod_id);
ALTER TABLE orders
      ADD CONSTRAINT fk_orders_customers FOREIGN KEY (cust_id)
      REFERENCES customers (cust_id);
ALTER TABLE products
      ADD CONSTRAINT fk_products_vendors
      FOREIGN KEY (vend_id) REFERENCES vendors (vend_id);
ALTER TABLE productnotes
      ADD CONSTRAINT fk_productnotes_products
      FOREIGN KEY (prod_id) REFERENCES products (prod_id);
      

刪除表

-- 永久刪除整個表customers2
DROP TABLE customers2; 

重命名表

ALTER TABLE customers2 RENAME TO customers;
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,606評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,582評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,540評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,028評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,801評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,223評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,294評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,442評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,976評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,800評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,996評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,543評論 5 360
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,233評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,662評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,926評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,702評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,991評論 2 374

推薦閱讀更多精彩內容

  • 關系型數據庫和SQL SQL語言的三個部分DML:Data Manipulation Language,數據操縱語...
    Awey閱讀 1,962評論 0 13
  • SQL與MySQL簡介 數據庫基礎 從SQL的角度來看,數據庫就是一個以某種有組織的方式存儲的數據集合。我們可以采...
    heming閱讀 3,112評論 1 8
  • 1. SQL 簡介 SQL 的目標 理想情況下,數據庫語言應允許用戶: 建立數據庫和關系結構 完成基本數據管理任務...
    板藍根plank閱讀 2,367評論 0 11
  • 前言 讀《sql必知必會 第四版》隨手做的筆記,寫的比較亂,可讀性并不好,讀的是中文版,翻譯過來的感覺有點怪怪的。...
    _老徐_閱讀 640評論 0 0
  • 一直想更新下紹興游記,網上的信息幾乎全都不準確,各家有各家的說法,更多的應該還是網絡推廣帶來的營銷弊端,坑苦的是我...
    溫暖dream閱讀 323評論 2 3