2019-06-01 SQL笔记

SQL操作方式: 创建 ,删除 , 修改

1.模式:  创建CREATE  SCHEMA      删除 DROPSCHEMA 

2.表 :创建CREATE  TABLE    删除DROP TABLE            修改 ALTER TABLE

3.视图 : 创建CREATE  VIEW    删除DROP  VIEW 

4.索引 :创建CREATE INDEX      删除DROP INDEX

sql语句不区分大小写

1.检索单个列

SQL SELECT

SELECT列名 FROM 表名;

SELECT  prod_name  

FROM  products;

2.多个检索列

SELECT列名1,列名2,列名3  FROM 表名;

SELECT prod_name, prod_name,prod_price

 FROM  products;


3.检索所有列

SELECT  *

FROM表名;

SELECT  *  FROM  products;


排序检索数据

1.排序数据

SELECT列名

FROM表名

ORDER BY列名;

SELECT  prod_name  FROM  products  order by prod_name;


按多列排序

SELECT列名1,列名2,列名3

FROM表名

ORDER BY列名2,列名1;

SELECT  prod_id,prod_price,prod_name

 FROM  products  

order by prod_price,prod_name;


按列位置排序

SELECT列名1,列名2,列名3

FROM表名

ORDER BY  2,3;

SELECT  prod_id,prod_price,prod_name

 FROM  products  

order by 2, 3;


指定排序方向

SELECT列名1,列名2,列名3

FROM表名

ORDER BY列名2  DESC;降序排序

SELECT  prod_id,prod_price,prod_name

 FROM  products  

order byprod_price  DESC;


SELECT列名1,列名2,列名3

FROM表名

ORDER BY列名2 DESC,列名1;

SELECT  prod_id,prod_price,prod_name

 FROM  products  

order by prod_price  DESC, prod_name;


过滤数据(搜索条件)

SELECT列名1,列名2,列名3

FROM表名

Where列名=数值(或其他条件);

SELECT  prod_id,prod_price,prod_name

 FROM  products  

WHERE  prod_price=3.95;

WHERE子句操作符

=!<不小于IS NULL为NULL值

<  >不等于> 

!=不等于>= 

不大于 

<=BETWEEN两值之间 


检查单个值

SELECT列名1,列名2,列名3

FROM表名

Where列名<数值(或其他条件);

SELECT  prod_id,prod_price,prod_name

 FROM  products  

WHERE  prod_price<10;


不匹配检查

SELECT列名1,列名2,列名3

FROM表名

Where列名< >数值(或其他条件);

SELECT  prod_id,prod_price,prod_name

 FROM  products  

WHERE  vend_id=’DLL01’;


范围值检查

SELECT列名1,列名2,列名3

FROM表名

Where列名 BETWEEN 数值(或其他条件) AND  数值(或其他条件);

SELECT  prod_id,prod_price,prod_name

 FROM  products  

WHERE  prod_price BETWEEN 5 AND 10;


空值检查

SELECT列名1,列名2,列名3

FROM表名

Where列名 IS NULL;

SELECT  prod_id,prod_price,prod_name

 FROM  products  

WHERE  prod_price IS NULL;


高级数据过滤

组合WHERE子句

AND操作

SELECT列名1,列名2,列名3

FROM表名

WHERE列名=数值(或其他条件)AND 列名=数值(或其他条件);

SELECT  prod_id,prod_price,prod_name

 FROM  products  

WHERE  vend_id=’DLL01’ AND  prod_price<=4;


OR操作符

SELECT列名1,列名2,列名3

FROM表名

WHERE列名=数值(或其他条件)OR 列名=数值(或其他条件);

SELECT  prod_id,prod_price,prod_name

 FROM  products  

WHERE  vend_id=’DLL01’ OR  vend_id=’BRS01’;


计算次序

SELECT列名1,列名2,列名3

FROM表名

WHERE(列名=数值(或其他条件)OR 列名=数值(或其他条件))AND 列名=数值(其他条件);

SELECT  prod_id,prod_price,prod_name

 FROM  products  

WHERE (vend_id=’DLL01’ OR  vend_id=’BRS01’)AND prod_price>=10;


IN操作符:指定范围

SELECT列名1,列名2,列名3

FROM表名

WHERE列名 IN (条件1,条件2)

ORDER BY列名;

SELECT  prod_id,prod_price,prod_name

 FROM  products  

WHERE vend_id IN (‘DLL01’,‘BRS01’)

ORDER BY prod_name;


NOT操作符:用来否定后面的条件



SELECT列名

FROM表名

WHERE  NOT列名=(条件1,条件2)

ORDER BY列名;

SELECT  prod_name

 FROM  products  

WHERE NOT vend_id=‘DLL01’

ORDER BY prod_name;


用通配符进行过滤

LIKE操作符

百分号(%)通配符:只任意字符出现任意次数

SELECT列名1,列名2,列名3

FROM表名

WHERE列名 LIKE ‘寻找的字段%’;

SELECT  prod_id,prod_price,prod_name

 FROM  products  

WHERE  prod_price LIKE ‘fish%’;


SELECT列名1,列名2,列名3

FROM表名

WHERE列名 LIKE ‘%寻找的字段%’;

SELECT  prod_id,prod_price,prod_name

 FROM  products  

WHERE  prod_price LIKE ‘%fish%’;还有文本的值,不论之前之后出现什么字符。


SELECT列名1

FROM表名

WHERE列名 LIKE ‘首字母%首字母’;

SELECT  prod_name

 FROM  products  

WHERE  prod_name LIKE ‘F%Y’;寻找F起头Y结尾的产品名。


除了一个或多个字符,%还能匹配0个字符。


下划线(_)通配符:与%相同,但只匹配单个字符。

SELECT列名

FROM表名

WHERE列名 LIKE ‘_’;

SELECT  prod_name

 FROM  products  

WHERE  prod_price LIKE ‘_inch teddy bear ’;


SELECT列名

FROM表名

WHERE列名 LIKE ‘%’;

SELECT  prod_name

 FROM  products  

WHERE  prod_price LIKE ‘%  inch teddy bear ’;


方括号([ ])通配符

SELECT列名

FROM表名

WHERE列名  LIKE’[姓名的首字母]%’

ORDER BY列名

SELECT cust_contact

FROM Customers

WHERE cust_contact  LIKE’[JM]%’

ORDER BY cust_contact查询以J或M首字母开头的人名


SELECT列名

FROM表名

WHERE列名  LIKE ’[^姓名的首字母]%’

ORDER BY列名

SELECT cust_contact

FROM Customers

WHERE cust_contact  LIKE’[^JM]%’

ORDER BY cust_contact查询以除了J或M首字母开头的其他人名


SELECT列名

FROM表名

WHERE  NOT列名  LIKE ’[姓名的首字母]%’

ORDER BY列名

SELECT cust_contact

FROM Customers

WHERE NOT cust_contact  LIKE’[JM]%’

ORDER BY cust_contact查询以除了J或M首字母开头的其他人名


使用通用配符技巧



创建计算字段

拼接字段

SELECT列名 + ‘(‘+列名 +’)’

FROM表名

ORDER BY列名;

SELECT vend_name + ‘(‘+ vend_country +’)’

FROM Vendors

ORDER BY vend_name;


SELECT列名 || ‘(‘||列名 ||’)’

FROM表名

ORDER BY列名;

SELECT vend_name || ‘(‘|| vend_country ||’)’

FROM Vendors

ORDER BY vend_name;




去掉空格

SELECT RTRTM(列名)+’(‘+RTRIM(列名)+’)’

FROM表名

ORDER BY列名;

SELECT RTRTM(vend_name)+’(‘+RTRIM(vend_country)+’)’

FROM Vendors

ORDER BY vend_name;


SELECT RTRIM(列名) || ‘(‘||RTRIM(列名) ||’)’

FROM表名

ORDER BY列名;

SELECT RTRIM(vend_name) || ‘(‘||RTRIM( vend_country) ||’)’

FROM Vendors

ORDER BY vend_name;

RTRIM()函数去掉右边的所有空格。LTRIM()函数去掉左边的空格


使用别名:新查询新命名

SELECT RTRTM(列名)+’(‘+RTRIM(列名)+’)’AS别名

FROM表名

ORDER BY列名;

SELECT RTRTM(vend_name)+’(‘+RTRIM(vend_country)+’)’ AS vend_title

FROM Vendors

ORDER BY vend_name;


SELECT RTRIM(列名) || ‘(‘||RTRIM(列名) ||’)’AS新别名

FROM表名

ORDER BY列名;

SELECT RTRIM(vend_name) || ‘(‘||RTRIM( vend_country) ||’)’ AS vend_title

FROM Vendors

ORDER BY vend_name;


执行算术计算

SELECT列名1,列名2,列名3

FROM表名

WHERE条件;

SELECT prod_id,quantity,item_price

FROM OrderItems

WHERE order_num=20008;检索订单号20008中得所有物品


SELECT

列名1,

列名2,

列名3,

列名2*列名3  AS 作为新列名

FROM表名

WHERE条件;

SELECT

prod_id,

quantity,

item_price,

quantity*item_price AS expanded_price

FROM OrderItems

WHERE order_num=20008;


文本处理函数

SELECT列名1,UPPER(列名2) AS

新列名

FROM表名

ORDER BY列名;

SELECT vend_name,UPPER(vend_name) AS

Vend_name_upcase

FROM Vendors  

ORDER BY vend_name;  UPPER将文本转为大写

常用的文本处理函数

LEFT返回串左边的字符RIGTH返回串右边的空格

LENGTH返回串的长度RTRIM去掉穿右边的空格

LOWER将串转换为小写SOUNDEX返回串的SOUNDEX值

LTRIM去掉串左边的空格UPPER将串转换为大写


SOUNDEX()函数将任何文本串转换为描述其语音表示的字母数字模式的算法。能对串进行发音比较。

SELECT列名1,列名2

FROM表名WHE

RE列名=’正确搜索条件’;

SELECT cust_name,cust_contact

FROM Customers

WHERE cust_contact=’Michael Green’;



SELECT列名1,列名2

FROM表名

WHERE SOUNDEX(列名2)=SOUNDEX(‘所有发言匹配条件’);

SELECT cust_name,cust_contact

FROM Customers

WHERE SOUNDEX(cust_contact)=SOUNDEX(‘Michael Green’);


日期和时间处理函数

SELECT列名1

FROM表名

WHERE DATEPART(yy,列名2)=2004;

SELECT order_num

FROM Orders

WHERE DATEPART(yy,order_date)=2004;


DATE_PART()函数

SELECT列名1

FROM表名

WHERE DATE_PART(‘year’,列名2)=2004;

SELECT order_num

FROM Orders

WHERE DATE_PART(‘year’,order_date)=2004;


YEAR()函数

SELECT列名1

FROM表名

WHERE YEAR(列名2)=2004;

SELECT order_num

FROM Orders

WHERE YEAR(order_date)=2004;


Oracle软件日期

SELECT列名1

FROM表名

WHERE to_number(to_char(order_date列名2,’YY’))=数值;

SELECT order_num

FROM Oeders

WHERE to_number(to_char(order_date,’YY’))=2004;to_number将提取成分转换为数值,to_char()函数用来提取日期成分。


BETWEEN()操作符

SELECT列名1

FROM表名

WHERE列名2  BETWEEN to_date(‘日期’)

AND to_date(‘日期’);

SELECT order_num

FROM Orders

WHERE order_date BETWEEN to_date(‘01-JAN-2004’)

AND to_date(‘31-DEC-2004); to_date()函数用来将两个串转换为日期。


常用数值处理函数

ABS()返回一个数的绝对值SIN()返回一个角的正弦

COS()返回一个角的余弦SQRT()返回一个数的平方根

EXP()返回一个数的指数值TAN()返回一个角的正切

PI()返回圆周率  



汇总数据

SQL聚集函数

AVG()返回某列平均值MIN()返回某列最小值

COUNT()返回某列行数SUM()返回某列值之和

MAX()返回某列最大值  


AVG()函数

SELECT AVG(列名) AS新列名

FROM表名;

SELECT AVG(prod_price) AS avg_price

FROM Products;


确定特定列和行的均值

SELECT AVG(列名1) AS 新列名

FROM表名

WHERE列名2=条件;

SELECT AVG(prod_price) AS avg_price

FROM Products

WHERE vend_id=’DLL01’;


COUNT()函数

COUNT(*)对表中行的数目进行计数,不管表列中包含的是空值(NULL)还是非空值。

COUNT(column)对特定列中具有值的行进行计数,忽略NULL值。


SELECT COUNT(*) AS 新列名

FROM表名;

SELECT COUNT(*) AS num_cust

FROM Customers;


SELECT COUNT(列名) AS 新列名

FROM表名;

SELECT COUNT(cust_email) AS num_cust

FROM Customers;


MAX()函数

SELECT MAX(列名) AS 新列名

FROM表名;

SELECT MAX(prod_price) AS  max_price

FROM Customers;


MIN()函数

SELECT MIN(列名) AS 新列名

FROM表名;

SELECT MIN(prod_price) AS  max_price

FROM Customers;


SUM()函数

SELECT SUM(列名) AS 新列名

FROM表名;

WHERE列名2=条件

SELECT SUM(quantity) AS  items_ordered

FROM OrderItems;

WHERE order_num=20005;


SELECT SUM(列名) AS 新列名

FROM表名;

WHERE列名2=条件

SELECT SUM(item_price*quantity) AS  total_price

FROM OrderItems;

WHERE order_num=20005;


聚集不同值

DISTINCT():只考虑各个不同的价格

SELECT AVG(DISTINCT列名1) AS 新列名

FROM表名

WHERE列名2=条件;

DISTINCT():只考虑各个不同的价格

SELECT AVG(DISTINCT prod_price) AS avg_price

FROM Products

WHERE vend_id=’DLL01’;


组合聚集函数

SELECT COUNT(*) AS新列名1,

MIN(列名) AS 新列名2,

MAX(列名) AS 新列名3,

AVG(列名)AS 新列名4

FROM表名;

SELECT COUNT(*) AS num_items,

MIN(prod_price) AS price_min,

MAX(prod_price) AS price_max,

AVG(prod_price) AS price_avg

FROM Product;


分组数据

数据分组

SELECT COUNT(*)  AS新列名

FROM表名

WHERE列名=条件;

SELECT COUNT(*) AS num_prods

FROM Products

WHERE vend_id=’DLL01’;


GROUP BY()函数创建分组

SELECT列名1,COUNT(*) AS 新列名

FROM表名

GROUP BY列名2;

SELECT vend_id,COUNT(*) AS num_prods

FROM Products

GROUP BY vend_id;


过滤分组

SELECT列名,COUNT(*) AS 新列名

FROM表名

GROUP BY列名

HAVING COUNT(*)>=2;

SELECT cust_id,COUNT(*) AS orders

FROM Orders

GROUP BY cust_id

HAVING COUNT(*)>=2;过滤掉大于等于2的分组。



SELECT列名,COUNT(*) AS 新列名

FROM表名

WHERE列名>=4

GRUUP BY列名

HAVING COUNT(*)>=2;

SELECT vend_id,COUNT(*) AS num_prods

FROM Products

WHERE prod_price>=4

GRUUP BY vend_id

HAVING COUNT(*)>=2;


分组和排序



SELECT列名,COUNT(*) AS 新列名

FROM表名

GROUP BY列名

HAVING COUNT(*)>=3;

SELECT order_num,COUNT(*) AS items

FROM OrderItems

GROUP BY order_num

HAVING COUNT(*)>=3;


SELECT列名,COUNT(*) AS 新列名

FROM表名

GROUP BY列名

HAVING COUNT(*)>=3

ORDER BY items,order_num;

SELECT order_num,COUNT(*) AS items

FROM OrderItems

GROUP BY order_num

HAVING COUNT(*)>=3

ORDER BY items, order_num;


SELECT子句顺序



使用子句查询

①SELECT列名1

FROM表名

WHERE列名2=条件;

SELECT order_num

FROM OrderItems

WHERE prod_id=’RGAN01’;


②SELECT列名1

FROM表名

WHERE列名2 IN(设置区间);

SELECT cust_id

FROM Orders

WHERE order_num IN(20007,20008);


将第一个查询变为子查询组合两个查询

SELECT列名1

FROM表名1

WHERE列名2IN (SELECT 列名2

FROM表名2

WHERE列名3=条件);

SELECT cust_id

FROM Orders

WHERE order_num IN (SELECT order_num

                    FROM OrderItems

                    WHERE prod_id=’RGAN01’);

首先,

在SELEC下语句中,子查询总是从内向外处理;在处理上面的SELECT语句时,DAMS实际上执行了两个操作。

首先,它执行下面的查询:

SELECT order_num FROM orderitems WHERE prod_ id=’RGAN01’

此查询返回两个订单号:20007和20008。然后,这两个值以工IN操作符要求的逗号分隔的格式传递给外部查询的WHERE子句。

外部查询变成;

SELECT cust id FROM orders WHERE order num TN (20007,20008)

可以看到,输出是正确的并且与前面硬编码WHEi}E子句所返回的值相同。


检索查询

SELECT列名1,列名2

FROM表名

WHERE列名3 IN(搜索区间);

SELECT cust_name,cust_contact

FROM Customers

WHERE  cust_id IN(‘1000004’,’10000005’);


将WHERE子句转换为查询

SELECT列名1,列名2

FROM表名1

WHERE列名3 IN(SELECT 列名3

FROM表名2

WHERE列名4 IN(SELECT 列名4

FROM表名3

WHERE列名5=条件));

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语句,DBMS实际上必须执行3条SELECT语句。最里边的子查询返回订单号列表,此列表用于其外面的子查询的WHERE子句。外面的子查询返回客户ID列表,此客户ID列表用于最外层查询的WHERE子句。最外层查询确实返回所需的数据。


作为计算字段使用子查询

使用SELECT(COUNT*)对表中的行进行计数,并且通过提供一条WHERE了句来过滤某个特定的客户ID,可仅对该客户的订单进行计数。

SELECT COUNT(*)AS新列名

FROM表名

WHERE列名=条件;

SELECT COUNT(*)AS orders

FROM Orders

WHERE cust id=’1000000001‘;


SELECT列名1,

列名2,

(SELECT COUNT(*)

FROM表名1

WHERE条件=条件)  AS

新列名

FROM表名

OROER BY列名1;

SELECT  cust_ name,

cust_ state,

(SELECT COUNT(*)

        FROM Orders

        WHERE Orders.cust_ id=Customers.cust_ id)  AS

orders

FROM Gustomers

OROER BY cust_ name;


联结表

创建联结

SELECT列名1,列名2,列名3

FROM表名1,表名2

WHERE表1中的关联条件=表2中的关联条件;

SELECT vend_name,prod_name,prod_price

FROM Vendors,Products

WHERE Vendors.vend_id=Products.vend_id;


笛卡儿积:检索出的行的数目将是第一个表中的行数乘以第二个表中的行数。

SELECT列名1,列名2,列名3

FROM表名1,表名2;

SELECT vend_name,prod_name,prod_price

FROM Vendors,Products;

从上面的输出中可以看到,相应的笛卡儿积不是我们所想要的。这里返回的数据用每个供应商匹配了每个产品,它包括了供应商不正确的产品。实际上有的供应商根本就没有产品。


内部联结:目前为止所用的联结称为等值联结,它基于两个表之间的相等测试。

SELECT列名1,,列名2,列名3

FROM表名1  INNER JOIN表名2

ON表1关联条件=表2关联条件;

SELECT vend_name,,prod_ name,prod_price

FROM Vendors  INNER JOIN Products

  ON Vendors.vend_ id=Products.vend_ id;

这里两个表之间的关系是FROM子句的组成部分,以INNERJOIN指定。在使用这种语法时,联结条件用特定的ON子句而不是WHERE子句给出。传递给ON的实际条件与传递给WHERE的相同。


联结多个表

SELECT列名1, 列名2, 列名3, 列名4

FROM表名1,表名2,表名3

WHERE表1条件=表1条件

AND表3条件=表1条件

AND筛选条件;

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;


SEiECT列名1,列名2

FRDM Customers表1,表2,表3

WHERE表1条件=表2条件

ANO表3条件=表1条件

AND筛选条件;

SEiECT cost name,cust_contact

FRDM Customers,Orders,OrderItems

WHERE Customers.cost_id =Orders.cust _id

ANO OrderItems.order_ nom=Orders.Order_nom

AND prod_id=’RGAN01’;


创建高级联结

请看下而的SELECT语句。它与之前所用的语句基本相同,但改成了使用别名:

SELECT列名1,列名2

FROM表名1AS别名1,表2AS别名2, 表3 AS别名3

WHERE表1=条件

AND表2=条件

AND表3=条件;

SELECT cust_ name,cust_ contact

FROM Customers AS C, Orders AS 0, OrderItems AS OI

WHERE C.cust_id=0.cust_id

  AND OI.order_ num=O.order_ num

  AND prod_id=’RGAN01’;

应该注意,表别名只在查询执行中使用。与列别名不一样,表别名不返回到客户机。


使用不同类型的联结

自联结

SELECT列名1,列名2, 列名3

FROM表

WHERE列名2=(SELECT列名2

FRDM表

WHERE列名3=条件);

SELECT cust_ id,cust_name, cust_contact

FROM Customers

WHERE cust_ name=(SELECT oust_ name

      FRDM Customers

    WHERE oust_ contact=’Jim Jones’);


SELECT列别名1,列别名2,列别名3

FROM表AS别名,表 AS别名

WHERE列别名1=列别名4

AND列别名5=条件;

SELECT c1.cust_ id,c1.cust_ name,c1 .cuss_ contact

FROM Customers AS c1,Customers ASc2

WHERE c1 .cust_name=c2.cust_ name

  AND c2.cust _contact=’Jim Jones’;

用自联结而不用子查询自联结通常作为外部语句用来替代从相同表中检索数据的使用子查询语句。虽然最终的结果是相同的,但许多DBMS处理联结远比处理子查询快得多。应该试

一下两种方法,以确定哪一种的性能更好。


自然联结:只能选择那些唯一的列。这一般是通过对表使用通配符(SELECT*),对所有其他表的列使用明确的子集来完成的。

SELECT  C.*,列别名1, 列别名2,列别名3,

列别名4,列别名5

FROM表1 AS 表别名1,表2AS表别名2,表3 AS 表别名3

WHERE列别名3=列别名6

AND列别名1=列别名7

AND列别名3=条件;

SELECT  C.*,0.order_ num, 0.order_date,OI .prod_id,

OI.quantity,OI .item_ price

FROM Customers AS C,Orders AS 0,OrderItems AS OI

WHERE C.cust_id=O.cust_id

  AND OI .order_num=0.order_num

  AND prod _id=’RGANOi’;


外部联结:许多联结将一个表中的行与另一个表中的行相关联。

SELECT列别名1,列别名2

FROM表1 LEFT OUTER JOIN 表2

ON列别名1=列别名3;

SELECT Customers.cost_ id,Orders.order_nom

FROM Customers LEFT OUTER JOIN orders

  ON Customers.cost_ id=orders.Cust_id;

这条SELECT语句使用了关键字OUTER  JOIN来指定联结的类型(而不是在WHERE子句中

指定)。但是与内部联结关联两个表中的行不同的是,外部联结还包括没有关联行的行。在使用OUTER  JOIN语法时,必须使用RTGHT或LEFT关键字指定包括其所有行的表(RTGHT指出的是OUTER  JOIN右边的表,而LEFT指出的是OUTER JOIN左边的表)。上面的例子使用LEFT OUTER  JOIN从FROM子句的左边表(Customers表)中选择所有行。


SELECT列别名1,列别名2

FROM表1 RIGHT OUTER JOIN 表2

ON列别名3=列别名1;

SELECT Customers.cust_id,Orders.order_num

FROM Customers RIGHT OUTER JOIN Orders

ON Orders.cust_ id=Customers.oust _id;为了从右边的表中选择所有行,应该使用RIGHT  OUTER  JOIN。


SQL服务器额外支持一种简化的外部联结语法。

SELECT列别名1 ,列别名2

FROM表1,表2

WHERE列别名1*=列别名3;

SELECT Customers.cust_id ,Orders.order_num

FROM Customers,Orders

WHERE Customers.cust_id*=Orders.cust_ id;

这里的联结条件是在WHERE子句中规定的。与使用=号的相等测试不一样,*=操作符用来指定应该包括Customers表中的每一行。*=为左外部联结操作符。它从左边表中检索所有行。与左外部联结相对的是右外部联结,由=*指定。可用它来返回列在操作符右边的表中所有行。


全外部联结语法:全外部联结包含来自两个表的不关联的行。

SELECT列别名1,列别名2

FROM表1 FULL OUTER JOIN表2

ON列别名3=列别名1;

SELECT Customers .cust_ id,Orders.order_ num

FROM Orders FULL OUTER JOIN Customers

  ON Ordars.cust_id=Customers.Cust_id;


使用带聚集函数的联结

SELECT列别名1,COUNT(列别名2)  AS 列别名3

FROM表1 INNER JOIN 表2

ON列别名1=列别名4

GROUP BY列别名1;

SELECT Customers.cust_id,COUNT(Orders.order_num)  AS num_ord

FROM Customers INNER JOIN Ordors

  ON Customers.cust_ id=Orders.cust_id

GROUP BY Customers.cust_id;


此SELECT语句使用INNER JO工闪将Customers和Orders表互

相关联。GROUP日Y子句按客户分组数据,因此,函数调用

COUN丁(Orders.order_ num)对娜个客户的订单计数,将它作为

num ord返回。


SELECT列别名1,COUNT(列别名2) AS 新列别名

FROM表1 LEFT  OUTER  JOIN 表2

ON列别名1=列别名3

GROUP BY列别名1;

SELECT Customers.cust_ id,COUNT(Orders.order_num) AS num_ord

FROM Customers LEFT  OUTER  JOIN Orders

  ON Customers.Cust_id=Orders.cust_ id

GROUP BY Customers cust_ id;


组合查询

SQL也允许执行多个查询(多条SELECT语句),并将结果作为单个查询结果集返回。这些组合查询通常称为并或复合查询。

有两种基本情况,其中需要使用组合查询:1在单个查询中从不同的表类似返同结构数据。

2对单个表执行多个查询,按单个查询返问数据。

创建组合查询

使用UNION

单句1

SELECT列名1,列名2 ,列名3

FROM表

WHERE列名4  IN(‘IL’,’IN’,’MI’);

单句2

SELECT列名1,列名2,列名3

FROM表

WHERE列名1=条件;

组合句

SELECT列名1,列名2 ,列名3

FROM表

WHERE列名4  IN(‘IL’,’IN’,’MI’);UNION

SELECT列名1,列名2,列名3

FROM表

WHERE列名1=条件;


单句1

SELECT cust_name,cust _contact ,cust_ email

FROM Customers

WHERE cust _state  IN(‘IL’,’IN’,’MI’);

单句2

SELECT cost_ name,cost contact .cost email

FROM Customers

WHERE cost_ name=’Fun4All’;

组合句

SELECT cost_ name,cost contact.cost email

FROM Customers

WHERE cost _state IN(‘IL’,’IN’,’MI’)

UNION

SELECT cost_ name,cost_ contact,cost_ email

FROM Customers

WHERE cust_name=’Fun4All’;


1.UNION必须由两条或两条以上的SELECT语句组成,语句之间用关键字UNTON分隔(因此,如果组合4条SELECT语句,将要使用3个UNTON关键字)。

2.UNION中的每个查询必须包含相同的列、表达式或聚集函数(不过各个列不需要以相同的次序列出)。

3.列数据类型必须兼容:类型不必完全相同,但必须是DBMS可以隐含地转换的类型(例如,不同的数值类型或不同的日期类型)。


包含或取消重复的行

UNION从查询结果集中自动去除了重复的行(换句话说,它的行为与单条SELECT语句中使用多个WHERE子句条件一样)。这是UNION的默认行为,但是如果愿意,可以改变它。事实上,如果想返回所有匹配行,可使用UNION ALL而不是UNION。

SELECT列名1,列名2,列名3

FROM表

WHERE列名4 IN(‘IL’,’IN’,’MI’)

UNION ALL

SELECT列名1,列名2,列名3

FROM表

WHERE列名5=条件;


对组合查询结果排序群

SELECT语句的输出用ORDER  BY子句排序。在用UNION组合查询时,只能使用一条ORDER  BY子句,它必须出现在最后一条 SELECT语句之后。对于结果集,不存在用一种方式排序一部分,而又用另一种方式排序另一部分的情况,因此不允许使用多条ORDER BY子句。

下面的例子排序前面UNION返回的结果:

SELECT列名1, 列名2,列名3

FROM表

WHERE列名1 IN(‘IL’,'IN',’MI’)

ONION

SELECT列名1, 列名2,列名3

FROM表

WHERE列名1=条件

ORDER BY列名1,列名2;

SELECT cust_ name, cust_ contact,cust_email

FROM Customers

WHERE cust_ state IN(‘IL’,'IN',’MI’)

ONION

SELECT cust_ name,cust_ contact,cust_email

FROM Customers

WHERE cust _name=’Fun4Al1’

ORDER BY cust _name,cust_ contact;


插入数据

插入完整的行

INSERT语法:把数据插入表中的最简单的方法是使用基本的INSERT语法,它要求指定表名和被插入到新行中的值。

INSERT INTO表

VALUES(插入的变量‘’,‘’,‘’,

NULL,

          NULL);

INSERT INTO Customers

VALUES(‘1000000006’,

        ‘Toy Land’

        ‘123 Any Street’

        'New York’,

        ‘NY’,

         ‘11111’,

          ‘USA’,

NULL,

          NULL);

此例子插入一个新客户到Customers表。存储到每个表列中的数据在VALUES子句中给出,对每个列必须提供一个值。如果某个列没有值,应该使用NULL值(假定表允许对该列指定空值)。各个列必须以它们在表定义中出现的次序填充。

编写INSERT语句的更安全〔不过更烦琐)的方法如下:

INSERT INTO表(列名1,

列名2,

列名3,

列名4,

列名5,

VALUES(加入新变量‘’,

NULL空值,

NULL);

INSERT INTO Customers(cust_ id,

cust_ name,

cust_ address,

cust_city,

cust_ state,

cust_ zip,

oust-country,

cust_ contact,

    cust_ email)

VALUES('1000000006’,

      ‘Toy Land’,

      ‘123 Any Street’,

‘New York’

‘NY’.

‘1111’,

‘USA’,

NULL,

NULL);


插入部分行

INSERT INTO表(列名1,

列名2,

列名3,

列名4,

列名5,

VALUES(加入新变量‘’);

INSERT INTO Customers(cust_ id,

cust_ name,

cust_ address,

cust_city,

cust_ state,

cust_ zip,

    oust-country)

VALUES('1000000006’,

      ‘Toy Land’,

      ‘123 Any Street’,

‘New York’

‘NY’.

‘1111’,

‘USA’);

省略的列必须满足以下某个条件:

1.该列定义为允许NULL值(无值或空值)。

2.在表定义中给出默认值。这表示如果不给出值,将使用默认值。

如果对表中不允许NULL值且没有默认值的列不给出值,则DBMS将产生一条错误消息,并且相应的行插入不成功。


插入检索出的数据

INSERT一般用来给表插入一个指定列值的行。但是, INSERT还存在另一种形式,可以利用它将一条SELEC下语句的结果插入表中。这就是所谓的INSERT SELECT顾名思义,它是由一条 INSERT语句和一条SELECT语句组成的。

INSERT INTO表1(表1中的列名)

SELECT表1中的列名

EROM表2;

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

EROM CustNew;

这个例了使用INSERT  SELECT从CustNew中将所有数据导入Customers。 SELECT语句从CustNew检索出要插入的值,而不是列出它们。SELECT中列出的每个列对应于Customers表名后所跟的列表中的每个列。这条语句将插入多少行有赖于CustNew表中有多少行。如果这个表为空,则没有行被插入(也不产生错误,因为操作仍然是合法的)。如果这个表确实含有数据,则所有数据将被插入到Customers。


从一个表复制到另一个表

SELECT  INTO语句:

SELECT *

INTO新表

FROM表;

SELECT

SELECT *

INTO CustCopy

FROM Customers;

SELECT

这条SELECT语句创建一个名为CustCopy的新表,并把Customers表的整个内容复制到新表中。因为这里使用的是*,所以将在CustCopy表中创建(并填充)与Customers表中得个列相同的列。要想只复制列的子集,可明确地给出列名而不是使用*通配符。


更新和删除数据

UPDATE语句更新数据

1.更新表中特定行;

2.更新表中所有行。

UPDATE表

SET列名=新值

WHERE列名2=过滤条件;

UPDATE Customers

SET cust email=’[email protected]

WHERE cust_id=’1000000005’;


UPDATE表

SET列名1=更新条件,

列名2=更新条件

WHERE列名3=过滤条件;

UPDATE Customers

SET cust _contact=’Sam Roberts’,

      Cust_ email=’[email protected]

WHERE cust id=’1000000006’;

在更新多个列时,只需要使用单个SET命令,每个“列=值”对之间用逗号分隔(最后一列之后不用逗号)二在此例子中,更新客户1000000006的cust contact和Gust email列。


为了册(除某个列的值,可设置它为NULL(假如表定义允许NULL值)。

UPDATE表

SET c列名1=空值

WHERE列名2=过滤条件;

UPDATE Customers

SET cust_ email=NULL

WHERE cust_ id=’000000005’;


删除数据

DELETE语句

1.从表中删除特定的行:

2.从表中删除所有行。

DELETE FROM表

WHERE列名 =删除条件;

DELETE FROM Customers

WHERE cust_id =’1000000006’;


DELETE不需要列名或通配符。DELETE删除整行而不是删除列。为了删除指定的列,请使用UPDATE语句。

如果想从表中删除所有行,不要使用DELETEo

可使用TRUNCATE TABLE语句,它完成相同的工作,但速度更快(因为不记录数据的变动)。


创建和操纵表

创建表

1.多数DBMS都具有交互式创建和管理表的工具;

2.表也可以直接用SQL语句操纵。

表创建基础

CREATE TABLE表

(变量);

CREATE TABLE Products

(

    prod_ id     CHAR(10)  NOT NULL,

    vend_ id     CHAR(10)   NOT NULL,

    Prod_name   CHAR(254)   NOT NULL

prod_ price   DECIMALS,2)  NOT NULL

    prod_ desc    VARCHAR(1000)    NULL

);


创建混合了NULL和NOT NULL列的表:

CREATE TABLE表

(列名 字段 是否空值);

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语句的列定义中用关键字DEFAULT指定。

CREATE TABLE表

(列名  字段 是否空值 指定默认值);

CREATE TABLE OrderItems

(

      order _num    INTEGER  NOT NULL,

      Order_ item   INTEGER   NOT NULL,

    prod_id      CHAR(10)   NOT NULL,

      quantity     INTEGER  NOT NULL       DEFAULT  1,

Item_price   DECTMAL(8,2)   NOT NULL,

);


系统数据      函数变量

Access   NEW()PostgreSQL  CURRENT_DATE

DB2    CURRENT_DATESQL Server     GETDATE()

MySQL   CURRENT_DATE()Sybase      GETDATE()

Oracle    SYSDATE 


更新表:使用ALTER  TABLE语句

给已有表增加列

ALTER TABLE表

ADD增加列 字段;

ALTER TABLE Vendors

ADD vend _phone CHAR(20);


删除过程

ALTER TABLE表

DROP COLUMN删除列名;

ALTER TABLE  Vendors

DROP COLUMN  vend_phone;


删除表

DROP TABLE表名;


重命名表

使用RENAME语句


使用视图

SELECT列名1,列名2

FROM视图名

WHERE列名3=条件;

SELECT cost _name,oust _contact

FROM ProductCustomers

WHERE prod_id=’RGAN01’;

ProductCustomers是一个视图,作为视图,它不包含任何列或数据,它包含的是一个查询。视图不包含数据,所以每次使用视图时,都必须处理查询执行时所需的任一个检索。


创建视图

CREATE  VIEW  viewname;

用DROP删除视图:其语法为DROP VIEW  viewname;

覆盖(或更新)视图必须先DROP它,然后再重新创建它。


利用视图简化复杂的联结

CREATE  VIEW视图 AS

SELECT列名1,列名2,列名3

FROM表1,表2,表3

WHERE联结1=联结2

AND联结3=联结4;

CREATE  VIEW ProductCustomers AS

SELECT cust_ name,cust_contact,prod_id

FROM Customers,Orders, Orderltems

WHERE Customers.cust_id=Orders.cost_ id

  AND OrderItems.order_ nom=Orders.order_ nom;


用视图重新格式化检索的数据

CREATE  VIEW视图 AS

SELECT  RTRIM(列名1)+’(‘+RTRIM(列名2)+’)’AS别名

FROM表;

CREATE  VIEW VendorLocations AS

SELECT  RTRIM(vend_ name)+’(‘+RTRIM(vend_ country)+’)’ AS vend_ title

FROM Vendors;


下面是使用||语法的相同语句:

CREATE  VIEW视图 AS

SELECT  RTRIM(列名1)||’(‘|| RTRIM(列名2)||’)’AS别名

FROM表;

CREATE  VIEW VendorLocations AS

SELECT  RTRIM(vend_ name)||’(‘|| RTRIM(vend_country)||’)’ AS vend_title

FROM Vendors;


检索出以创建所有邮件标签的数据

SELECT*

FROM视图;


用视图过滤不想要的数据

CREATE  VIEW视图 AS

SELECT列名1,列名2,列名3

FRDM表

WHERE列名3  IS  NOT NULL;

CREATE  VIEW CustomerEMailList  AS

SELECT  cust_ id,cust_ name,cust_ email

FRDM Customers

WHERE cust_ email  IS  NOT NULL;


检索出以创建所有邮件标签的数据

SELECT*

FROM视图名


使用视图与计算字段

CREATE VIEW视图

SELECT列名

乘积AS别名

FROM表;

CREATE VIEW OrderItemsExpanded

SELECT order_ num,

prod_id,

        quantity,

item_price,

        quantity*item_price  AS  expanded_price

FROM OrderItems;


检索出以创建所有邮件标签的数据

SELECF*

FROM视图

WHERE过滤条件;

SELECF*

FROM OrderItemsExpanded

WHERE order_ num=20008;


使用存储过程

EXECUTE执行存储过程的语句

EXECUTE储存新产品到表中(参数1,参数2,参数3,参数4)

EXECUTE AddNewProduct(‘JTS01’,

’Stuffed Eiffel Tower’,

6.49,

‘Plush stuffed toy with the text La Tour Eiffrl

in red white and blue’)

这里执行一个名为AddNewProduct的存储过程;它将一个新产品添加到Products表。AddNewProduct有4个参数,分别是:供应商ID (Vendors表的主键)、产品名、价格和描述。这4个参数匹配存储过程中4个预期的变量(定义为存储过程自身的组成部分)。此存储过程添加新行到Products表并将传入的属性赋给相应的列。


创建存储过程

下面是该过程的Oracle版本:

CREATE PROCECURE参数

(参数 OUT NUMBER)

IS

BEGIN

SELEGT*FROM表

WHERE NOT列名 IS NULL;

参数:=SQL%ROWCOUNT;

END;

CREATE PROCECURE MailingListCount

(ListCount OUT NUMBER)

IS

BEGIN

      SELEGT*FROM Customers

    WHERE NOT cust_ email IS NULL;

      ListCount:=SQL%ROWCOUNT;

END;

此存储过程有一个名为ListCount的参数。此参数从存储过程

返回一个值而不是传递一个值给存储过程。关键字OUT用来指

示这种行为。Oracle支持IN(传递值给存储过程)、OUT(从存储过程返

回值,如这里所示)、INOUT(既传递值给存储过程也从存储过程传回值)

类型的参数。存储过程的代码括在BEGIN和END语句中,这里的执行一条

简单的SELECT语句,它检索具有邮件地址的客户。然后用检索出的行数

设置ListCount(要传递的输出参数)。


下面是Microsoft SQL Server版本:

CREATE PROCEDURE MailingListCount

AS

DECLARE @cnt INTEGER

SELECT @cnt=COUNT(*)

FROM Customers

WHERE NOT cust_ email IS NULL;

RETURN @cnt;


下面是另一个例子,这次在Orders表中插入一个新订单。此程序仅

适用于SQL Server但它说明了存储过程的某些用途和技术:

CREATE PROCEDiJRE NewOrder @cust_ id CHAR(10)

AS

    Declare variable for order number

DECLARE @order_ num INTEGER

    Get current highest order number

SELECT @order_num=MAX(order_num)

FROM Orders

    Determine next order number

SELECT @order_num=@order_num+1

      Insert new order

INSERT INTO Orders(order_num, order_ date,cust_id)

VALUES(@order_ num,GETDATE(),@cust_id)

    Return order number

RETURN @order _num;


下面是相同SQL Server代码的相当不同的版本:

CREATE PROCEDURE NewOrder @cust_ id CHAR(10)

AS

    Insert  new order

INSERT INTO Orders(cust_id)

VALUES(@cust_ id)

    Return order number

SELECT order _num=@@IDENTITY;


管理事务处理

事务处理术语

1.事务(transaction)指一组SQL语句;

2.回退(rollback)’指撤销指定SQL语句的过程;

3.提交(commit)指将未存储的SQL语句结果写入数据库表;

4.保留点(savepoint)指事务处理中设置的临时占位符( placeholder ),你可以对它发布回退(与回退整个事务处理不同)。

可以回退哪些语句?事务处理用来管理INSERT,UPDATE和CELETE语句。不能回退SELECT语句(回退SELECT语句也没有多少必要),也不能回退CREATE或DROP操作。事务处理中可以使用这些语句,但进行回退时,它们不被撤销。


管理事务处理

在SQL Server:

BEGIN TRANSACTION

COMMIT TRANSACTION


使用ROLLBACK撤回语句

DELETE FROG Orders;

ROLLBACK;


使用COMMIT提交语句

在SQL Server:

BEGIN TRANSACTION

DELETE OrderItems WHERL order _num=12345

DELETE Orders WHERE order_ num=12345

COMMIT TRANSACTION


为在Oracle完成相同的工作,可如下进行;

DELETE OrderItems WHERE order_ num=12345;

DELETE  Orders WHERE order _num=12345;

COMMIT;


使用保留点

在SQL中,这些占位符称为保留点。为了在MySQL和Oracle中创建占立符,可如下使用SAVEPOINT语句:

SAVEPOINT delete1;


使用游标

创建游标:游标用DECLARE语句创建

下面是创建此游标的DB2, SQL Server和Sybase版本:

DECLARE CustCursor CURSOR

FOR

SELECT*FROM Customers

WHERE cust _email IS NULL

下面是Oracle和PostgreSQL版本:

DECLARE CURSOR CustCursor

IS

SELECT*FROM Customers

WHERE cust_ email IS NULL


使用游标

游标用OPEN CURSOR语句来打开:

OPEN CURSOR CustGursor


用FETCH语句访问游标数据

DECLARE TYPE CustCursor IS REF CURSOR

 RETURN Customers%ROWTYPE;

DECLARE CustRecord Customers%ROWTYPE

BEGIN

      OPEN CustCursor;

      FETCH CustCursor INTO CustRecord;

      CLOSE CustCursor;

END;

在这个例子中,FETCH用来检索当前行(自动从第一行开始)到声明的变量CustRecord中。刘于检索出来的数据没做任何其他处理。


DECLARE TYPE CustCursor IS REF CURSOR

      RETURN Gustomers%ROWTYPE;

DECLARE CustRecord Customers%ROWTYPE

BEGIN

      OPEN CustCursor;

      LOOP

      FETCH CustCursor INTO CustRecord;

LXIT WHEN CustCursor%NOTFOUND;

END LOOP;

CLOSE CustCursor;

END;

为CustRecord的变量中。但与前一个例子不一样,这里的FETCH位于LOOP内,因此它反复执行。代码EXIT WHEN CustCursor%NOTFOUN使处理在取不出更多的行时终止(退出循环)。这个例子也没有做实际的处理;在实际的例子中可用具体的处理代码替换占位符…。


关闭游标

CLOSE CustCursor


约束:管理如何插入或处理数据库数据的规则。


创建触发器:用CREATE  TRIGGER语。

CREATE TRIGGER newproduct AFTER INSERT ON products

FOR EACH ROW SELECT’Product added’;

CREATE  TRIGGER用来创建名为newproduct的新触发器。触发器可在一个操作发生之前或之后执行,这里给出了AFTER  INSERT,所以此触发器将在INSERT语句成功执行后执行。这个触发器还指定FOR EACH ROW,因此代码对每个插入行执行。在这个例子中,文本Product added将对每个插入的行显示一次。


触发器只支持表,视图不支持(临时表也不支持)

每个表每个事件每次只允许一个触发器。因此,每个表最多支持6个触发器(每条INSERT、UPDATE和DELETE的之前和之后)。单一触发器不能与多个事件或多个表关联,所以,如果你需要一个对INSERT和UPDATE操作执行的触发器,则应该定义两个触发器。


删除触发器

DROP TRIGGER newproduct;


INSERT触发器

1.在INSER下触发器代码内,可引用一个名为NEW的虚拟表,访问被插入的行;

2.在BEFORE INSERT触发器中,NEW中的值也可以被更新(允许更改被插入的值);

3.对于AUTO INCREMENT列,NEW在INSERT执行之前包含0,在INSERT执行之后包含新的自动生成值。


新生成值

CREATE TRIGGER neworder AFTER INSERT ON orders

FOR EACH ROW SELECT NEW.order_num;


INSERT INTO orders(order_date,cust_id)

VALUES(Now(),10001);


DELETE触发器

1.在DELETE触发器代码内,你可以引用一个名为OLD的虚拟表,访问被删除的行;

2.OLD中的值全都是只读的,不能更新。


CREATE TRIGGER  deleteorder BEFORE DELETE ON orders

FOR EACH ROW

BEGIN

    INSERT INTO  archive_orders(order_num,order_ date, cust_ id)

    VALUES(OLD.order_num, OLD.order_date,OLD.cust_ id);

END;


UPDATE触发器

1.在UPDATE触发器代码中,你可以引用一个名为OLD的虚拟表访问 以前(U P DAT E语句前)的值,引用一个名为NEW的虚拟表访问新更新的值;

2.在BEFORE UPDATE触发器中,NEW中的值可能也被更新(允许更改将要用于UPDATE语句中的值);

3. OLD中的值全都是只读的,不能更新。


CREATE TRIGGER updatevendor BEFORE UPDATE ON vendors

FOR EACH ROW SET NEW.vend_ state=Upper(NEW:vend_state);








SELECT列名1,列名2,列名3

FROM表名

Where列名=数值(或其他条件);

SELECT  prod_id,prod_price,prod_name

 FROM  products  

WHERE  prod_price=3.95;

你可能感兴趣的:(2019-06-01 SQL笔记)