SQL简明教程

数据定义

基本类型:

  • char(n):char是定长的,也就是当你输入的字符小于你指定的数目时,char(8),你输入的字符小于8时,它会再后面补空值。当你输入的字符大于指定的数时,它会截取超出的字符。
  • varchar(n):存储变长数据,但存储效率没有char高。如果一个字段可能的值是不固定长度的,我们只知道它不可能超过10个字符,把它定义为 VARCHAR(10)是最合算的。VARCHAR类型的实际长度是它的值的实际长度+1。为什么“+1”呢?这一个字节用于保存实际使用了多大的长度。从空间上考虑,用varchar合适;从效率上考虑,用char合适,关键是根据实际情况找到权衡点。
  • Numeric(p,d):定点数,精度由用户指定。有p位数字,其中d位数字在小数点后面。
  • float(n):精度至少位n位的浮点数

DDL Data Definition Language

create database database_name
create table r(A1 D1,A2 D2,......An Dn,完整性约束1,......,完整性约束k);
Drop table r;
Alter table r add A D; A:要添加的属性的名字 D:要添加的属性的类型(关系中的所有元组在该新属性的取值将被设置为null);
create view ; alter view ; delete view;
truncate table;

truncate和delete的区别

  • delete from后面可以写条件,truncate不可以。
  • delete from记录是一条条删的,所删除的每行记录都会进日志,而truncate一次性删掉整个页,因此日至里面只记录页释放,简言之,delete from更新日志,truncate基本不,所用的事务日志空间较少。
  • delete from删空表后,会保留一个空的页,truncate在表中不会留有任何页。
  • 当使用行锁执行 DELETE 语句时,将锁定表中各行以便删除。truncate始终锁定表和页,而不是锁定各行。
  • 如果有identity产生的自增id列,delete from后仍然从上次的数开始增加,即种子不变,而truncate后,种子会恢复初始。
  • truncate不会触发delete的触发器,因为truncate操作不记录各个行删除。

DML Data Manipulation Language

Delete table r;删除关系中所有的元组
INSERT INTO table_name VALUES (值1, 值2,....);
INSERT INTO table_name (列1, 列2,...) VALUES (值1, 值2,....);
update table_name set col1='' where col2='';

DQL Data Query Language

示例数据库结构:

表关系图
表关系图
Select A1,A2,......An from R1,R2,......Rm Where P;
Select distinct branch_name from loan;
在select后加入关键词distinct,强行删除重复,SQL允许我们使用all来显式指明不去除重复:
select all branch_name from loan;
保留重复元组是默认的

where子句

  • 逻辑连词:and or not
  • 比较运算符:<、<=、>、>=、=、<>
  • 为简化where子句,SQL提供between、not between
    Select loan_number from loan where amount (not) between 3000 and 5000;

更名运算

Select loan_number as loan_id from loan;
Select customer_name, T.loan_number, S.amount from borrower as T, loan as S Where T.loan_number=S.loan_number;

元组变量在比较同一关系中的两个元组时非常有用
Select T.branch_name from branch as T, branch as S Where T.assets>S.assets and S.branch_name=’....’;

字符串运算

SQL中使用单引号来标示字符串,如果单引号是字符串的组成部分,可以使用两个单引号标示:如表示“It’s right”可用:“It’’s right”来标示。

最常见的是使用like运算符的模式匹配(大小写敏感):

  • %:匹配任意子串
  • _:匹配任意一个字符

在like比较运算符中,使用escape关键字来定义转义字符,例子:

Like ‘ab\%cd%’ escape ‘\’ 匹配所有以ad%cd开头的字符串

排序
Order by desc 表示降序,asc 表示升序,默认升序

集合运算

union intersect except:并、交、非。

(select customer_name from depositor) Union (select customer_name from borrower)
表示在银行有账户、有贷款或者两者都有的客户

Union自动除去重复,如果想保留,使用union all(如果Jeason在银行中有三个账户和 两笔贷款,那么将会有五个元组包含Jeason)

(select customer_name from depositor) intersect (select customer_name from borrower)
表示在银行有账户并且有贷款的客户

intersect自动除去重复,如果想保留,使用intersect all(如果Jeason在银行中有三个账户和两笔贷款,那么将会有2个元组包含Jeason)

except:(oracle中为minus)

(select customer_name from depositor) except (select customer_name from borrower)
表示在银行有账户但是没有贷款的客户。

except自动除去重复,如果想保留,使用except all(如果Jeason在银行中有三个账户和两笔贷款,那么将会有1个元组包含Jeason;如果Jeason在银行中有两个账户和三笔贷款,那么结果没有元组包含Jeason)

聚集函数

avg min max sum count

使用聚集函数是可以使用group byhaving作为辅助:

Select branch_name,avg(balance) From account Group by branch_name;

如果在计算聚集函数前先删掉重复元组,可以在聚集函数中使用关键字distinct:

找出每个支行储户数:
Select branch_name count(distinct customer_name) From depositor,account Where depositor.account_number=account.account_number Group by branch_name;

Having子句用于对分组的限定条件

Select branch_name avg(balance) From account Group by branch_name Having avg(balance)>1000;

having子句中的谓词在形成分组后才起作用,因此可以使用聚集函数。

如果一个查询语句中同时存在where子句和having子句,那么SQL首先应用where子句中的谓词,满足where谓词的元组通过group by子句形成分组,having子句若在,就将作用于每个分组,不符合having子句谓词的分组将被抛弃。

空值

Is null, is not null

Select loan_number from loan where amount is null;

如果算术运算的输入有一个是空值,则该算术表达式(+、-、*、/)的结果是空,如果有空值参与比较运算,SQL将比较结果看成unknown

Unknown可以被布尔运算符处理

Select ... From R1,R2,R3... Where P;

查询结果中包含使得P为true的元组,如果元组使得P的值为false或者unknown,那么该元组就不会被添加到结果中去

Is unknown , is not unknown 判断比较结果是不是unknown

嵌套子查询

in, not in:

Select distinct customer_name from borrower where customer_name in (select customer_name from depositor);

some, all

Select branch_name from branch where assets > some (select assets from branch where branch_city=’Brooklyn’);
some表示至少比某一个要大

还有=some,=some和<>some(=some等价于in)

Select branch_name from branch where assets > all (select assets from branch where branch_city=’Brooklyn’);
all:比所有的都大

还有=all,=all和<>all(<>all等价于not in)

SQL中聚集函数不能进行组合使用,因而使用max(avg(...))是不允许的

问题:找出平均余额最高的支行

Select branch_name from account group by branch_name having avg(balance)>=all(select avg(balance) from account group by branch_name);

测试是否为空关系

exists:测试一个子查询的结果中是否有元组,exists结构在作为参数的子查询非空时返回true

查找在银行既有账户又有贷款的客户
Select customer_name from borrower where exists (select * from depositor Where depositor.customer_name=borrower.customer_name)

Not exists:可以模拟集合包含运算

关系A包含B:not exists(B except A)

查找在Brooklyn所有支行都有账户的客户
Select distinct S.customer_name From depositor as S Where not exists ((select branch_name from branch Where branch_city=’Brooklyn’) Except (select R.branch_name From depositor as T,account as R Where T.account_number=R.account_number and S.customer_name=T.customer_name))

测试是否存在重复元组

关键字:unique,如果作为参数的子查询的结果中没有重复的元组,unique结构将返回true

例:查找所有在Perryridge支行中只有一个账户的客户

Select S.customer_name from depositor as S where unique (select R.customer_name from account,depositor as R where account.account_number=R.account_number and Account.branch_name=’Perryridge’ and R.customer_name=T.customer_name)

not unique

例:找出所有在Perryridge支行中有两个以上账户的客户

Select distinct T.customer_name from depositor as T where not unique (select R.customer_name from account,depositor as R Where account.account_number=R.account_number and Account.branch_name=’Perryridge’ and R.customer_name=T.customer_name)

复杂查询

派生关系

as:对from子句中的查询表达式产生的结果命名

找出平均账户余额大于1200的支行的平均账户余额
Select branch_name avg_balance from (select branch_name,avg(balance) From account Group by branch_name) As branch_avg (branch_name,avg_balance) Where avg_balance>1200;

可以用于替换having子句

视图

任何不是逻辑模型的一部分但作为虚关系对用户可见的关系称为视图(view)

Create view view_name as <查询表达式>
Create view branch_total_loan(branch_name,total_loan) as Select branch_name sum(amount) From loan  Group by branch_name;

因为表达式sum(amount)没有名称,其属性名需要在视图中显示指定

视图的一般实现:当我们定义一个视图时,数据库系统存储视图的定义本身,而不存储定义该视图的关系表达式的计算结果,一旦视图关系出现在查询中,他就被已存储的关系表达式代替,因此,无论何时我们执行这个查询,视图关系都被重新计算。

物化视图:有些特定数据库允许视图关系被存储,但是它们保证如果用于定义视图的实际关系发生改变,视图也跟着修改。

如果需要频繁使用一个视图,物化视图比较合适;那些需要快速响应基于视图的特定查询的应用也是如此。

连接关系

<table>
<tr><th>连接类型</th><th>连接条件 </th></tr>
<tr><td>Inner join</td><td> Natural</td></tr>
<tr><td>Left outer join</td><td>On<谓词></td></tr>
<tr><td>Right outer join</td><td>Using(A1,A2...An)</td></tr>
<tr><td>Full outer join</td><td></td></tr>
</table>

关键字inner和outer是可选的。

对于外连接,连接条件是必须的;但是对于内连接,连接条件则是可选的(如果省略,将产生笛卡尔积)。On和using出现在连接表达式的末尾。

示例表内容:

loan:

loan_number branch_name amount

L-170 Downtown 3000

L-230 Redwood 4000

L-260 Perryridge 1700

borrower:

customer_name loan_number

Jones L-170

Smith L-230

Hayes L-155

内连接
loan inner join borrower on loan.loan_number = borrower.loan_number;

loan_number branch_name amount customer_name loan_number

L-170 Downtown 3000 Jones L-170

L-230 Redwood 4000 Smith L-230

所得结果的属性由左侧关系的属性后跟右侧关系的属性构成。

左外连接
loan left outer join borrower on loan.loan_number = borrower.loan_number;

loan_number branch_name amount customer_name loan_number

L-170 Downtown 3000 Jones L-170

L-230 Redwood 4000 Smith L-230

L-260 Perryridge 1700 null null

左外连接:先计算内连接的结果,然后,对左边关系(loan)中每个在内连接时与右边关系(borrower)中的任何元组都不匹配的元组t,向结果中加入一个元组r,r左边关系属性值为t,其他属性为null。

自然连接
loan natural inner join borrower;

loan_number branch_name amount customer_name

L-170 Downtown 3000 Jones

L-230 Redwood 4000 Smith

自然连接:连接属性(公共的属性)首先出现,按照它们在左侧的关系中的顺序,然后是左侧关系中所有的非连接属性,最后是右侧关系中所有的非连接属性。

全连接是左外连接和右外连接的组合

loan full outer join borrower using (loan_number);

loan_number branch_name amount customer_name

L-170 Downtown 3000 Jones

L-230 Redwood 4000 Smith

L-260 Perryridge 1700 null

L-155 null null Hayes

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容