SQL爲結構化查詢語言(Structured Query Language)的縮寫。SQL是一種專門用來與數據庫溝通的語言。html
-- 檢索單個列 SELECT prod_name FROM Products; -- 檢索多個列 SELECT prod_id,prod_name,prod_price FROM Products; -- 檢索全部列 SELECT * FROM Products;
注:檢索全部列會下降檢索和應用程序的性能。java
SELECT DISTINCT vend_id FROM Products; -- DISTINCT不能部分使用,下面的SQL只有當vend_id和prod_name都相同的兩行纔不會被檢出。 SELECT DISTINCT vend_id,prod_name FROM Products;
-- 前5條 -- MYSQL SQLite PostgreSQL SELECT prod_name FROM Products LIMIT 5; -- Oracle SELECT prod_name FROM Products WHERE ROWNUM <= 5 /* 分隔條 */ -- 跳過前5條 -- MYSQL SQLite PostgreSQL SELECT prod_name FROM Products LIMIT 5 OFFSET 5; -- MYSQL SELECT prod_name FROM Products LIMIT 5, 5; -- Oracle SELECT prod_name FROM Products WHERE ROWNUM > 5 and ROWNUM <= 10;
SELECT prod_name FROM Products ORDER BY prod_name;
注1:ORDER BY只能在SELECT語句最後一條子句。
注2:ORDER BY所使用的列不須要是顯示而選擇的列,能夠選擇非檢索的列。mysql
-- 先按照prod_price排序,當prod_price相同時,才按照prod_name排序。 SELECT prod_id,prod_price,prod_name FROM Products ORDER BY prod_price,prod_name; -- 列位置爲檢出的位置。 SELECT prod_id,prod_price,prod_name FROM Products ORDER BY 2,3; -- 先按照prod_price降序排,當prod_price相同時,才按照prod_name升序排。 SELECT prod_id,prod_price,prod_name FROM Products ORDER BY prod_price DESC,prod_name;
SELECT prod_name,prod_price FROM Products WHERE prod_price = 3.49;
操做符 | 說明 |
---|---|
= | 等於 |
<> 或 != | 不等於 |
< | 小於 |
> | 大於 |
!< | 不小於 |
!> | 不大於 |
>= | 大於等於 |
<= | 小於等於 |
BETWEEN | 兩值之間 |
IS NULL | 爲NULL |
-- 檢查單個值 SELECT prod_name,prod_price FROM Products WHERE prod_price < 10; -- 不匹配檢查 SELECT vend_id,prod_name FROM Products WHERE vend_id != 'DLL01'; -- 範圍檢查 SELECT prod_name,prod_price FROM Products WHERE prod_price BETWEEN 5 and 10; -- 空值檢查 SELECT prod_name FROM Products WHERE prod_price IS NULL;
-- AND SELECT prod_id,prod_price,prod_name FROM Products WHERE vend_id = 'DLLL01' AND prod_price <=4; -- OR SELECT prod_id,prod_price,prod_name FROM Products WHERE vend_id = 'DLLL01' OR vend_id = 'BRS01'; -- 求值順序 SELECT prod_name,prod_price WHERE (vend_id = 'DLL01' OR vend_id = 'BRS01') AND prod_price >=10; /* 使用IN的好處 1.在不少合法選項時,IN操做符更清晰。 2.在不少AND和OR操做組合使用IN時,求值順序更容器管理 3.IN操做符比一組OR操做符執行更快 4.IN能夠包含其餘SELECT語句,可以更動態創建WHERE語句。 */ -- IN SELECT prod_name,prod_price FROM Products WHERE vend_id IN ('DLL01','BRS01') ORDER BY prod_name; -- NOT SELECT prod_name,prod_price FROM Products WHERE vend_id NOT IN ('DLL01','BRS01') ORDER BY prod_name;
-- % 通配符:0、1或多個字符,不匹配NULL SELECT prod_id,prod_name FROM Products WHERE prod_name LIKE 'Fish%'; SELECT prod_id, prod_name ROM Products WHERE prod_name LIKE '%bean bag%'; -- 有些數據庫會用空格來填補字段的內容。如:prod_name爲5個字符,'Fly' -> 'Fly ',這樣'F%y'就沒法匹配到,解決方法爲函數去除空格或'F%y%' SELECT prod_name FROM Products WHERE prod_name LIKE 'F%y'; -- 搜索電子郵件地址 WHERE email LIKE 'b%@gmail.com'; -- _通配符:只匹配單個字符。 SELECT prod_id, prod_name FROM Products WHERE prod_name LIKE '__ inch teddy bear'; -- []通配符 SELECT cust_contact FROM Customers WHERE cust_contact LIKE '[JM]%' ORDER BY cust_contact;
-- 大部分數據庫 SELECT vend_name + ' (' + vend_country + ')' FROM Vendors ORDER BY vend_name; SELECT vend_name || ' (' || vend_country || ')' FROM Vendors ORDER BY vend_name; -- MYSQL SELECT Concat(vend_name,'(',vend_country,')') FROM Vendors ORDER BY vend_name;
SELECT Concat(vend_name,'(',vend_country,')') AS vend_title FROM Vendors ORDER BY vend_name;
注1:別名能夠是字符串,如:‘vend title’,不夠最後不使用多單詞的字符串,而是使用_分隔的單詞。算法
-- 彙總價格 SELECT prod_id,quantity,item_price,quantity*item_price AS expanded_price FROM OrderItems WHERE order_num = 20008;
函數 | 語法 |
---|---|
截取字符串 | Oracle使用SUBSTR();MySQL使用SUBSTRING(str,start,end) |
數據類型轉換 | Oracle使用多個函數;MySQL使用CONVERT() |
獲取當前時間 | Oracle使用SYSDATE;MySQL使用CURDATE() |
函數 | 說明 |
---|---|
LEFT(str,len) | 返回字符串左邊字符 |
LENGTH(str) 或 DATALENGTH() 或 LEN() | 返回字符串的長度 |
LOWER(st) UPPER(str) | 小寫 大寫 |
LTRIM(str) TRIM(str) RTRIM(str) | 刪除左空格 刪除左右空格 刪除右空格 |
SOUNDEX() | 返回字符串的SOUNDEX值 |
注1:上述加粗的部分表明MySQL可用函數。
注2:soundex是一個將任何文本串轉換爲描述其語音表示的字母數字模式的算法。sql
SELECT SUBSTRING(prod_name,5,6) AS prod_new_id FROM products; SELECT LEFT(prod_name,2) AS left_name FROM products; SELECT LENGTH(prod_name) AS name_length FROM products; SELECT LTRIM(prod_name) FROM products; -- 尋找顧客聯繫方式發音爲Y San的顧客 SELECT * FROM customers WHERE soundex(cust_contact) = soundex('Y San');
-- 尋找order_date爲2012年的數據 -- Oracle -- 方法1 SELECT order_num FROM Orders WHERE to_number(to_char(order_date, 'YYYY')) = 2012; -- 方法2 SELECT order_num FROM Orders WHERE order_date BETWEEN to_date('01-01-2012') AND to_date('12-31-2012'); -- MySQL SELECT order_num FROM Orders WHERE YEAR(order_date) = 2012;
具體列出MySQL的部分日期函數數據庫
函數 | 說明 |
---|---|
now() | 獲取當前日期+時間(date + time) |
current_timestamp() | 獲取當前時間戳 |
date_format(str,format);str_to_date(str,format) | date -> str;str -> date |
to_days(date);from_days(days) | date -> 天數;天數 -> date |
time_to_sec(time);sec_to_time(sec) | time -> sec;sec -> time |
timediff(time1,time2) datediff(date1,date2) | 日期相減 |
date_add(date,interval expr UNIT) | 加exper UNIT |
SELECT now() SELECT CURRENT_TIMESTAMP -- 2019-02-14 15:22:00 SELECT DATE_FORMAT(now(),'%Y-%m-%d %H:%i:%s') SELECT STR_TO_DATE('20190214 15:22:00','%Y%m%d %H:%i:%s'); SELECT DATE_ADD(now(),INTERVAL 1 day)
函數 | 說明 |
---|---|
ABS(x) | 絕對值 |
COS(x) SIN(x)TAN(x) | 餘弦值 正弦值 正切值 |
EXP(x) | 指數值 |
PI() | 圓周率 |
SQRT(x) | 平方根 |
CEIL(x) FLOOR(x) ROUND(x) | 最大整數值 最小整數值 四捨五入 |
TRUNCATE(x,y) | 保留y位小數值 |
RAND() | 0~1隨機數 |
MOD(x,y) | x mod y |
SELECT ABS(-11); -- 0.5 SELECT COS(PI()/180*60) SELECT SIN(PI()/180*30) -- 6 SELECT ceil(5.1) -- 5 SELECT FLOOR(5.1) -- 5 SELECT ROUND(5.1) -- 1.12 SELECT TRUNCATE(1.12345,2)
函數 | 說明 |
---|---|
AVG() | 某列的平均值,忽略NULL值 |
COUNT() | 某列的行數 |
MAX() MIN() | 某列最大值 最小值 |
SUM() | 某列求和 |
SELECT AVG(prod_price) AS avg_price FROM Products WHERE vend_id = 'DLL01'; -- COUNT(*):計算NULL值 -- COUNT(column):忽略NULL值 SELECT COUNT(*) AS num_cust FROM Customers; -- MAX用於找出最大數值或日期值,若是用於文本則找出排序後的最後一行,忽略NULL值。 SELECT MAX(prod_price) AS max_price FROM Products; -- 返回訂單中全部物品數量之和,忽略NULL值。 SELECT SUM(quantity) AS items_ordered FROM OrderItems WHERE order_num = 20005;
SELECT AVG(DISTINCT prod_price) AS avg_price FROM Products WHERE vend_id = 'DLL01';
SELECT COUNT(*) AS num_items,MIN(prod_price) AS price_min,MAX(prod_price) AS price_max, AVG(prod_price) AS price_avgFROM Products;
-- 安裝vend_id分組 SELECT vend_id, COUNT(*) AS num_prods FROM Products GROUP BY vend_id; SELECT vend_id,prod_name,COUNT(vend_id) AS count FROM products GROUP BY vend_id,prod_name;
-- 對分組後的結果進行排序 SELECT cust_id, COUNT(*) AS orders FROM Orders WHERE prod_price >= 4 GROUP BY cust_id HAVING COUNT(*) >= 2;
ORDER BY | GROUP BY |
---|---|
對產出的輸出排序 | 對行分組,但輸出可能不是分組的順序 |
任意列均可以(甚至非檢出的列也行) | 只可能使用選擇列或表達式列,並且必須使用每一個選擇列表達式 |
不必定須要 | 若是與彙集函數一塊兒使用列(或表達式),則必須使用 |
-- 因爲分組後的順序不肯定,因此最後加上ORDER BY排序 SELECT order_num, COUNT(*) AS items FROM OrderItems GROUP BY order_num HAVING COUNT(*) >= 3 ORDER BY items, order_num;
子句 | 說明 | 是否必須使用 |
---|---|---|
SELECT | 返回列或表達式 | 是 |
FROM | 從中檢索數據的表 | 僅從表中檢索數據時須要 |
WHERE | 行級過濾 | 否 |
GROUP BY | 分組說明 | 僅在按組計算聚合時使用 |
HAVING | 分組過濾 | 否 |
ORDER BY | 輸出排序 | 否 |
-- 查看哪位顧客購買了RGAN01商品 SELECT cust_id FROM Orders WHERE order_num IN (SELECT order_num FROM OrderItems WHERE prod_id = 'RGAN01');
注1:子查詢的SELECT語句只能查詢單個列。
注2:子查詢可能影響性能。安全
-- 查詢顧客購下了多少訂單 SELECT cust_name, cust_state, (SELECT COUNT(*) FROM Orders WHERE Orders.cust_id = Customers.cust_id) AS orders FROM Customers ORDER BY cust_name;
可以適應不斷增長的工做量而不失敗。設計良好的數據庫或應用程序稱爲可伸縮性好(scale well)。服務器
SELECT vend_name,prod_name,prod_price FROM Venders,Products WHERE Venders.vend_id = Products.vend_id;
-- 等同於上面,只是語法不一樣 SELECT vend_name, prod_name, prod_price FROM Vendors INNER JOIN Products ON Vendors.vend_id = Products.vend_id;
-- 顯示訂單20007中的物品 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 = 20007; -- 子查詢 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 = 'RGAN01')); -- 聯結方式消除子查詢 SELECT cust_name,cust_contact FROM Customers,Orders,OrderItems WHERE Customers.cust_id = Orders.cust_id AND Orders.order_num = OrderItems.order_num AND OrderItems.prod_id = 'RGAN01
注1:性能:DBMS在運行時關聯指定的每一個表,以處理聯結。這種處理可能很是耗費資源,所以應該注意,不要聯結沒必要要的表。
注2:聯結中表的最大數目:實際上許多DBMS都有限制併發
-- 子查詢 SELECT cust_id, cust_name, cust_contact FROM Customers WHERE cust_name = (SELECT cust_name FROM Customers WHERE cust_contact = 'Jim Jones'); -- 子聯結 SELECT cust_id,cust_name,cust_contact FROM Customers AS c1,Customers AS c2 WHERE c1.cust_name = c2.cust_name AND c2.cust_contact = 'Jim Jones';
注:子聯結比子查詢查詢快得多。ide
-- 去除重複列 SELECT C.*, O.order_num, O.order_date, OI.prod_id, OI.quantity, OI.item_price FROM Customers AS C, Orders AS O, OrderItems AS OI WHERE C.cust_id = O.cust_id AND OI.order_num = O.order_num AND prod_id = 'RGAN01';
-- 對每一個顧客下的訂單進行計數,包括那些至今還沒有下訂單的顧客; -- 列出全部產品以及訂購數量,包括沒有人訂購的產品; -- 計算平均銷售規模,包括那些至今還沒有下訂單的顧客。 -- 檢索全部顧客及其訂單,不包含沒有訂單的顧客 SELECT Customers.cust_id, Orders.order_num FROM Customers INNER JOIN Orders ON Customers.cust_id = Orders.cust_id; -- 要檢索包括沒有訂單顧客在內的全部顧客 SELECT Customers.cust_id, Orders.order_num FROM Customers LEFT OUTER JOIN Orders ON Customers.cust_id = Orders.cust_id; -- 全外聯結(full outer join),它檢索兩個表中的全部行並關聯那些能夠關聯的行(惋惜MySQL不支持) SELECT Customers.cust_id, Orders.order_num FROM Orders FULL OUTER JOIN Customers ON Orders.cust_id = Customers.cust_id;
-- 檢索全部顧客及每一個顧客所下的訂單數 SELECT Customers.cust_id, COUNT(Orders.order_num) AS num_ord FROM Customers INNER JOIN Orders ON Customers.cust_id = Orders.cust_id GROUP BY Customers.cust_id;
SELECT cust_name, cust_contact, cust_email FROM Customers WHERE cust_state IN ('IL','IN','MI') OR cust_name = 'Fun4All'; -- 修改成UNION SELECT cust_name, cust_contact, cust_email FROM Customers WHERE cust_state IN ('IL','IN','MI') UNION SELECT cust_name, cust_contact, cust_email FROM Customers WHERE cust_name = 'Fun4All';
-- 取消重複:UNION SELECT cust_name, cust_contact, cust_email FROM Customers WHERE cust_state IN ('IL','IN','MI') UNION SELECT cust_name, cust_contact, cust_email FROM Customers WHERE cust_name = 'Fun4All'; -- 包含重複:UNION ALL SELECT cust_name, cust_contact, cust_email FROM Customers WHERE cust_state IN ('IL','IN','MI') UNION ALL SELECT cust_name, cust_contact, cust_email FROM Customers WHERE cust_name = 'Fun4All';
在用UNION組合查詢時,只能使用一條ORDER BY子句,它必須位於最後一條SELECT語句以後。
SELECT cust_name, cust_contact, cust_email FROM Customers WHERE cust_state IN ('IL','IN','MI') UNION SELECT cust_name, cust_contact, cust_email FROM Customers WHERE cust_name = 'Fun4All' ORDER BY cust_name, cust_contact;
-- 插入完整行 INSERT INTO Customers VALUES('1000000006', 'Toy Land', '123 Any Street' 'New York', 'NY', '11111', 'USA', NULL, NULL); -- 更安全的方式,一樣是填充全部列 INSERT INTO Customers(cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country, cust_contact, cust_email) VALUES('1000000006', 'Toy Land', '123 Any Street', 'New York', 'NY', '11111', 'USA', NULL, NULL); -- 插入部分行 -- 省略了cust_contact和cust_email,這兩列容許爲NULL或者有默認值。 INSERT INTO Customers(cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country) VALUES('1000000006', 'Toy Land', '123 Any Street', 'New York', 'NY', '11111', 'USA'); -- 插入檢索出的數據,從CustNew檢索出來並插入到Customers INSERT INTO Customers(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;
當須要測試新的SQL時,能夠進行該操做複製一張新表進行測試。
-- 建立一個名爲CustCopy的新表,並把Customers表的整個內容複製到新表中 CREATE TABLE CustCopy AS SELECT * FROM Customers; -- 只複製表結構 CREATE TABLE CustCopy LIKE Customers; CREATE TABLE CustCopy AS SELECT * FROM Customers where 1=2
UPDATE Customers SET cust_contact = 'Sam Roberts', cust_email = 'kim@thetoystore.com' WHERE cust_id = '100000000005';
注:更新時不要省略過濾條件,除非你肯定要更新全部行。
DELETE FROM Customers WHERE cust_id = '100000000005'; -- 清空表 TRUNCATE TABLE Customers;
注:刪除時不要省略過濾條件,除非你肯定要刪除全部行。
MySQL數據類型 | 含義 |
---|---|
tinyint(m) | 1個字節 範圍(-128~127) |
smallint(m) | 2個字節 範圍(-32768~32767) |
mediumint(m) | 3個字節 範圍(-8388608~8388607) |
int(m) | 4個字節 範圍(-2147483648~2147483647) |
float(m.d) | 單精度浮點型 8位精度(4字節) m總個數,d小數位,如:float(5,3) 123.4567 => 123.457 |
double(m,d) | 雙精度浮點型 16位精度(8字節) m總個數,d小數位 |
decimal(m,d) | 定點數爲精確值,浮點值爲近似值,m<65 是總個數,d<30 且 d<m 是小數位 |
char(n) | 固定長度,最多255個字符,空格填充,查詢時取出空格,佔n字節。 |
varchar(n) | 可變長度,最多65535個字符,佔實際+1(<=255)或2(大於255)字節但不超過n,可直接建立索引。 |
tinytext | 可變長度,最多255個字符 |
text | 可變長度,最多65535個字符,佔實際+2字節,須要指定前多少字符建立索引。 |
mediumtext | 可變長度,最多2的24次方-1個字符 |
longtext | 可變長度,最多2的32次方-1個字符 |
date | 日期 '2008-12-2' |
time | 時間 '12:25:36' |
datetime | 日期時間 '2008-12-2 22:06:44' |
timestamp | 自動存儲記錄修改時間 |
注:整型取值範圍若是加了 unsigned,則最大值翻倍
-- 基礎 CREATE TABLE Products ( prod_id CHAR(10) NOT NULL, vend_id CHAR(10) NOT NULL, prod_name CHAR(254) NOT NULL, prod_price DECIMAL(8,2) NOT NULL, prod_des TEXT NULL ); -- 使用NULL CREATE TABLE Orders ( order_num INT NOT NULL, order_date DATETIME NOT NULL, cust_id CHAR(10) NOT NULL ); CREATE TABLE Vendors ( vend_id CHAR(10) NOT NULL, vend_name CHAR(50) NOT NULL, vend_address CHAR(50) , vend_city CHAR(50) , vend_state CHAR(5) , vend_zip CHAR(10) , vend_country CHAR(50) ); -- 指定默認值 CREATE TABLE OrderItems ( order_num INT NOT NULL, order_item INT NOT NULL, prod_id CHAR(10) NOT NULL, quantity INT NOT NULL DEFAULT 1, item_price DECIMAL(8,2) NOT NULL ); -- 建立Tasks表 CREATE TABLE IF NOT EXISTS Tasks ( task_id INT(11) NOT NULL AUTO_INCREMENT, subject VARCHAR(45), start_date DATE, end_date DATE, description VARCHAR(200), PRIMARY KEY (task_id) ) ENGINE = InnoDB;
-- 新增字段 ALTER TABLE Venders ADD vend_phone CHAR(20); -- 刪除字段 ALTER TABLE Venders DROP COLUMN vend_phone;
DROP TABLE CustCopy;
ALTER TABLE CustCopy RENAME TO CustCopyTest;
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 = 'RGAN01'; -- ProductCustomers爲視圖 SELECT cust_name, cust_contact FROM ProductCustomers WHERE prod_id = 'RGAN01';
-- 建立視圖簡化聯結 CREATE VIEW ProductCustomers AS SELECT cust_name, cust_contact, prod_id FROM Customers, Orders, OrderItems WHERE Customers.cust_id = Orders.cust_id AND OrderItems.order_num = Orders.order_num; SELECT cust_name, cust_contact FROM ProductCustomers WHERE prod_id = 'RGAN01'; -- 從新格式化檢索出的數據 SELECT CONCAT(RTRIM(vend_name),' (',RTRIM(vend_country),')') AS vend_title FROM Vendors ORDER BY vend_name; SELECT * FROM VendorLocations; -- 使用視圖和計算字段 CREATE VIEW OrderItemsExpanded AS SELECT order_num, prod_id, quantity, item_price, quantity*item_price AS expanded_price FROM OrderItems; SELECT * FROM OrderItemsExpanded WHERE order_num = 20008;
常常會有一些複雜的操做須要多條語句才能完成。例如如下的情形:
簡言之,簡單、安全、高性能。
-- EXECUTE 存儲過程(args) -- 驗證傳遞數據、生成主鍵惟一ID、將新產品插入到Products表中 EXECUTE AddNewProduct( 'JTS01', 'Stuffed Eiffel Tower', 6.49, 'Plush stuffed toy with the text La➥Tour Eiffel in red white and blue' );
-- 建立刪除商品的存儲過程 mysql> delimiter $$ mysql> CREATE PROCEDURE delete_product(IN p_prod_id int) -> BEGIN -> DELETE FROM products -> WHERE prod_id = p_prod_id; -> END $$ -- 調用存儲過程 mysql> CALL delete_product(1);
-- 存儲過程體 label1: BEGIN label2: BEGIN label3: BEGIN statements; END label3 ; END label2; END label1 -- 參數說明 CREATE PROCEDURE 存儲過程名([[IN |OUT |INOUT ] 參數名 數據類形...]) -- demo mysql > DELIMITER // mysql > CREATE PROCEDURE update_and_return(INOUT p_prod_id int,IN p_test int) -> BEGIN -> UPDATE products -> SET vend_id = p_test -> WHERE prod_id = p_prod_id; -> SELECT vend_id -> FROM products -> WHERE prod_id = p_prod_id; -> SET p_prod_id = 4; -> END -> // mysql > DELIMITER ; mysql > SET @Y = 3; mysql > CALL update_and_return(@Y,100); // 100 mysql > SELECT @Y; // 4 -- 條件語句 mysql > DELIMITER // mysql > CREATE PROCEDURE proc2(IN parameter int) -> begin -- declare 聲明變量 -> declare var int; -> set var=parameter+1; -> if var=0 then -> insert into t values(17); -> end if; -> if parameter=0 then -> update t set s1=s1+1; -> else -> update t set s1=s1+2; -> end if; -> end; -> // mysql > DELIMITER ; -- 循環語句 mysql > DELIMITER // mysql > CREATE PROCEDURE proc4() -> begin -> declare var int; -> set var=0; -> while var<6 do -> insert into t values(var); -> set var=var+1; -> end while; -> end; -> // mysql > DELIMITER ;
事務處理是一種機制,用來管理必須成批執行的SQL操做,保證數據庫不包含不完整的操做結果。
事務處理用來管理INSERT、UPDATE和DELETE語句。
不能回退SELECT語句,也不能回退CREATE或DROP操做。
小結:不可重複讀的和幻讀很容易混淆,不可重複讀側重於修改,幻讀側重於新增或刪除。解決不可重複讀的問題只需鎖住知足條件的行,解決幻讀須要鎖表(設置串行化隔離級別)。
InnoDB支持下列四種隔離級別;Myisam不支持事務,只支持表鎖。
事務隔離級別 | 髒讀 | 不可重複讀 | 幻讀 |
---|---|---|---|
讀未提交(read-uncommitted) | 是 | 是 | 是 |
不可重複讀(read-committed) | 否 | 是 | 是 |
可重複讀(repeatable-read) | 否 | 否 | 是 |
串行化(serializable) | 否 | 否 | 否 |
表鎖:
行鎖:
注:意向鎖搭配行鎖使用來阻塞表鎖,如:
/* BEGIN:開啓一個事務 ROLLBACK:發生異常回滾 COMMIT:事務正常提交 */ /* SET AUTOCOMMIT=0:禁止自動提交 SET AUTOCOMMIT=1:開啓自動提交 */
遊標(cursor)是一個存儲在DBMS服務器上的數據庫查詢,它不是一條SELECT語句,而是被該語句檢索出來的結果集。
特性:
-- 建立遊標 DECLARE CustCursor CURSOR FOR SELECT * FROM Customers WHERE cust_email IS NULL -- 使用遊標 DECLARE @cust_id CHAR(10), @cust_name CHAR(50), @cust_address CHAR(50), @cust_city CHAR(50), @cust_state CHAR(5), @cust_zip CHAR(10), @cust_country CHAR(50), @cust_contact CHAR(50), @cust_email CHAR(255) -- 開啓遊標 OPEN CustCursor -- 獲取下一行 FETCH NEXT FROM CustCursor INTO @cust_id, @cust_name, @cust_address, @cust_city, @cust_state, @cust_zip, @cust_country, @cust_contact, @cust_email WHILE @@FETCH_STATUS = 0 BEGIN FETCH NEXT FROM CustCursor INTO @cust_id, @cust_name, @cust_address, @cust_city, @cust_state, @cust_zip, @cust_country, @cust_contact, @cust_email END -- 關閉遊標 CLOSE CustCursor
create table stu( sid int UNSIGNED primary key auto_increment, name varchar(20) not null) TYPE=InnoDB charset=utf8; create table sc( scid int UNSIGNED primary key auto_increment, sid int UNSIGNED not null, score varchar(20) default '0', index (sid), --外鍵必須加索引 FOREIGN KEY (sid) REFERENCES stu(sid) ON DELETE CASCADE -- 級聯刪除 ON UPDATE CASCADE -- 級聯更新 )TYPE=InnoDB charset=utf8;
指定列的默認值
指定列不爲空
索引用來排序數據以加快搜索和排序操做的速度。
能夠在一個或多個列上定義索引,使DBMS保存其內容的一個排過序的列表。
開始建立索引前,應該記住如下內容:
注:索引的效率隨表數據的增長或改變而變化。許多數據庫管理員發現,過去建立的某個理想的索引通過幾個月的數據處理後可能變得再也不理想了。最好按期檢查索引,並根據須要對索引進行調整。
CREATE INDEX prod_name_ind ON PRODUCTS (prod_name);
注:指定全文索引時,無需指定索引類型。
觸發器是特殊的存儲過程,它在特定的數據庫活動發生時自動執行。觸發器能夠與特定表上的INSERT、UPDATE和DELETE操做(或組合)相關聯。
觸發器內的代碼具備如下數據的訪問權:
常見用途:
-- 模板 DROP TRIGGER IF EXISTS triggerName; create trigger triggerName after/before insert/update/delete on tableName for each row begin sql語句; end; -- 例:更新時間戳 DROP TRIGGER IF EXISTS `upd_info`; create trigger upd_info after insert on StuCost for each row begin update StuCostbyHour set HourCost = HourCost + new.Cost where (TimeJD = hour(new.RecordTime) + 1) and date_format(new.RecordTime, '%Y-%m-%d') = date_format(RecordTime, '%Y-%m-%d'); end;
-- 刪除重複行:只有last_name、first_name和sex都相同才視爲相同 CREATE TABLE tmp SELECT last_name, first_name, sex FROM person_tbl GROUP BY last_name, first_name, sex; DROP TABLE person_tbl; ALTER TABLE tmp RENAME TO person_tbl;
參考:
《SQL必知必會》
Runoob的MySQL教程