连接类型在关系代数中,连接运算是由一个笛卡尔积运算和一个选取运算构成的。首先用笛卡尔积完成对两个数据集合的乘运算,然后对生成的结果集合进行选取运算,确保只把分别来自两个数据集合并且具有重叠部分的行合并在一起。连接的全部意义在于在水平方向上合并两个数据集合(通常是表),并产生一个新的结果集合,其方法是将一个数据源中的行于另一个数据源中和它匹配的行组合成一个新元组。SQL提供了多种类型的连接方式,它们之间的区别在于:从相互交叠的不同数据集合中选择用于连接的行时所采用的方法不同。连接类型 定义内连接 只连接匹配的行左外连接 包含左边表的全部行(不管右边的表中是否存在与它们匹配的行),以及右边表中全部匹配的行右外连接 包含右边表的全部行(不管左边的表中是否存在与它们匹配的行),以及左边表中全部匹配的行全外连接 包含左、右两个表的全部行,不管另外一边的表中是否存在与它们匹配的行。(H)(theta)连接 使用等值以外的条件来匹配左、右两个表中的行交叉连接 生成笛卡尔积-它不使用任何匹配或者选取条件,而是直接将一个数据源中的每个行与另一个数据源的每个行都一一匹配在INFORMIX中连接表的查询如果FROM子句指定了多于一个表引用,则查询会连接来自多个表的行。连接条件指定各列之间(每个表至少一列)进行连接的关系。因为正在比较连接条件中的列,所以它们必须具有一致的数据类型。SELECT语句的FROM子句可以指定以下几种类型的连接FROM子句关键字 相应的结果集CROSS JOIN 笛卡尔乘积(所有可能的行对)INNER JOIN 仅对满足连接条件的CROSS中的列LEFT OUTER JOIN 一个表满足条件的行,和另一个表的所有行RIGHT OUTER JOIN 与LEFT相同,但两个表的角色互换FULL OUTER JOIN LEFT OUTER 和 RIGHT OUTER中所有行的超集
2.2 内连接(Inner Join)内连接是最常见的一种连接,它页被称为普通连接,而E.FCodd最早称之为自然连接。下面是ANSI SQL-92标准select * from t_institution i inner join t_teller t on i.inst_no = t.inst_nowhere i.inst_no = "5801"其中inner可以省略。等价于早期的连接语法select * from t_institution i, t_teller t where i.inst_no = t.inst_noand i.inst_no = "5801"
2.3 外连接2.3.1 左外连接(Left Outer Jion)select * from t_institution i left outer join t_teller t on i.inst_no = t.inst_no其中outer可以省略。2.3.2 右外连接(Rigt Outer Jion)select * from t_institution i right outer join t_teller t on i.inst_no = t.inst_no2.3.3 全外连接(Full Outer)全外连接返回参与连接的两个数据集合中的全部数据,无论它们是否具有与之相匹配的行。在功能上,它等价于对这两个数据集合分别进行左外连接和右外连接,然后再使用消去重复行的并操作将上述两个结果集合并为一个结果集。在现实生活中,参照完整性约束可以减少对于全外连接的使用,一般情况下左外连接就足够了。在数据库中没有利用清晰、规范的约束来防范错误数据情况下,全外连接就变得非常有用了,你可以使用它来清理数据库中的数据。select * from t_institution i full outer join t_teller t on i.inst_no = t.inst_no2.3.4 外连接与条件配合使用当在内连接查询中加入条件是,无论是将它加入到join子句,还是加入到where子句,其效果是完全一样的,但对于外连接情况就不同了。当把条件加入到join子句时,SQL Server、Informix会返回外连接表的全部行,然后使用指定的条件返回第二个表的行。如果将条件放到where子句中,SQL Server将会首先进行连接操作,然后使用where子句对连接后的行进行筛选。下面的两个查询展示了条件放置位子对执行结果的影响:条件在join子句select * from t_institution i left outer join t_teller t on i.inst_no = t.inst_noand i.inst_no = “5801”结果是:inst_no inst_name inst_no teller_no teller_name5801 天河区 5801 0001 tom5801 天河区 5801 0002 david5802 越秀区5803 白云区条件在where子句select * from t_institution i left outer join t_teller t on i.inst_no = t.inst_nowhere i.inst_no = “5801”结果是:inst_no inst_name inst_no teller_no teller_name5801 天河区 5801 0001 tom5801 天河区 5801 0002 david
2.4 自身连接自身连接是指同一个表自己与自己进行连接。这种一元连接通常用于从自反关系(也称作递归关系)中抽取数据。例如人力资源数据库中雇员与老板的关系。下面例子是在机构表中查找本机构和上级机构的信息。select s.inst_no superior_inst, s.inst_name sup_inst_name, i.inst_no, i.inst_namefrom t_institution ijoin t_institution son i.superior_inst = s.inst_no
结果是:superior_inst sup_inst_name inst_no inst_name800 广州市 5801 天河区800 广州市 &nbs
========================================================
例表a aid adate 1 a1 2 a2 3 a3 表b bid bdate 1 b1 2 b2 4 b4 两个表a,b相连接,要取出id相同的字段 select * from a ,b where a.aid = b.bid这是仅取出匹配的数据. 此时的取出的是: 1 a1 b1 2 a2 b2 那么left join 指: select * from a left join b on a.aid = b.bid 首先取出a表中所有数据,然后再加上与a,b匹配的的数据 此时的取出的是: 1 a1 b1 2 a2 b2 3 a3 空字符 同样的也有right join 指的是首先取出b表中所有数据,然后再加上与a,b匹配的的数据 此时的取出的是: 1 a1 b1 2 a2 b2 4 空字符 b4
select * from a INNER join b on a.aid = b.bid 1 a1 b1 2 a2 b2 3 a3 空字符 4 空字符 b4
LEFT JOIN 或 LEFT OUTER JOIN。
左向外联接的结果集包括 LEFT OUTER 子句中指定的左表的所有行,而不仅仅是联接列所匹配的行。如果左表的某行在右表中没有匹配行,则在相关联的结果集行中右表的所有选择列表列均为空值。
====================================================================
重载、重写和隐藏的定义:
重载:同一个作用域内发生(比如一个类里面),定义一系列同名方法,但是方法的参数列表不同。这样才能通过传递不同的参数来决定到底调用哪一个。而返回值类型不同是不能构成重载的。
重写:继承时发生,在子类中重新定义父类中的方法,子类中的方法和父类的方法是一样的 例如:基类方法声明为virtual(虚方法),派生类中使用override申明此方法的重写.
隐藏:基类方法不做申明(默认为非虚方法),在派生类中使用new声明此方法的隐藏。
重载时,根据参数选择调用的方法;重写时,访问父类子类皆调用子类的重写方法;隐藏时,访问父类则调用父类的方法,子类子类的方法。
隐藏(new)示例:
using System; class A { public void F() { Console.WriteLine("A.F"); } } class B: A { new public void F() { Console.WriteLine("B.F"); } } class Test { static void Main(string[] args) { B b = new B(); b.F(); A a = b; a.F(); } } 输出为 B.F A.F重写virtual(虚方法)示例 using System; class A { public virtual void F() { Console.WriteLine("A.F"); } } class B: A { public override void F() { Console.WriteLine("B.F"); } } class Test { static void Main() { B b = new B(); b.F(); A a = b; a.F(); } } 输出为 B.F B.F
补充:重写override一般用于接口实现和继承类的方法改写,要注意
1、覆盖的方法的标志必须要和被覆盖的方法的标志完全匹配,才能达到覆盖的效果; 2、覆盖的方法的返回值必须和被覆盖的方法的返回一致; 3、覆盖的方法所抛出的异常必须和被覆盖方法的所抛出的异常一致,或者是其子类; 4、被覆盖的方法不能为private,否则在其子类中只是新定义了一个方法,并没有对其进行覆盖。
=====================================================================
首先理解一下什么叫多态。同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果,这就是多态性。
多态性通过派生类覆写基类中的虚函数型方法来实现。
多态性分为两种,一种是编译时的多态性,一种是运行时的多态性。
编译时的多态性:编译时的多态性是通过重载来实现的。对于非虚的成员来说,系统在编译时,根据传递的参数、返回的类型等信息决定实现何种操作。
运行时的多态性:运行时的多态性就是指直到系统运行时,才根据实际情况决定实现何种操作。C#中运行时的多态性是通过覆写虚成员实现。
下面我们来分别说明一下多态中涉及到的四个概念:重载,覆写,虚方法和抽象方法。
重载和覆写的区别:
重载
类中定义的方法的不同版本
public int Calculate(int x, int y)
public double Calculate(double x, double y)
特点(两必须一可以)
方法名必须相同
参数列表必须不相同
返回值类型可以不相同
覆写
子类中为满足自己的需要来重复定义某个方法的不同实现。
通过使用override关键字来实现覆写。
只有虚方法和抽象方法才能被覆写。
要求(三相同)
相同的方法名称
相同的参数列表
相同的返回值类型
最后再来介绍一下虚方法和抽象方法
虚方法:
声明使用virtual关键字。
调用虚方法,运行时将确定调用对象是什么类的实例,并调用适当的覆写的方法。
虚方法可以有实现体。
抽象方法:
必须被派生类覆写的方法。
可以看成是没有实现体的虚方法。
如果类中包含抽象方法,那么类就必须定义为抽象类,不论是否还包含其他一般方法。
注意:
昨天突然发现c#,和c++俩种语言在多态性的 实现机制 上面的细微差别。 如果是C++,在基类的构造函数里面调用虚函数的话,会调用本类的不会调用派生类的,原因是基类构造的时候,虚表还没有被派生类继承和修改。
但如果是C#,那就不同了,在基类的构造函数里面照样调用派生类的。不知道有谁知道c#它的这种底层机制是怎样的?-------是这样的,C++会先初始化基类,然后逐级初始化派生类型。C#则是一开始就把对象创建好了,然后逐个调用构造函数。本质区别在于C++的构造函数的任务是初始化,C#则不然,C#的类型的任何字段不必初始化,均有默认值,所以C#在调用构造函数之前就已经将对象初始化完毕了。
通过继承,一个类可以用作多种类型:可以用作它自己的类型、任何基类型,或者在实现接口时用作任何接口类型。这称为多态性。C#中的每种类型都是多态的。类型可用作它们自己的类型或用作Object实例,因为任何类型都自动将Object当作基类型。 多态性不仅对派生类很重要,对基类也很重要。任何情况下,使用基类实际上都可能是在使用已强制转换为基类类型的派生类对象。基类的设计者可以预测到其基类中可能会在派生类中发生更改的方面。例如,表示汽车的基类可能包含这样的行为:当考虑的汽车为小型货车或敞篷汽车时,这些行为将会改变。基类可以将这些类成员标记为虚拟的,从而允许表示敞篷汽车和小型货车的派生类重写该行为。