数据库

数据库之路——
从关系演算到数据立方
作者:WangQingDa                Gender: Male
专业:会计电算化(bachelor);计算机软件理论(Master)
仅以此文献给我自己,以及对数据库理论和实践感兴趣的并具备足够的耐心阅读它的诸位朋友。数据库对于任何学习计算机专业的人来说都是基础之中的基础,但同时DBMS理论又博大精深,包罗万象,既有深层上的理论研究价值,于实用又可千变万化,解决问题。这份材料主要是作为备忘来编写,也有自己的一些体会性的内容。
 
 
 
 
 
 
 
Bibliography
[1] Jeffery D. Ullman “Principles of DataBase and Knowledge-Base System”
[2] Jiawei Han, Micheline Kamber “Data Mining: Concepts and Techniques”
[3] M.H.Alsuwaiyel (沙特)算法设计技巧与分析
 
1 数据库系统的数据模型理论
什么是数据模型,如果需要让计算机存储并处理数据,那么数据一定要按照便于表达、便于处理、便于应用的模式存储,并有一套相关的理论作为支撑。
Ullman给出了数据模型的定义,虽然比较泛化,抽象,但做到了高度概括:
 一套标记数据的符号系统,可以描述论域中的所有的数据。
 一套定义在这个符号系统之上的运算(操作)集,用于处理数据。
1.1 关系模型(Relation Model)
关系模型是由E. Codd在1970年提出来的,它迅速地流行起来并得到了应用,主要是它的Value-oriented(面向值的)特点及对于数据的虽然很简单但是却描述性很强的表达特点。我们可以把数据存储为关系Relation,并且对于定义在关系之上的运算,其结果也是关系,所以利用关系及关系上的运算(operation),我们可以生成一个封闭的代数系统。听起来稍微有些复杂,实际上很简单,大意是你可以把关系模型就理解为一个数据表,关系操作即直接操纵数据,数据处理完之后还是数据表。除了关系模型之外,还有面向对象模型、面向逻辑模型等等。
应该说关系模型是最简单的了,SQL语句是基于关系模型的,否则如果让你写谓词逻辑公式求解数据,那就麻烦透了,数据库用户起码得缩减掉90%。
面向对象的数据模型(如IBM公司推出的ORDBMS),就不如关系模型来得简单,原因可以介绍两条:
 关系模型便于表示数据处理的结果。因为关系模型不用支持object ID(如果是对象模型,需要为每一个对象类指示ID,并且保证ID不可重复)。
 支持抽象数据类型的模型,会带来另外的弊端。一个有用的数据库操作往往会产生一个新的数据类型,而这个新的数据类型在系统中需要为它作新的定义,所以这个新的数据类型(临时结果集)无法马上成为一个新的运算操作的操作数。这个问题我个人认为在关系数据库(RDBMS)中也是存在的,除了利用非核心的如Foxpro中的远程视图、C#.net中的内存数据表对象、微软的DTC以外,对关系表的中间计算结果实际上也无法作为下一个关系运算的操作数进行使用。
1.1.1 关系的基本概念(基于集合论的概念表述)
数据库系统中的关系,是取自于集合论中的概念,一个关系,是若干个值域的笛卡尔乘积的子集。
▲域D(domain):也是一个很宽泛的概念,如整数、实数、有理数、无理数、副点数、双符点、字符、字符串、可变长字符串、大文本、图像、声音、复杂数据类型、对象数据类型等等。
▲ 笛卡尔积╳(Cartesian product):k个域D1、D2、D3、…Dk的笛卡尔积可以表示为一个k元元组(tuples)的集合,笛卡尔乘积的运算符号为╳,则笛卡尔乘积可以表述为:
D1╳D2╳D3╳…╳Dk={(v1, v2, v3…vk)|all v1∈D1 and v2∈D2 … and vk∈Dk}
▲一个定义在D1╳D2╳D3╳…╳Dk上的关系R也是一个n元组集合,且RÍ D1╳D2╳D3╳…╳Dk。关系R的一个例子是{(0,a),(0,b),(1,c)},又如{(“Mary”,32),(“Tom”,34)}
▲一个关系的成员称为tuple,即元组。一个关系如果是定义在D1╳D2╳D3╳…╳Dk之上的,则称k为元数(在数据仓库中叫做维度)。一个有着k元数的元组被称为k元组。
□ 评述:这些理论都是非常直观的,所谓的Relation,我们可以理解为一张数据表;所谓的元组,就是数据表中的某一行;没有相关性,没有任何关系的一张表是不可能放在一起的,所以称这个集合为关系。
数据库_第1张图片
关系是定义在域的集合之上的,引入域(Domain)的概念,引入域的概念的目的是为了对关系作规范、作限制;甚至可以说域的笛卡尔积形式就是关系的元数据(metadata),它是用来解释关系的模型的。如一个学生档案关系可以是如下笛卡尔积的子集(subset):全体学生姓名╳地址╳所有电话号码╳大于0小于200的整数╳…。通过指定关系的笛卡尔积的子集形式,我们可以得到关系的模式。但在实际的RDBMS中,域的类型实际上只限于数据类型,而无法对具体的贴近实际应用的域作定义,而辅助以域的名字作为元数据,即通过{域名,数据类型}的方式制定一个域。
□如何对多个关系求笛卡尔积,如何看到在一个关系中所有域的笛卡尔积?
1、对多个关系R1,R2,…Rk SELECT * FROM R1 R2 …Rk
2、对一个关系R中所有域v1,v2,…vK的笛卡尔积
SELECT R1. v1 R2. v2 RK. vK  FROM R R1, R R2, … R RK
即把这一个关系表虚拟成多个(有多少个域,就有多少个虚拟关系),然后分别从不同的数据表中提取出相应的数据域进行笛卡尔积。实际上RDBMS只对多个Relation作笛卡尔积,而不对一个关系表里面的多个字段作笛卡尔积。
□ Example 1.1.1.1:(MS SQL Server)
SELECT R1.admin_id, R2.admin_name, R3.admin_pwd
FROM admin R1 CROSS JOIN admin R2 CROSS JOIN admin R3
数据库_第2张图片
这个例子是在 Microsoft SQL Sever 2000 中做出的, Cross Join 表示要对两个关系进行笛卡尔积。
□ Example 1.1.1.2:(Oracle 8)
Select R1.swjg_mc, R2.swjg_jc from ht_swjg_dmb R1, Ht_swjg_dmb R2
 
Oracle 中,可以直接去掉关联条件,即可以实现笛卡尔积。
从直观上看,我们似乎很难找到笛卡尔积的实用意义——特别是在具体的应用领域中,但笛卡尔积对于一个 RDBMS 系统至关重要,因为我们所有的对于多个关系表的操作(关联、筛选等等)都是先对多个 RELATION 执行笛卡尔积操作,然后在笛卡尔积上再执行选择(通过 Where 条件做),投影。笛卡尔积是一个数据的操作的上缺界。
□ 以数据表的观点来看关系

模式-> 属性 属性 属性 属性 属性 属性 属性
记录 Name Id Gender Address post Age salary
记录 ***            
记录 ***            
*** ***            
*** ***            

1.1.2 用集合论和映射的观点来理解关系
在我们已经给每一个属性都起了名字的前提下,关系的模式,即字段名的集合的前后顺序就显得无关紧要了。我们也可以把元组看作是从域向属性的映射。这里的观点实际上是设定一个元组变量 µ,然后这个映射实际上是一个一对多的映射,即由一个元组映射到多个属性的值。
 Example 1.1.2.1
给定一个关系 {City,State,Pop} { San Diego,Texas,4490 Miami,Oklahoma,13880 , Pittsburg,lowa,509 }
如果从映射来说,可以理解为对每一个元组集的成员,单个元组,这个一对多的映射 µ,把每一个元组都映射到每个域的某个成员。如对元组 San Diego,Texas,4490 )来说,这个映射可以反映(定义)为:
µ (City)=Diego  :当前元组对应的 City 域的值是 Diego
µ (State)=Texas  :当前元组对应的 State 域的值是 Texas
µ (Pop)=Diego  :当前元组对应的 Pop 域的值是 4490
当需要按照固定序列列出的时候;当只需要用映射的方式给出时;我们会采用不同的方法。关系表的模式是和顺序相关的,而映射的方式( set-of-mapping )是和顺序无关的。在 Set-of-list (即列明字段的模式下,基于集合论 set theory 模式下),我们给出了隐式的强制性的数据列出顺序。
在一个商用的关系型数据库系统中,我们很难说出某个数据库系统是按照集合的模型还是按照映射的模型来处理数据的。比如要在数据库中插入一条数据记录,如果不指名字段的出现顺序, insert into table values (V1,V2,…,Vn) ,则就是按照 Set-of-list 处理的数据,而如果使用 insert into table(Attr1,Attr2,…,Attrn) values (V1,V2,…,Vn) 插入一条数据记录,则是按照 Set-of-Mapping 的模型处理数据。
1.1.3 把实体-关系模型存储到关系模型中去
实体 - 关系模型,即 Entity-Relation(E-R) 模型,实体关系模型在结构化的软件工程时代( 1976 年提出)支撑软件工程逻辑建模的基础性工具,到目前仍在不断地完善,发挥实用价值。到后来的 UML 的类图,实际上还是在 E-R 模型之上加入了类的概念,加入了继承、 isa 关系、复杂对象、成员函数等等。
数据库_第3张图片
Figure 1.1.3.1  实体关系图
在实体 - 关系图中,每一个实体(图中的大方框中)可以看作是一个关系,一个元组的集合,图中的实体的属性可以看作关系中的域。通过 E-R 图,我们可以把现实世界中的事务虚拟成 E-R 图中的实体、属性,实体之间的关系可以通过图中的连线体现(在关系中体现为具有相同的域),两个抽象实体之间具有共同的属性。而两个抽象实体之间的关系可以体现为一对一、一对多、多对一、多对多。如图 1.1.3.1 种,又两个相关联的抽象实体,一个为学生实体,另一个是成绩实体,两个抽象实体之间通过 Student_ID 建立起关联。注意,这里还存在一个引用关系( Reference 或称为 ForeignKey ),即学生成绩实体中的学生属性是通过学生号参照的学生档案主关系中的学生号,作为外键,它一定是标志某个实体的关系的主键。这里非常容易理解,因为学生号不可能唯一地表示学生成绩,它只从一个侧面说明了该成绩属于哪个学生。
数据库_第4张图片
Figure 1.1.3.2  类图:部门 - 雇员类图
UML (统一建模语言)标准中的类图比 E-R 图多出了什么呢?首先里面确定了继承关系(即 IsA 关系),如图 1.1.3.2 中, Employee is a Person ,即雇员是一个人,没有继承关系的类之间存在着 E-R 关系。而在类图中,还有一种成员变量之间的关系,如轮胎是汽车的一部分,如下图中显示出的汽车和轮子的聚合关系。详细的内容请阅读 UML 文档。
数据库_第5张图片
Figure 1.1.3.3
我们甚至可以说, E-R 图是简单化了的类图,或者称 E-R 模型是 Class Diagram 的一个子集。去掉了继承关系,聚合、接口、成员方法、构造函数、析构函数等等,单纯表述出实体之间的静态关系。
1.1.3.1 把E-R图转换为关系模型Relational Scheme
我们使用关系模型集合来表示数据的方法称为关系型数据库模式( Relational Database scheme ),但我们应该遵循何种方法来使用关系模型呢?通常存在着标准的模式,即先用实体 - 关系模型建模,然后把 E-R 图存储为关系模型,定义在关系型数据库里。
□首先,作为 E-R 图中的一个抽象实体 E ,直接对应于关系模型中的一个关系,该关系的逻辑模式包含了 E 的所有的属性。该实体的实体集可以存储为关系表,即实体集中的每一个具体的实体对应于关系的每一个元组。如果在用关系 R 表示 E 的同时,也要保存其它的实体集 F ,则也需要纳入 F 的属性。
如果需要一个关系 R 表示多个实体集 E1, E2, … Ek 之间的联系,则关系 R 的属性集里一定要包括每个实体集的关键字,如果这些实体之间存在着多个重名的字段,则需要修改重复的字段名。
对于“关系”,在数据库的处理中有默认隐含的关系和显示地定义两种:
 Example 1.1.3.1.1  显式的关系
两个实体集: Employee(em_id,name,age,major,dep_id)
        Department(dep_id,name,responsibilty)
在这个例子中,有两个实体集,一个是雇员集,一个是部门集。在这个实体 - 关系模型中,雇员与部门之间存在着多对一的关系,这种关系我们没有单独用一个关系表( Relation )进行存储。因为在雇员关系表中,有一个属性已经能够明确表明这种映射,不用单独建立一个映射关系表了。
 Example 1.1.3.1.2  隐式的关系
三个实体集: Student(Enroll_id,name,age,major,HomeTown,IdenCo)
        Course(Course_id,description,Teacher,aim,Hours)
   ElectCourse(Enroll_id,Course_id,Year,Term,Score)
在这个例子中,我们注意到 E-R 模型中存在着 3 个实体集,但只有两个真实的静态的实体集,一个是学生实体集,另外一个是课程实体集,实际上在 E-R 图上我们能够见到的也就是这 2 个实体集。我们注意到这两个实体集之间的关系是多对多的关系,即一个学生可以选择多个课程,同时一个课程可以由多个学生选择。由于目前的关系型数据库是一个二维( 2-dimensional )结构,不支持在一个单元中继续存储关系,所以对这种多对多的关系必须分解成一对多(或一对一)的关系。所以我们必须显示地分解,即引入选课关系 electCourse ,记录下每一个学生的具体选课情况。
     从实体关系模型到关系模式如果需要,可以做优化工作。
我们没有必要原封不动地,照本宣科地把实体 - 关系模型中的实体集机械地转换成关系模型,有时候可以合并若干实体集,还有的时候需要把一个实体集分解为多个。这一工作需要考虑数据库的范式理论,即 1NF,2NF,3NF,BCNF 等等。关于范式理论请参阅相关的资料 ; 同时还要考虑系统的运行效率、可移植性、开发成本等等相关的因素。
1.1.3.2 关系中的键(Keys of Relation)
象实体集一样,关系里也要有键。键的概念有些像人的 DNA ,又像是身份证号,象一个企业工商登记证号、组织代码证号,它唯一地表示某个元组(实体)。我们给出键的形式化的概念,关系 R 的键是一组属性 S ,满足:
关系 R 中反映现实世界中的实例(以单个元组体现),没有任何两个实例在关系 R 中具有相同的 S 值(即 S 中的每个属性值都相同)。
S 中去掉任何属性,都无法保证条件 的成立。
键的作用,我个人认为主要有这几个方面:首先,关系里面存储的每一个元组是多个域的成员之间的关系,如一个雇员档案中的某个雇员的元组,记录的是名字、年龄、地域等等,另一方面,元组本身代表了一个实体,这个实体需要有一个能够标志其唯一身份的特征向量,便于从数据库里增加、删除、修改,否则就无法为单个的实体定位;这也是数据库管理系统的需要,为了保持数据的域完整性(世界上不存在两个完全一样的事物);另外,为了防止数据的冗余,其它的关系在参照这一关系时(即某个属性引用这个关系),可以使用键,而不用录入这个关系的全部的字段值。
 Example 1.1.3.2.1
我们用一个例子来看一下键值的约束作用。就如我们看一下选课关系 ElectCourse(Enroll_id,Course_id,Year,Term,Score) ,实际上的键值选择要结合现实世界的应用情况,实情况而定。在通常的情况下,我们认为用( Enroll_id,Course_id )即可,即学生、课程可以唯一标志一个选课,不可能存在两条一样的元组,即同一个学生选了两次课(重复学习);而且去除掉健的任何一个成员,都无法保证键值不重复。同理,( Enroll_id,Course_id )作为键,如果加入一个字段,也无法保证其逻辑的可行性( DBMS 无法控制其逻辑上是否合理,这时允许重复的 Enroll_id,Course_id 对出现在数据库中),如果增加一个键的成员属性,则出现了例如( Mary,History,78.5 )和 (Mary,History,86) 的成绩,一门课程同一个人两个成绩,不是很荒谬吗!但这种把键放得太大的情况,要靠设计人员自行控制。
所以我们说,如何对一个关系设计它的键,不是取决于它的数据实例,而是最终取决于整个关系的概念含义,其实际的环境约束。取决于 Scheme
多个健值
很多时候在一个关系中,模式定义里有多个键,如对于一个企业档案信息关系,全国统一的组织机构代码可以作为一个键;如果不允许存在同名的企业,则企业的名称也可以作为键。通常情况下, DBMS 希望设计者能够指定一个主键,以便于数据库管理系统从物理存储上便于管理关系表,这个键称作主键, Primary key 。所有具备键的条件的属性集被称为备选键。
 
 
1.1.3.3 关系之间拥有的共同的键
每一个关系都是若干的域的笛卡尔积的子集,关系与关系之间有可能存在着共同的属性,也有可能存在着共同的键( Common Key )。即某个健 K ,既是关系 R1 的备选键,又是 R2 的备选键,则 K 成为 R1 R2 的共同拥有的键。注意,这里要强调的是仅仅是属性名一致、数据域一致还不能称之为 Common Key ,只有确定语义上的一致才可以,如 Student(Id,name,age) Teacher(Id,graduateTime,Major) ,虽然是都有 id 作为主键,但一个是学生登记号而另一个是教师工号,两个 id 是截然不同的东西,不是共同键。如果语义上一致,即使键的名字或属性的名称不对应,甚至是数据类型不对应,也可以认为是 Common Key ,可以通过其进行管理的连接。
   如果多个 Relation 之间具有 Common key ,则这多个关系之间可以通过共同键合并为一个关系。这样做的好处之一是可以节省空间;另外,如果某些查询涉及到这多个关系,可以使查询语句变得更为简洁,执行速度更快。
但带来的坏处是把多个实体集合并在一起,使整个关系模式变得含混,失去了清晰的语义,不太符合“分而治之”的原则。
1.1.3.4 空挂的元组(Dangling Tuples)
如果需要对两个拥有 Common Key 关系 R1 R2 进行合并成一个关系的操作,则我们注意到如果 R1 R2 Common key 的值不能做到一一对应,那末会导致 R1  R2 中有一些元组无法合并到新的关系中,如下图:

鍙湁鍦ㄨ皟璇曟ā寮忎笅杩涜缂栬瘧鏃讹紝鐢熸垚姝ゆ湭澶勭悊寮傚父鐨勬簮浠g爜鎵嶄細鏄剧ず鍑烘潵銆傝嫢瑕佸惎鐢ㄦ鍔熻兘锛岃鎵ц浠ヤ笅姝ラ涔嬩竴锛岀劧鍚庤姹?URL:

1. 鍦ㄤ骇鐢熼敊璇殑鏂囦欢鐨勯《閮ㄦ坊鍔犱竴鏉♀€淒ebug=true鈥濇寚浠ゃ€備緥濡?

  <%@ Page Language="C" Debug="true" %>

鎴?

2. 灏嗕互涓嬬殑鑺傛坊鍔犲埌搴旂敤绋嬪簭鐨勯厤缃枃浠朵腑:


   
       
   



璇锋敞鎰忥紝绗簩涓楠ゅ皢浣跨粰瀹氬簲鐢ㄧ▼搴忎腑鐨勬墍鏈夋枃浠跺湪璋冭瘯妯″紡涓嬭繘琛岀紪璇戯紱绗竴涓楠や粎浣胯鐗瑰畾鏂囦欢鍦ㄨ皟璇曟ā寮忎笅杩涜缂栬瘧銆?br>
閲嶈浜嬮」: 浠ヨ皟璇曟ā寮忚繍琛屽簲鐢ㄧ▼搴忎竴瀹氫細浜х敓鍐呭瓨/鎬ц兘绯荤粺寮€閿€銆傚湪閮ㄧ讲鍒扮敓浜ф柟妗堜箣鍓嶏紝搴旂‘淇濆簲鐢ㄧ▼搴忚皟璇曞凡绂佺敤銆?/code>
鍫嗘爤璺熻釜:

[ArgumentException: 鍙傛暟鏃犳晥銆俔 System.Drawing.Image.FromStream(Stream stream, Boolean useEmbeddedColorManagement, Boolean validateImageData) +388134 System.Drawing.Image.FromStream(Stream stream) +8 Dottext.Admin.UploadWord.SaveFile(HttpPostedFile File) +32 Dottext.Admin.UploadWord.Page_Load(Object sender, EventArgs e) +76 System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +15 System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +34 System.Web.UI.Control.OnLoad(EventArgs e) +99 System.Web.UI.Control.LoadRecursive() +47 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1061


鐗堟湰淇℃伅: Microsoft .NET Framework 鐗堟湰:2.0.50727.832; ASP.NET 鐗堟湰:2.0.50727.832

你可能感兴趣的:(数据库,sqlserver,sql,stream,object,tuples)