SQL 可分成如下几组:
DML(Data Manipulation Language,数据操作语言):
用于检索或者修改数据;
DDL(Data Definition Language,数据定义语言):
用于定义数据的结构,比如创建,修改或者删除数据库对象;
DCL(Data Control Language,数据控制语言):
用于定义数据库用户的权限。
DML组可以细分为以下的几个语句;
SELECT:用于检索数据;
INSERT:用于增加数据到数据库;
UPDATE:用于从数据库中修改闲存的数据;
DELETE:用于从数据库中删除数据。
DDL语句可以用于创建用户和重建数据库对象。
CREATE TABLE
ALTER TABLE
DROP TABLE
CREATE INDEX
DROP INDEX
DCL命令用于创建关系用户访问以及授权的对象。
ALTER PASSWORD
GRANT
REVOKE
CREATE SYNONYM
表的基础知识:
关系数据库通常包含多个表。数据库实际上是表的集合,
数据库的数据或信息都是存储在表中的。
表是对数据进行存储和操作的一种逻辑结构,每一个表都代表一个
对用户意义的对象。
数据检索:SELECT语法:
select "列名1"[,"列名2",etc] from "表名" [where "条件"];
注释:[]表示可选;
你可以指定多个列,或者使用‘*’来选择所有的列。
条件:= 等于;>大于;<小于;>=大于等于;<=小于等于;<>不等于;LIKE;
其中LIKE 中可以用百分号‘%’匹配任何可能的字符。
例:select first,last from empinfo where last LIKE '%s';
select * from empinfo where first = 'Eric';
创建表:语法:
CREATE TABLE "表名"
("列名" "数据类型" [约束],
"列名2" "数据类型" [约束],
"列名3" "数据类型" [约束]);
注释:表格和列名必须以字母开头,第二个字符开始可以说字母,数字或者下划线。
但是要保证名字的总长度不要超过30个字符。
数据类型:char(size):固定长度的字符串型。size是圆括号中指定的参数,
它可以由用户随意设置,但是不能超过255个字节。
varchar(size):变长度的字符串型。它的最大长度是由括号中的参数
size设定的。
number(size):数值型。最大数字的位数由括号中的参数size设置。
date:日期数值型。
number(size,d):数值型。它的最大数字的位数由括号中的参数size设定,
而括号中的参数d是设置小数点的位数。
约束:当表被创建的时候,可以一列也可以多列共用一个约束。约束是一个跟列有关的
的基本准则,返回的数据必须遵循这个准则。
插入数据到表:
语法:INSERT into "表名" (列名,列名2,....列名n) values (值,....值n);
例:insert into employee (first,last,age,address,city)
values ('Luke','Duke',45,'2130 Boars Nest','Hazard Co');
注意:每一个字符串都要用单引号括起来。
删除表:Drop table命令用于删除一个表格或者表中的所有行。其语法格式为:
drop table "表名"
例:drop table employee;
Drop table命令跟从表中删除所有记录是不一样的:
删除表中的所有记录是留下表格(只是它是空的)以及约束信息;
而Drop table是删除表的所有信息,包括所有行,表格以及约束信息等。
更新记录 Update语句用于更新或者改变匹配指定条件的记录,它是通过构造一个
where语句来实现的。其语句格式如下:
update "表名" set "列名"="新值" [,"列名2"="新值2"。。。]
where "列名" 条件 "旧值" [and|or "列名2" 条件 "旧值2"];
例:update phone_book set area_code =623 where prefix = 979;
update phone_book set last_name = 'Smith',prefix=555,suffix=9292
where last_name = 'Jones';
删除记录 Delete语句是用来从表中删除记录或者行,其语句格式为:
delete from "表名" where "列名" 条件 "值" [and|or "列名" 条件 "值"];
例:delete from employee;
这条语句没有where语句,所以它将删除所有的记录。
delete from employee where lastname = 'May' or firstname = 'Eric';
SELECT 语句 是SQL的核心。SELECT语句用于查询数据库并检索匹配你指定条件的选择数据。
SELECT 语句有五个主要的子句你可以选择,而FROM是唯一必须的子句。
语句格式:
SELECT [ALL | DISTINCT] 列名 [,列名2]
FROM 表名[,表名2]
[WHERE 条件]
[GROUP BY "表的集合"]
[HAVING 条件]
[ORDER BY "表的集合" [ASC|DESC] ]
例:select name,age,salary from employee where age>50;
注:一定要在SQL语句末尾加上一个分号。这个分号提示SQL语句已经结束并准备被解释。
例:select name,title,dept from employee where title LIKE 'Pro%';
ALL(缺省) DISTINCT(单一记录,并丢弃所有你在SELECT指定的列复制的记录)
例:select DISTINCT age from employee_info;
合计函数 MIN 返回一个给定列中最小的数值
MAX 返回一个给定列中最大的数值
SUM 返回一个给定列中所有数值的总和
AVG 返回一个给定列中所有数值的平均值
COUNT 返回一个给定列中所有数值的个数
COUNT(*) 返回一个表中的行数
合计函数用于从select语句中计算一个“返回列的数据”。它们是总结了所选数据列的结果。
虽然它们需要“GROUP BY”的子句,但是这些函数也可以在不用使用“GROUP BY”
子句的情况被使用。
例:select AVG(salary) from employee where title = 'Programmer';
select COUNT(*) from employees;//返回employee表的行数。
GROUP BY子句 语法:
select 列名,SUM(列名2) from 表名 GROUP BY "列名"
例:select max(salary),dept from employee group by dept;
//在每一个单独的部门中选择工资最高的工资。结果他们的salart和dept
将被返回。
HAVING 子句 语法:
select 列名,SUM(列名2) from 表名 GROUP BY "列名" HAVING 条件;
这个HAVING子句允许你为每一个组指定条件,换句话说,可以根据你指定
的条件来选择行。HAVING子句必须处在GROUP BY子句之后。
例:select dept,avg(salary) from employee group by dept;
//选择每个部门中的平均工资
select dept,avg(salart) from employee group by dept
having avg(salart)>2000;
ORDER BY 子句 语法:
select 列名,sum(列名2) from 表名 order by 列名 [asc|desc];
order by 是一个可选的子句,它允许你根据指定要order by的列来已上升或
者下降的顺序来显示查询的结果。
ASC = Ascending Order -这个是缺省的
DESC = Descending Order
例:select employee_id,dept,name,age,salary from employee_info
where dept = 'Sales' order by salary;
//这条SQL语句将从employee_info表中列dept等于'Sales'选择employee_id,
dept,name,age和salary,并且根据他们的salary按升序的顺序来列出检索结果。
select employee_id,dept,name,age,salary from employee_info where
dept = 'Sales' order by salary,age DESC;
组合条件和布尔运算符
例:select 列名,sum(列名2) from 表名 where 条件1 and 条件2;
IN 和 BETWEEN 条件运算符
IN 例:select 列名,sum(列名2) from 表名 where 列名3 IN 值;
BETWEEN例:select 列名,sum(列名2) from 表名 where 列名3 between
值1 and 值2;
实际上,IN 条件运算符是一个设置成员测试运算符,也就是说,它用于测试是否一个
数值处在IN关键字之后提供的数值之中。
例:select employeeid,lastname,salary from employee_info where
lastname in ('Hernandez','Jones','Roberts','Ruiz');
NOT IN 和IN 的用法相同
BETWEEN例:select employeeid,age,lastname,salary from employee_info
where age BETWEEN 30 and 40;
NOT BETWEEN和BETWEEN的用法相同
数学运算符
ABS(x) : 返回x的绝对值; SIGN(x): 当x为负数,零,正数的时候分别返回x的符号-1,0,1;
MOD(x,y):返回x除以y的余数,跟x%y作用一样; FLOOR(x):返回小于等于x的最大整数;
CEILING(x)或CEIL(x):返回大于等于x的最小整数; POWER(x,y): 返回x的y次方的数值;
ROUND(x):返回最接近于x的数; ROUND(x,d):返回小数点数为4的接近于x的数;
SQRT(x):返回x的平方根。
JOIN 子句:
关于sql语句中的连接(join)关键字,是较为常用而又不太容易理解的关键字,下面这个例子给出了一个简单的解释 --建表table1,table2:
create table table1(id int,name varchar(10))
create table table2(id int,score int)
insert into table1 select 1,'lee'
insert into table1 select 2,'zhang'
insert into table1 select 4,'wang'
insert into table2 select 1,90
insert into table2 select 2,100
insert into table2 select 3,70
如表
-------------------------------------------------
table1 | table2 |
-------------------------------------------------
id name |id score |
1 lee |1 90 |
2 zhang |2 100 |
4 wang |3 70 |
-------------------------------------------------
以下均在查询分析器中执行
一、外连接
1.概念:包括左向外联接、右向外联接或完整外部联接
2.左连接:left join 或 left outer join
(1)左向外联接的结果集包括 LEFT OUTER 子句中指定的左表的所有行,而不仅仅是联接列所匹配的行。如果左表的某行在右表中没有匹配行,则在相关联的结果集行中右表的所有选择列表列均为空值(null)。
(2)sql语句
select * from table1 left join table2 on table1.id=table2.id
-------------结果-------------
id name id score
------------------------------
1 lee 1 90
2 zhang 2 100
4 wang NULL NULL
------------------------------
注释:包含table1的所有子句,根据指定条件返回table2相应的字段,不符合的以null显示
3.右连接:right join 或 right outer join
(1)右向外联接是左向外联接的反向联接。将返回右表的所有行。如果右表的某行在左表中没有匹配行,则将为左表返回空值。
(2)sql语句
select * from table1 right join table2 on table1.id=table2.id
-------------结果-------------
id name id score
------------------------------
1 lee 1 90
2 zhang 2 100
NULL NULL 3 70
------------------------------
注释:包含table2的所有子句,根据指定条件返回table1相应的字段,不符合的以null显示
4.完整外部联接:full join 或 full outer join
(1)完整外部联接返回左表和右表中的所有行。当某行在另一个表中没有匹配行时,则另一个表的选择列表列包含空值。如果表之间有匹配行,则整个结果集行包含基表的数据值。
(2)sql语句
select * from table1 full join table2 on table1.id=table2.id
-------------结果-------------
id name id score
------------------------------
1 lee 1 90
2 zhang 2 100
4 wang NULL NULL
NULL NULL 3 70
------------------------------
注释:返回左右连接的和(见上左、右连接)
二、内连接
1.概念:内联接是用比较运算符比较要联接列的值的联接
2.内连接:join 或 inner join
3.sql语句
select * from table1 join table2 on table1.id=table2.id
-------------结果-------------
id name id score
------------------------------
1 lee 1 90
2 zhang 2 100
------------------------------
注释:只返回符合条件的table1和table2的列
4.等价(与下列执行效果相同)
A:select a.*,b.* from table1 a,table2 b where a.id=b.id
B:select * from table1 cross join table2 where table1.id=table2.id (注:cross join后加条件只能用where,不能用on)
三、交叉连接(完全)
1.概念:没有 WHERE 子句的交叉联接将产生联接所涉及的表的笛卡尔积。第一个表的行数乘以第二个表的行数等于笛卡尔积结果集的大小。(table1和table2交叉连接产生3*3=9条记录)
2.交叉连接:cross join (不带条件where...)
3.sql语句
select * from table1 cross join table2
-------------结果-------------
id name id score
------------------------------
1 lee 1 90
2 zhang 1 90
4 wang 1 90
1 lee 2 100
2 zhang 2 100
4 wang 2 100
1 lee 3 70
2 zhang 3 70
4 wang 3 70
------------------------------
注释:返回3*3=9条记录,即笛卡尔积
4.等价(与下列执行效果相同)
A:select * from table1,table2
索引 在AntiqueOwners列中为OwnerID创建索引:
CREATE INDEX OID_IDX ON ANTIQUEOWNERS (OWNERID);
下面语句为名字创建索引:
CREATE INDEX NAME_IDX ON ANTIQUEOWNERS(OWNERLASTNAME,OWNERFIRSTNAME);
下面语句删除索引:
DROP INDEX OID_IDX;
主键:类的唯一性;
创建唯一的索引:
CREATE UNIQUE INDEX OID_IDX ON ANTIQUEOWNERS (OWNERID);
DISTINCT和排除复制
假如你想列出所有买过古董的ID和名字,很明显,你可能会将所有的顾客都列出来而没有
考虑有些顾客是买过多种古董的,所以这时你会发现有些数据是重复的。这就意味着
你需要通知SQL来排除复制的行,而不管这个顾客买过多少种古董,只需要列出一次
即可。为了实现这个目的,你可以使用DISTINCT关键字。
SELECT DISTINCT SELLERID,OWNERLASTNAME,OWNERFIRSTNAME
FROM ANTIQUES,ANTIQUEOWNERS
WHERE SELLERID = OWNERID
ORDER BY OWNERLASTNAME,OWNERFIRSTNAME,OWNERID
Aliases,In以及查询
以下语句搜索所有已经定货的顾客的LastName以及他们定什么货。
SELECT OWN.OWNERLASTNAME Last Name, ORD.ITEMDESIRED Item Orderd
FROM ORDERS ORD,ANTIQUEOWNERS OWN
WHERE ORD.OWNERID = OWN.OWNERID
AND ORD.ITEMDESIRED IN (SELECT ITEM FROM ANTIQUES);
这条查询语句的结果为:
Last Name Item Ordered
Smith Table
Smith Desk
Akins Chair
Lawson Mirror
“Last Name”和“Item Ordered”给出了报告的数据头。
OWN和ORD是aliases(别名)
IN等价于=
更多的子查询
我们可以使用在SELECT查询语句中再包括一个SELECT子查询语句。
SELECT OWNERID FROM ANTIQUES
WHERE PRICE>(SELECT AVG(PRICE)+100 FROM ANTIQUES);
上面可以使用DISTINCT OWNERID 来排除复制的现象。
假设有一个买过bookcase的顾客,他的FirstName在数据库中出错了,应该为John:
UPDATE ANTIQUEOWNERS
SET OWNERFIRSTNAME='John'
WHERE OWNERID =
(SELECT BUYERID FROM ANTIQUES WHERE ITEM = 'Bookcase');
上面的语句中的子查询首先搜索买过bookcase的顾客的BuyerID,然后在外层的查询
中来更新他的FirstName.
EXISTS和ALL
如果商店在处理Chair的时候,有个顾客想看看所有拥有者的列表,就可以使用EXISTS.
SELECT OWNERFIRSTNAME,OWNERLASTNAME FROM ANTIQUEOWNERS
WHERE EXISTS (SELECT * FROM ANTIQUES WHERE ITEM ='Chair');
如果在Antiques中有Chair,那么子查询就会返回一行或者多行,就使得EXISTS为真,
如果没有搜索到Chair,则没有行被返回,条件就为假。
ALL举例:
SELECT BUYERID,ITEM FROM ANTIQUES WHERE PRICE>=
ALL(SELECT PRICE FROM ANTIQUES);
上面这条语句将返回最高价格的Item以及它的平方。子查询返回了Antiques表中的所有的
Price列。
UNION和(Outer Join)外部连接
有时候,你想一起看多个查询的结果,组合它们的输出,你可以使用UNION关键字。
SELECT BUYERID FROM ANTIQUEOWNERS
UNION SELECT OWNERID FROM ORDERS;
注意:使用UNION时SQL要求SELECT的列表必须匹配,即数据类型匹配,即BUYERID
和UNION的数据类型必须相同。
使用UNION时SQL会进行自动复制排除。而在单一的查询中,你就必须使用DISTINCT.
外部连接
SELECT OWNERID,'is in both Orders&Antiques' FROM ORDERS,ANTIQUES
WHERE OWNERID=BUYERID
UNION
SELECT BUYERID ,'is in Antiques only' FROM ANTIQUES
WHERE BUYERID NOT IN (SELECT OWNERID FROM ORDERS);
嵌入式SQL
嵌入SQL允许程序连接数据库并且包括SQL代码到程序中,这样在程序中就可以对数据库进行
使用,操作以及处理数据等等。以下是用C语言编写的使用嵌入SQL的例程,它将打印一个
报告;这个程序必须在普通的编译之前先预编译SQL语句。嵌入SQL对于不同系统是不一样
的,所以在不同的系统中对以下的程序稍作修改,特别是变量的声明以及过程记录等。在
嵌入SQL时,考虑网络,数据库管理系统,操作系统是相当重要的。
以下是详细的代码?
#include <stdio.h>
/*以下这部分是声明主机变量,它将使用于程序中*/
EXEC SQL BEGIN DECLARE SECTION;
int BuyerID;
char FirstName[100],LastName[100],Item[100];
EXEC SQL END DECLARE SECTION;
/*以下包括SQLCA变量,它可以用来进行错误检查*/
EXEC SQL INCLUDE SQLCA;
main()
{
/*以下是连接数据库*/
EXEC SQL CONNECT UserID/Password;
/*以下是连接数据库并检查是否有错误产生*/
if(sqlca.sqlcode)
{
prinrf(Printer,"Error connecting to database server./n");
exit();
}
printf("Connected to database server./n");
/*下面声明一个“Cursor”.它将在查询结果多于一行的时候使用*/
EXEC SQL DECLARE ItemCursor CURSOR FOR
SELECT ITEM,BUYERID FROM ANTIQUES ORDER BY ITEM;
EXEC SQL OPEN ItemCursor;
/*当这个CURSOR没有数据,sqlcode将被产生以允许我们推出循环。这里注意,
为了简单起见,我们使程序遇到错误的时候就退出任何的sqlcode.*/
EXEC SQL FETCH ItemCursor INFO :Item,:BuyerID;
while(!sqlca.sqlcode)
{
EXEC SQL UPDATE ANTIQUES
SET PRICE = PRICE+5
WHERE ITEM = :Item AND BUYERID = :BuyerID;
EXEC SQL SELECT OWNERFIRSTNAME,OWNERLASTNAME
INTO:FirstName,:LastName FROM ANTIQUEOWNERS
WHERE BUYERID = :BuyerID;
printf("%25s %25s %25s",FirstName,LastName,Item);
EXEC SQL FETCH ItemCursor INTO:Item,:BuyerID;
}
/*关闭CURSOR,提交变化并推出程序*/
EXEC SQL CLOSE DataCursor;
EXEC SQL COMMIT RELEASE;
exit();
}