简单入门

1
2
3
SELECT prod_id 
FROM Products;
--输出prod_id列
1
2
SELECT prod_id, prod_name 
FROM Products;
1
2
SELECT * FROM Products ;
--输出所有列
1
2
3
SELECT DISTINCT prod_id 
FROM Products;
--输出prod_id不同的列

检索前5行,各数据库有差异:

1
2
SELECT TOP 5 prod_id 
FROM Products;
1
2
3
4
SELECT prod_id 
FROM Products
WHERE ROWNUM <= 5;
--oraCal
1
2
3
SELECT prod_id 
FORM Products LIMIT 5;
--输出5行
1
2
3
4
SELECT prod_id 
FROM Products
LIMIT 5 OFFSET 10;
--从第10行开始,输出5行

1
2
3
4
5
--行内注释的一种方式

#行内注释的另一种方式

/* */块级注释

1
2
3
4
SELECT prod_name 
FROM Products
ORDER BY prod_name;
--按字母顺序排序
1
2
3
4
SELECT prod_id, prod_name, prod_price 
FROM Products
ORDER BY prod_price, prod_name;
--按多列排序
1
2
3
4
SELECT prod_id, prod_name, prod_price 
FROM Products
ORDER BY 2, 3;
--按相对列排序(此处下标从1开始)
1
2
3
4
SELECT prod_id, prod_name, prod_price 
FROM Products
ORDER BY prod_price DESC;
--按降序排列,价格从高到低
1
2
3
4
SELECT prod_id, prod_name, prod_price 
FROM Products
ORDER BY prod_price DESC, prod_name;
--按降序排列,价格从高到低,name还是按字母升序排列

1
2
3
SELECT prod_name, prod_price 
FROM Producs
WHERE prod_price = 3.49;

同时使用WHERE和ORDER BY时,ORDER BY应放在WHERE之后


WHERE子句操作符

操作符 说明
= 等于
<> 不等于
!<= 不等于
< 小于
<= 小于等于
! 不小于
> 大于
>= 大于等于
!> 不大于
BETWEEN 在指定的两个值之间
IS NULL 为NULL值
1
2
3
SELECT prod_name, prod_price 
FROM Products
WHERE prod_price < 10;
1
2
3
SELECT vent_id, prod_name 
FROM Products
WHERE vent_id <> 'DLL01';

单引号用来限定字符串,如果将值与字符串比较就需要用单引号包起来,如果与数值比较就不需要。我觉得最好就都包呗~

有<>和!=是因为DBMS支持上的差异

1
2
3
SELECT prod_name, prod_price
FROM Products
WHERE prod_price BETWEEN 5 AND 10;
1
2
3
4
SELECT prod_name
FROM Products
WHERE prod_price IS NULL;
--空值

组合WHERE子句

1
2
3
4
SELECT prod_id, prod_price, prod_name
FROM Products
WHERE vend_id = 'DLL01' AND prod_price <= 4;
--可以加好多个AND
1
2
3
4
SELECT prod_name, prod_price
FROM Products
WHERE vend_id = 'DLL01' OR vend_id = ‘BRS01’;
--如果OR前面的为true,则一定会打印
1
2
3
4
SELECT prod_name, prod_price
FROM Products
WHERE (vend_id = 'DLL01' OR vend_id = ‘BRS01’) AND prod_price >= 10;
--AND优先级高于OR
1
2
3
4
5
SELECT prod_name, prod_price 
FROM Products
WHERE vend_id IN ( 'DLL01', 'BRS01' )
ORDER BY prod_name;
--IN操作符完成了与OR一样的功能,但是更简洁,直观
1
2
3
4
5
SELECT prod_name
FROM Products
WHERE NOT vend_id = 'DLL01'
ORDER BY prod_name;
--NOT操作符否定其后跟的任何条件

使用通配符过滤

1
2
3
4
5
6
SELECT prod_id, prod_name 
FROM Products
WHERE prod_name LIKE 'Fish%';
--LIKE操作符
--%通配符代表搜索模式中给定位置的0个、1个或多个字符(除NULL外)(Access使用*)
--找出所有以词Fish起头的产品
1
2
3
4
SELECT prod_id, prod_name
FROM Products
WHERE prod_name LIKE '%bean bag%';
--可以使用任意个%
1
2
3
4
SELECT prod_id, prod_name
FROM Products
WHERE prod_name LIKE '_ inch teddy bear';
--_通配符只匹配单个字符,可以使用多个_(Access使用?)
1
2
3
4
5
SELECT cust_contact
FROM Customers
WHERE cust_contact LIKE '[JM]%'
ORDER BY cust_contact;
--[JM]匹配任何以方括号中字母(J或者M)开头的联系人名,它也只能匹配单个字符
1
2
3
4
5
SELECT cust_contact
FROM Customers
WHERE cust_contact LIKE '[^JM]%'
ORDER BY cust_contact;
--^脱字号匹配不以J或M起头的任意联系人名

通配符搜索一般比前面讨论的其他搜索要耗费更长的处理时间:

  • 不要过度使用通配符,如果其它操作符能达到目的,就使用其它操作符
  • 尽量不要用在搜索模式的开始处,用在开始处是最慢的

创建计算字段

1
2
3
4
SELECT RTRIM(vend_name) + ' (' + RTRIM(vend_country) + ')' FROM Vendors
ORDER BY vend_name;
--拼接两列,+或者||(各数据库有差别)
--RTRIM去掉右边空格
1
2
3
4
SELECT RTRIM(vend_name) + ' (' + RTRIM(vend_country) + ')' AS vend_title
FROM Vendors
ORDER BY vend_name;
--AS后面是合并后的新列的名称(别名Alias)
1
2
3
4
5
SELECT prod_id, quantity, item_price,
quantity*item_price AS expanded_price
FROM OrderItems
WHERE order_num = 20008;
--输出中显示的expanded_price列是一个计算字段,此计算为quantity*item_price

SELECT语句为测试、检验函数和计算提供了很好的方法。虽然SELECT通常用于从表中检索数据,但是省略了FROM子句后就是简单地访问 和处理表达式,例如SELECT 3 * 2;将返回6,SELECT Trim(‘ abc ‘);将返回abc,SELECT Now();使用Now()函数返回当前日期和时间。现在 你明白了,可以根据需要使用SELECT语句进行检验。


使用数据处理函数

1
2
3
4
SELECT vend_name, UPPER(vend_name) AS vend_name_upcase 
FROM Vendors
ORDER BY vend_name;
--UPPER()函数将文本转换为大写(这里列出了两列,原来的和转换后的)

常用的文本处理函数:

函数 说明
LEFT()(或使用子字符串函数) 返回字符串左边的字符
LENGTH()(也使用DATALENGTH()或LEN()) 返回字符串的长度
LOWER()(Access使用LCASE()) 将字符串转换为小写
LTRIM() 去掉字符串左边的空格
RIGHT()(或使用子字符串函数) 去掉字符串右边的空格
RTRIM() 去掉字符串右边的空格
SOUNDEX() 返回字符串的SOUNDEX值
UPPER()(Access使用UCASE()) 将字符串转换为大写
1
2
3
4
SELECT cust_name, cust_contact
FROM Customers
WHERE SOUNDEX(cust_contact) = SOUNDEX('Michael Green');
--SOUNDEX发音类似函数(神奇!)
1
2
3
4
SELECT order_num
FROM Orders
WHERE DATEPART(yy, order_date) = 2012;
--DATEPART检索日期的函数(还有其它版本)

数值处理函数:

函数 说明
ABS() 返回一个数的绝对值
COS() 返回一个角度的余弦
EXP() 返回一个数的指数值
PI() 返回圆周率
SIN() 返回一个角度的正弦
SQRT() 返回一个数的平方根
TAN() 返回一个角度的正切

聚集函数

对某些行运行的函数,计算并返回一个值

我们经常需要汇总数据而不用把它们实际检索出来

函数 说明
AVG() 返回某列的平均值
COUNT() 返回某列的行数
MAX() 返回某列的最大值
MIN() 返回某列的最小值
SUM() 返回某列之和
1
2
3
4
5
6
7
SELECT AVG(prod_price) AS avg_price 
FROM Products
WHERE vend_id = 'DLL01';
/*
AVG()可用来返回所有列的平均值,也可以用来返回特定列或行的平均值.
要获得多个列的平均值,必须使用多个AVG()函数
*/
1
2
3
4
5
6
SELECT COUNT(cust_email) AS num_cust 
FROM Customers;
/*
如果指定列名,则COUNT()函数会忽略指定列的值为空的行,
但如果COUNT()函数中用的是星号(*),则不忽略
*/
1
2
3
4
5
6
7
8
9
SELECT MAX(prod_price) AS max_price 
FROM Products;
/*
虽然MAX()一般用来找出最大的数值或日期值,
但许多(并非所有)DBMS允许将它用来返回任意列中的最大值,
包括返回文本列中的最大 值。在用于文本数据时,
MAX()返回按该列排序后的最后一行(MIN()与其相反)。
MAX()/MIN()函数忽略列值为NULL的行。
*/
1
2
3
4
5
SELECT SUM(item_price*quantity) AS total_price 
FROM OrderItems
WHERE order_num = 20005;
--SUM()函数忽略列值为NULL的行
--如本例所示,所有聚集函数都可以用来执行多个列以上的运算

以上5个聚集函数都可以如下使用:

  • 对所有行执行计算,指定A LL参数或不指定参数(因为A LL是默认行为)。
  • 只包含不同的值,指定DISTINCT参数

提示:ALL为默认,无需指定

1
2
3
4
SELECT AVG(DISTINCT prod_price) AS avg_price 
FROM Products
WHERE vend_id = 'DLL01';
--警告:DISTINCT不能用于COUNT(*)
1
2
3
4
5
6
7
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语句子句:创建分组GROUP BY子句和过滤分组HAVING子句

1
2
3
4
SELECT vend_id, COUNT(*) AS num_prods 
FROM Products
GROUP BY vend_id;
--GROUP BY会对每个vend_id而不是整个表计算num_prods一次

GROUP BY的一些规定:

  • GROUP BY子句可以包含任意数目的列,因而可以对分组进行嵌套,更细致地进行数据分组
  • 如果在GROUP BY子句中嵌套了分组,数据将在最后指定的分组上进行汇总。换句话说,在建立分组时,指定的所有列都一起计算(所以 不能从个别的列取回数据)
  • 如果在GROUP BY子句中嵌套了分组,数据将在最后指定的分组上进行汇总。换句话说,在建立分组时,指定的所有列都一起计算(所以 不能从个别的列取回数据)
  • 大多数SQL实现不允许GROUP BY列带有长度可变的数据类型(如文本或备注型字段)
  • 除聚集计算语句外,SELECT语句中的每一列都必须在GROUP BY子句中给出
  • 如果分组列中包含具有NULL值的行,则NULL将作为一个分组返回。如果列中有多行NULL值,它们将分为一组
  • GROUP BY子句必须出现在WHERE子句之后,ORDER BY子句之前
1
2
3
4
5
SELECT cust_id, COUNT(*) AS orders 
FROM Orders
GROUP BY cust_id
HAVING COUNT(*) >= 2;
--HAVING过滤COUNT(*) >= 2(两个以上订单)的那些分组

HAVING和WHERE的差别:
WHERE在数据分组前进行过滤,HA VING在数据分组后进行过滤。这是一个重要的区别,WHERE排除的行不包括在分组中。这可能会改变计算值,从而影响HA VING子句中基于这些值过滤掉的分组.使用HAVING时应 该结合GROUP BY子句,而WHERE子句用于标准的行级过滤。

1
2
3
4
SELECT vend_id, COUNT(*) AS num_prods FROM Products
WHERE prod_price >= 4
GROUP BY vend_id
HAVING COUNT(*) >= 2;

分组和排序:ORDER BY与GROUP BY

ORDER BY GROUP BY
对产生的输出排序 对行分组,但输出可能不是分组的排序
任意列(甚至非选择的列)都可以使用 只可能使用选择列或表达式列,而且必须使用每个选择列表达式
不一定需要 如果与聚集函数一起使用列(或表达式),则必须使用
1
2
3
4
5
6
7
8
9
10
11
SELECT order_num, COUNT(*) AS items 
FROM OrderItems
GROUP BY order_num
HAVING COUNT(*) >= 3
ORDER BY items, order_num;
/*
在这个例子中,使用GROUP BY子句按订单号(order_num列)分组数据,
以便COUNT(*)函数能够返回每个订单中的物品数目。
HAVING子句过滤数据,使得只返回包含三个或更多物品的订单。
最后,用ORDER BY子句排序输出。
*/

SELECT子句顺序

字句 说明 是否必须使用
SELECT 要返回的列表或表达式
FROM 从中检索数据的表 仅在从表中检索数据时使用
WHERE 行级过滤
GROUP BY 分组说明 仅在按组计算聚集时使用
HAVING 组级过滤
ORDER BY 输出排序顺序

子查询

1
2
3
4
5
6
7
8
9
10
11
SELECT cust_id
FROM Orders
WHERE order_num IN
(SELECT cust_id
FROM Orders
WHERE order_num IN (SELECT order_num
FROM OrderItems
WHERE prod_id = 'RGAN01');
FROM OrderItems
WHERE prod_id = 'RGAN01');
--从内向外处理,先SELECT order_num...

联结表

创建联结:

1
2
3
4
SELECT vend_name, prod_name, prod_price 
FROM Vendors, Products
WHERE Vendors.vend_id = Products.vend_id;
--WHERE子句指示DBMS将Vendors表中的vend_id与Products表中的vend_id匹配起来
1
2
3
4
SELECT vend_name, prod_name, prod_price 
FROM Vendors INNER JOIN Products
ON Vendors.vend_id = Products.vend_id;
--联结条件用特定的ON子句给出

联结多个表:

1
2
3
4
5
6
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;
--不要联结不必要的表,非常耗资源

高级联结

使用表别名:

1
2
3
4
5
6
SELECT cust_name, cust_contact
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';
--缩短SQL语句
--允许在一条SELECT语句中多次使用相同的表
1
2
3
4
5
6
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';
--自然联结
1
2
3
4
5
SELECT Customers.cust_id, Orders.order_num 
FROM Customers
INNER JOIN Orders
ON Customers.cust_id = Orders.cust_id;
--内联结
1
2
3
4
5
SELECT Customers.cust_id, Orders.order_num 
FROM Customers
LEFT OUTER JOIN Orders
ON Customers.cust_id = Orders.cust_id;
--外联结
1
2
3
4
5
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;
--带聚集函数的联结

创建组合查询

1
2
3
4
5
6
7
8
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与使用多条WHERE子句相同,如下个例子
1
2
3
4
SELECT cust_name, cust_contact, cust_email 
FROM Customers
WHERE cust_state IN ('IL','IN','MI') OR cust_name = 'Fun4All';
--参照例子,多个WHERE子句

UNION规则

  • UNION必须由两条或两条以上的SELECT语句组成,语句之间用关键字UNION分隔(因此,如果组合四条SELECT语句,将要使用三 个UNION关键字)
  • UNION中的每个查询必须包含相同的列、表达式或聚集函数(不过,各个列不需要以相同的次序列出)
  • 列数据类型必须兼容:类型不必完全相同,但必须是DBMS可以隐含转换的类型(例如,不同的数值类型或不同的日期类型)

使用UNION时,重复的行会被自动取消,如果想返回所有的匹配行,可使用UNION ALL;
在用UNION组合查询时,只能使用一条ORDER BY子句,它必须位于最后一条SELECT语句之后


插入数据

INSERT用来将行插入(或添加)到数据库表

1
2
3
4
5
6
7
8
9
INSERT INTO Customers VALUES('1000000006',
'Toy Land',
'123 Any Street', 'New York',
'NY',
'11111',
'USA',
NULL,
NULL);
--插入完整的行
1
2
3
4
5
6
7
8
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);
--给出了列名虽然繁琐,但是更安全,可以打乱顺序,还可以只插入部分行
1
2
3
4
5
6
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;
--插入检索出的数据(将SELECT语句的结果插入表中)

INSERT通常只插入一行。要插入多行,必须执行多个INSERT语句。INSERT SELECT是个例外,它可以用一条INSERT插入多行,不 管SELECT语句返回多少行,都将被INSERT插入。


从一个表复制到另一个表

1
2
3
4
5
6
7
8
9
10
SELECT *
INTO CustCopy
FROM Customers;
/*
这条SELECT语句创建一个名为CustCopy的新表,
并把Customers表的整个内容复制到新表中。
因为这里使用的是SELECT *,
所以将在CustCopy表中创建(并填充)与Customers表的每一列相同的列。
要想只复制部分的列,可以明确给出列名,而不是使用*通配符。
*/

使用SELECT INTO时:

  • 任何SELECT选项和子句都可以使用,包括WHERE和GROUP BY
  • 可利用联结从多个表插入数据
  • 不管从多少个表中检索数据,数据都只能插入到一个表中

更新和删除数据

UPDATE和DELETE

注意安全

1
2
3
4
UPDATE Customers
SET cust_contact = 'Sam Roberts',
cust_email = 'sam@toyland.com'
WHERE cust_id = '1000000006';
1
2
3
4
UPDATE Customers
SET cust_email = NULL
WHERE cust_id = '1000000005';
--要删除某个列的值,可设置它为NULL
1
2
3
4
DELETE FROM Customers 
WHERE cust_id = '1000000006';
--删除一行,即使删除了所有行,也不删除表
--删除所有行,可使用TRUNCATE TABLE语句,速度更快

更新和删除的指导原则:

  • 除非确实打算更新和删除每一行,否则绝对不要使用不带WHERE子句的UPDA TE或DELETE语句
  • 保证每个表都有主键,尽可能像WHERE子句那样使用它
  • 在UPDA TE或DELETE语句使用WHERE子句前,应该先用SELECT进行测试,保证它过滤的是正确的记录,以防编写的WHERE子句不正确
  • 使用强制实施引用完整性的数据库
  • 有的DBMS允许数据库管理员施加约束,防止执行不带WHERE子句的UPDA TE或DELETE语句。如果所采用的DBMS支持这个特性,应该使用它

创建表

1
2
3
4
5
6
7
8
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 DEFAULT 1,,
prod_desc VARCHAR(1000) NULL
--缺省时,使用默认值
);

允许NULL值的列也允许在插入行时不给出该列的值
不允许NULL值的列不接受没有列值的行


更新表

1
2
ALTER TABLE Vendors
ADD vend_phone CHAR(20);
1
2
ALTER TABLE Vendors 
DROP COLUMN vend_phone;

使用ALTER TABLE要极为小心,应该在进行改动前做完整的备份(模式和数据的备份)。数据库表的更改不能撤销,如果增加了不需要的 列,也许无法删除它们。类似地,如果删除了不应该删除的列,可能会丢失该列中的所有数据。


删除表

1
DROP TABLE CustCopy;

视图

1
2
3
4
5
6
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;
--创建视图
1
2
3
4
SELECT cust_name, cust_contact 
FROM ProductCustomers
WHERE prod_id = 'RGAN01';
--使用视图
1
2
3
4
5
CREATE VIEW VendorLocations AS
SELECT RTRIM(vend_name) + ' (' + RTRIM(vend_country) + ')'
AS vend_title
FROM Vendors;
--用视图重新格式化检索出的数据
1
2
3
4
5
CREATE VIEW CustomerEMailList 
AS SELECT cust_id, cust_name, cust_email
FROM Customers
WHERE cust_email IS NOT NULL;
--用视图过滤不想要的数据
1
2
3
4
5
6
7
8
CREATE VIEW OrderItemsExpanded 
AS SELECT order_num,
prod_id,
quantity,
item_price,
quantity*item_price AS expanded_price
FROM OrderItems;
--使用视图与计算字段

视图为虚拟的表。它们包含的不是数据而是根据需要检索数据的查询。视图提供了一种封装SELECT语句的层次,可用来简化数据处理,重新格 式化或保护基础数据。


使用存储过程

1
2
3
4
EXECUTE AddNewProduct( 'JTS01', 'Stuffed Eiffel Tower',
6.49,
'Plush stuffed toy with the text La ➥Tour Eiffel in red white and blue' );
--执行存储过程
1
2
3
4
5
6
7
8
9
CREATE PROCEDURE MailingListCount ( ListCount OUT INTEGER
)
IS v_rows INTEGER;
BEGIN
SELECT COUNT(*) INTO v_rows
FROM Customers
WHERE NOT cust_email IS NULL; ListCount := v_rows;
END;
--创建存储过程(oracle)

事务处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
BEGIN TRANSACTION
INSERT INTO Customers(cust_id, cust_name)
VALUES('1000000010', 'Toys Emporium');
SAVE TRANSACTION StartOrder;
INSERT INTO Orders(order_num, order_date, cust_id)
VALUES(20100,'2001/12/1','1000000010');
IF @@ERROR <> 0 ROLLBACK TRANSACTION StartOrder;
INSERT INTO OrderItems(order_num, order_item, prod_id, quantity, item_price)
VALUES(20100, 1, 'BR01', 100, 5.49);
IF @@ERROR <> 0 ROLLBACK TRANSACTION StartOrder;
INSERT INTO OrderItems(order_num, order_item, prod_id, quantity, item_price)
VALUES(20100, 2, 'BR03', 100, 10.99);
IF @@ERROR <> 0 ROLLBACK TRANSACTION StartOrder;
COMMIT TRANSACTION
/*
这里的事务处理块中包含了4条INSERT语句。在第一条INSERT语句之后定义了一个保留点,
因此,如果后面的任何一个INSERT操作失败,事 务处理最近回退到这里。在SQL Server中,
可检查一个名为@@ERROR的变量,看操作是否成功。(其他DBMS使用不同的函数或变量返回此 信息。)
如果@@ERROR返回一个非0的值,表示有错误发生,事务处理回退到保留点。
如果整个事务处理成功,发布COMMIT以保留数据。
*/

游标

有时,需要在检索出来的行中前进或后退一行或多行,这就是游标的用途所在。游标(cursor)是一个存储在DBMS服务器上的数据库查询,
它不是一条SELECT语句,而是被该语句检索出来的结果集。在存储了游标之后,应用程序可以根据需要滚动或浏览其中的数据。

1
2
3
4
DECLARE CURSOR CustCursor IS
SELECT * FROM Customers
WHERE cust_email IS NULL
--创建游标
1
2
3
4
5
6
7
8
9
10
11
DECLARE TYPE CustCursor 
IS REF CURSOR
RETURN Customers%ROWTYPE;
DECLARE CustRecord Customers%ROWTYPE
BEGIN
OPEN CustCursor;
FETCH CustCursor INTO CustRecord;
CLOSE CustCursor;
END;
--使用游标OPEN CURSOR CustCursor
--关闭游标CLOSE CustCursor

高级数据处理特性:约束、索引和触发器

1
2
3
CREATE INDEX prod_name_ind 
ON PRODUCTS (prod_name);
--创建索引
1
2
3
4
5
6
7
8
CREATE TRIGGER customer_state 
AFTER INSERT OR UPDATE FOR EACH ROW
BEGIN
UPDATE Customers
SET cust_state = Upper(cust_state)
WHERE Customers.cust_id = :OLD.cust_id
END;
--触发器

建议使用:Oracle SQL Developer

SQL语句语法

ALTER TABLE:用来更新已存在表的结构
COMMIT:用来将事务写入数据库
CREATE INDEX:用于在一个或多个列上创建索引
CREATE PROCEDURE:用于创建存储过程
CREATE TABLE:用于创建新数据库表
CREATE VIEW:用来创建一个或多个表上的新视图
DELETE从:表中删除一行或多行
DROP:永久地删除数据库对象(表、视图、索引等)
INSERT:为表添加一行
INSERT SELECT:将SELECT的结果插入到一个表
ROLLBACK:用于撤销一个事务块
SELECT:用于从一个或多个表(视图)中检索数据
UPDATE:更新表中的一行或多行

数据类型

字符串数据类型

数据类型 说明
CHAR 1~255个字符的定长字符串。它的长度必须在创建时规定
NCHAR CHAR的特殊形式,用来支持多字节或Unicode字符(此类型的不同实现变化很大)
NVARCHAR TEXT的特殊形式,用来支持多字节或Unicode字符(此类型的不同实现变化很大)
TEXT(也称为LONG、MEMO或VARCHAR) 变长文本

不管使用何种形式的字符串数据类型,字符串值都必须括在单引号内

如果数值是计算(求和、平均等)中使用的数值,则应该存储在数值数据类型列中;如果作为字符串(可能只包含
数字)使用,则应该保存在字符串数据类型列中。

数值数据类型

数据类型 说明
BIT 单个二进制位值,或者为0或者为1,主要用于开/关标志
DECIMAL(或NUMERIC) 定点或精度可变的浮点值
FLOAT(或NUMBER) 浮点值
INT(或INTEGER) 4字节整数值,支持-2147483648~2147483647的数
REAL 4字节浮点值
SMALLINT 2字节整数值,支持-32768~32767的数
TINYINT 1字节整数值,支持0~255的数

日期和时间数据类型

数据类型 说明
DATE 日期值
DATETIME(或TIMESTAMP) 日期时间值
SMALLDATETIME 日期时间值,精确到分(无秒或毫秒)
TIME 时间值

二进制数据类型

数据类型 说明
BINARY 定长二进制数据(最大长度从255字节到8000字节,有赖于具体的实现)
LONG RAW 变长二进制数据,最长2 GB
RAW(某些实现为BINARY) 定长二进制数据,最多255字节
VARBINARY 变长二进制数据(最大长度一般在255字节到8000字节间变化,依赖于具体的实现)