简单入门 1 2 3 SELECT prod_id FROM Products;
1 2 SELECT prod_id, prod_name FROM Products;
1 2 SELECT * FROM Products ;
1 2 3 SELECT DISTINCT prod_id FROM Products;
检索前5行,各数据库有差异:
1 2 SELECT TOP 5 prod_id FROM Products;
1 2 3 4 SELECT prod_id FROM Products WHERE ROWNUM <= 5 ;
1 2 3 SELECT prod_id FORM Products LIMIT 5 ;
1 2 3 4 SELECT prod_id FROM Products LIMIT 5 OFFSET 10 ;
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 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;
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_priceFROM ProductsWHERE prod_price BETWEEN 5 AND 10 ;
1 2 3 4 SELECT prod_nameFROM ProductsWHERE prod_price IS NULL ;
组合WHERE子句 1 2 3 4 SELECT prod_id, prod_price, prod_nameFROM ProductsWHERE vend_id = 'DLL01' AND prod_price <= 4 ;
1 2 3 4 SELECT prod_name, prod_priceFROM ProductsWHERE vend_id = 'DLL01' OR vend_id = ‘BRS01’;
1 2 3 4 SELECT prod_name, prod_priceFROM ProductsWHERE (vend_id = 'DLL01' OR vend_id = ‘BRS01’) AND prod_price >= 10 ;
1 2 3 4 5 SELECT prod_name, prod_price FROM ProductsWHERE vend_id IN ( 'DLL01' , 'BRS01' ) ORDER BY prod_name;
1 2 3 4 5 SELECT prod_nameFROM ProductsWHERE NOT vend_id = 'DLL01' ORDER BY prod_name;
使用通配符过滤 1 2 3 4 5 6 SELECT prod_id, prod_name FROM ProductsWHERE prod_name LIKE 'Fish%' ;
1 2 3 4 SELECT prod_id, prod_nameFROM ProductsWHERE prod_name LIKE '%bean bag%' ;
1 2 3 4 SELECT prod_id, prod_nameFROM ProductsWHERE prod_name LIKE '_ inch teddy bear' ;
1 2 3 4 5 SELECT cust_contactFROM CustomersWHERE cust_contact LIKE '[JM]%' ORDER BY cust_contact;
1 2 3 4 5 SELECT cust_contactFROM CustomersWHERE cust_contact LIKE '[^JM]%' ORDER BY cust_contact;
通配符搜索一般比前面讨论的其他搜索要耗费更长的处理时间:
不要过度使用通配符,如果其它操作符能达到目的,就使用其它操作符
尽量不要用在搜索模式的开始处,用在开始处是最慢的
创建计算字段 1 2 3 4 SELECT RTRIM (vend_name) + ' (' + RTRIM (vend_country) + ')' FROM VendorsORDER BY vend_name;
1 2 3 4 SELECT RTRIM (vend_name) + ' (' + RTRIM (vend_country) + ')' AS vend_titleFROM VendorsORDER BY vend_name;
1 2 3 4 5 SELECT prod_id, quantity, item_price,quantity*item_price AS expanded_price FROM OrderItemsWHERE order_num = 20008 ;
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 VendorsORDER BY vend_name;
常用的文本处理函数:
函数
说明
LEFT()(或使用子字符串函数)
返回字符串左边的字符
LENGTH()(也使用DATALENGTH()或LEN())
返回字符串的长度
LOWER()(Access使用LCASE())
将字符串转换为小写
LTRIM()
去掉字符串左边的空格
RIGHT()(或使用子字符串函数)
去掉字符串右边的空格
RTRIM()
去掉字符串右边的空格
SOUNDEX()
返回字符串的SOUNDEX值
UPPER()(Access使用UCASE())
将字符串转换为大写
1 2 3 4 SELECT cust_name, cust_contactFROM CustomersWHERE SOUNDEX (cust_contact) = SOUNDEX ('Michael Green' );
1 2 3 4 SELECT order_numFROM OrdersWHERE DATEPART (yy, order_date) = 2012 ;
数值处理函数:
函数
说明
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 ProductsWHERE vend_id = 'DLL01' ;
1 2 3 4 5 6 SELECT COUNT (cust_email) AS num_cust FROM Customers;
1 2 3 4 5 6 7 8 9 SELECT MAX (prod_price) AS max_price FROM Products;
1 2 3 4 5 SELECT SUM (item_price*quantity) AS total_price FROM OrderItemsWHERE order_num = 20005 ;
以上5个聚集函数都可以如下使用:
对所有行执行计算,指定A LL参数或不指定参数(因为A LL是默认行为)。
只包含不同的值,指定DISTINCT参数
提示:ALL为默认,无需指定
1 2 3 4 SELECT AVG (DISTINCT prod_price) AS avg_price FROM ProductsWHERE vend_id = 'DLL01' ;
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_avgFROM Products;
分组数据 两个新SELECT语句子句:创建分组GROUP BY子句和过滤分组HAVING子句
1 2 3 4 SELECT vend_id, COUNT (*) AS num_prods FROM ProductsGROUP BY vend_id;
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 OrdersGROUP BY cust_idHAVING 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 ProductsWHERE prod_price >= 4 GROUP BY vend_idHAVING 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 OrderItemsGROUP BY order_numHAVING COUNT (*) >= 3 ORDER BY items, order_num;
SELECT子句顺序
字句
说明
是否必须使用
SELECT
要返回的列表或表达式
是
FROM
从中检索数据的表
仅在从表中检索数据时使用
WHERE
行级过滤
否
GROUP BY
分组说明
仅在按组计算聚集时使用
HAVING
组级过滤
否
ORDER BY
输出排序顺序
否
子查询 1 2 3 4 5 6 7 8 9 10 11 SELECT cust_idFROM OrdersWHERE order_num IN (SELECT cust_id FROM OrdersWHERE order_num IN (SELECT order_numFROM OrderItemsWHERE prod_id = 'RGAN01' ); FROM OrderItems WHERE prod_id = 'RGAN01');
联结表 创建联结:
1 2 3 4 SELECT vend_name, prod_name, prod_price FROM Vendors, ProductsWHERE Vendors.vend_id = Products.vend_id;
1 2 3 4 SELECT vend_name, prod_name, prod_price FROM Vendors INNER JOIN ProductsON Vendors.vend_id = Products.vend_id;
联结多个表:
1 2 3 4 5 6 SELECT prod_name, vend_name, prod_price, quantity FROM OrderItems, Products, VendorsWHERE Products.vend_id = Vendors.vend_idAND OrderItems.prod_id = Products.prod_id AND order_num = 20007 ;
高级联结 使用表别名:
1 2 3 4 5 6 SELECT cust_name, cust_contactFROM Customers AS C, Orders AS O, OrderItems AS OI WHERE C.cust_id = O.cust_idAND OI.order_num = O.order_num AND prod_id = 'RGAN01' ;
1 2 3 4 5 6 SELECT C.*, O.order_num, O.order_date, OI.prod_id, OI.quantity, OI.item_priceFROM 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 OrdersON Customers.cust_id = Orders.cust_id;
1 2 3 4 5 SELECT Customers.cust_id, Orders.order_num FROM Customers LEFT OUTER JOIN OrdersON Customers.cust_id = Orders.cust_id;
1 2 3 4 5 SELECT Customers.cust_id, COUNT (Orders.order_num) AS num_ordFROM Customers INNER JOIN Orders ON Customers.cust_id = Orders.cust_idGROUP BY Customers.cust_id;
创建组合查询 1 2 3 4 5 6 7 8 SELECT cust_name, cust_contact, cust_email FROM CustomersWHERE cust_state IN ('IL' ,'IN' ,'MI' )UNION SELECT cust_name, cust_contact, cust_email FROM CustomersWHERE cust_name = 'Fun4All' ;
1 2 3 4 SELECT cust_name, cust_contact, cust_email FROM CustomersWHERE cust_state IN ('IL' ,'IN' ,'MI' ) OR cust_name = 'Fun4All' ;
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;
INSERT通常只插入一行。要插入多行,必须执行多个INSERT语句。INSERT SELECT是个例外,它可以用一条INSERT插入多行,不 管SELECT语句返回多少行,都将被INSERT插入。
从一个表复制到另一个表
1 2 3 4 5 6 7 8 9 10 SELECT *INTO CustCopy FROM Customers;
使用SELECT INTO时:
任何SELECT选项和子句都可以使用,包括WHERE和GROUP BY
可利用联结从多个表插入数据
不管从多少个表中检索数据,数据都只能插入到一个表中
更新和删除数据 UPDATE和DELETE
注意安全
1 2 3 4 UPDATE CustomersSET cust_contact = 'Sam Roberts' ,cust_email = 'sam@toyland.com' WHERE cust_id = '1000000006' ;
1 2 3 4 UPDATE CustomersSET cust_email = NULL WHERE cust_id = '1000000005' ;
1 2 3 4 DELETE FROM Customers WHERE cust_id = '1000000006' ;
更新和删除的指导原则:
除非确实打算更新和删除每一行,否则绝对不要使用不带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 VendorsADD vend_phone CHAR (20 );
1 2 ALTER TABLE Vendors DROP COLUMN vend_phone;
使用ALTER TABLE要极为小心,应该在进行改动前做完整的备份(模式和数据的备份)。数据库表的更改不能撤销,如果增加了不需要的 列,也许无法删除它们。类似地,如果删除了不应该删除的列,可能会丢失该列中的所有数据。
删除表
视图 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_idAND OrderItems.order_num = Orders.order_num;
1 2 3 4 SELECT cust_name, cust_contact FROM ProductCustomersWHERE 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 CustomersWHERE 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 CustomersWHERE NOT cust_email IS NULL ; ListCount := v_rows;END ;
事务处理 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
游标 有时,需要在检索出来的行中前进或后退一行或多行,这就是游标的用途所在。游标(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 ;
高级数据处理特性:约束、索引和触发器 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 CustomersSET 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字节间变化,依赖于具体的实现)