基本理念
关系表和关系型数据库设计的基本理念。
接下来的内容并未覆盖以上所有主题,但足够让你进入后面的学习。
假设你有一个包含产品类别的数据库表,每行包含一个类别项。各个类别可以存储的信息包括产品介绍和价格,以及生产产品的公司的供应商信息。
由同一个供应商提供的许多不同类别的产品,应该把供应商的信息存储在哪里?因为如下理由,你不会把供应商信息和产品信息存储在一起。
- 因为对于每个产品,供应商的信息是相同的,对每个产品重复同样的信息是在浪费时间和存储空间。
- 如果供应商的信息改变,你不得不更新每一个存储的供应商信息。
- 当数据重复时(即供应商信息和产品信息混合在一起),每次都以完全相同的方式输入数据的概率很低。在报表中无法使用不一致的数据。
设计关系表时,将信息分割到多个表中,每个表包含一种数据类型,表与表之间通过相同值联系起来 (即关系设计当中“关系”)
以上的??例子可以创建两个表,一个用来存放供应商信息vendors,另一个用来存放产品信息products。
vendors表包含供应商的所有信息,表中每行代表一个供应商,并且有一个标识供应商的唯一标志符。这个值叫做主键(primary key),可以称为供应商id,或者其他唯一值。
products表仅存储产品信息,并且除了供应商id之外,没有供应商其他的信息。供应商id称为外键,通过它,关联venders表盒products表,并且这个供应商id能够让你通过vendor表找到合适供应商的详细信息。
外键(Foreign Key)在表的一列中包含来自其他表的主键值,这样就定义了表与表之间的关系。
这样做的优点就是:
- 供应商的信息永远不会重复,因此不会浪费时间和空间
- 如果供应商信息改变了,可以更新vendors表中的但个记录。相应表中的数据不会改变
- 由于没有重复数据,使用的数据显然是一致的,这使得数据报表和操作更加简单
扩展性(Scale)能够随着数据量的增长进行处理,而不会失败。一个设计良好的关系型数据库或者应用程序被称作扩展性好。
创建连接
创建连接非常简单,必须包含所有指定的表,并且说明它们是如何关联起来的。
SELECT vend_name, prod_name, prod_price FROM vendors, products WHERE vendors.vend_id = products.vend_id ORDER BY vend_name, prod_name;
例子(以下是在不同库里面的两张不同表):
mysql> select appKeyInfo.appKey, businessId,appName, infoType, appKeyInfo.remark from appKeyInfo,crowdRewards.businessInfo where appKeyInfo.appKey=businessInfo.appKey and infoType=4 order by appKeyInfo.id desc limit 10; +------------+------------+---------+----------+-----------------------------------------+ | appKey | businessId | appName | infoType | remark | +------------+------------+---------+----------+-----------------------------------------+ | 1194641763 | 133 | | 4 | zhiyonginfom | | 3217703708 | 132 | | 4 | 测试使用 | | 1029667166 | 0 | | 4 | sichuanyinyue | | 3927050004 | 130 | | 4 | 546546546 | | 1966753355 | 129 | | 4 | king | | 2740425196 | 128 | | 4 | 666663321 | | 2496853641 | 127 | | 4 | 6666633 | | 751377797 | 126 | | 4 | 66666 | | 1031297745 | 125 | | 4 | qqqaaa | | 2061454479 | 124 | | 4 | qqq | +------------+------------+---------+----------+-----------------------------------------+ 10 rows in set (0.08 sec)
其中,
desc appKeyInfo;
+-----------------+---------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-----------------+---------------------+------+-----+---------+----------------+ | id | int(10) unsigned | NO | PRI | NULL | auto_increment | | appKey | int(10) unsigned | NO | UNI | 0 | | | appName | varchar(32) | NO | | | | | remark | varchar(32) | NO | | | | | infoType | tinyint(4) unsigned | NO | | 0 | | | appLogo | varchar(128) | NO | | | | +-----------------+---------------------+------+-----+---------+----------------+ 6 rows in set (0.06 sec)
desc businessDemo;
+-------------------+------------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------------------+------------------------+------+-----+---------+----------------+ | id | int(10) unsigned | NO | PRI | NULL | auto_increment | | name | varchar(64) | NO | | | | | appKey | int(10) unsigned | NO | | 0 | | | businessID | int(10) unsigned | NO | | 0 | | | remark | varchar(128) | NO | | | | +-------------------+------------------------+------+-----+---------+----------------+ 5 rows in set (0.04 sec)
使用WHERE来设置连接关系看起来有些奇怪,不过事实上有一个很好的理由支持这种做法。记住,当表通过SELECT语句连接起来时,关系的组织是动态。...事实上,你将第一个表中的每一行同第二个表中的每一行进行对比,WHERE事实上就是一个过滤器,使其仅仅包含匹配制定过滤器条件(连接条件)的行。没有WHERE子句,第一个表的每一行将匹配第二个表中的每一行,无论它们是否符合逻辑。
笛卡尔乘积(Cartesian product)没有使用连接条件的表关系的返回结果。返回的行数时第一个表的行数乘以第二个表的行数。
不要忘记WHERE子句,确保所有的连接都包含WHERE子句,否则MariaDB将返回超出你所需的数据。类似的,确保正确使用WHERE子句,错误的过滤条件将会导致MariaDB返回错误数据。
交叉连接(Cross Joins)这种就是笛卡尔乘积的连接类型。
SELECT vend_name, prod_name, prod_price FROM vendors, products ORDER BY vend_name, prod_name;
内连接
SELECT vend_name, prod_name, prod_price FROM vendors INNER JOIN products ON vendors.vend_id = products.vend_id;
另外,跨库的连接
select dataBaseName1.appKey,dataBaseName2.tableName2.appKey from tableName1 inner join dataBaseName2.tableName2on appKeyInfo.appKey=dataBaseName2.tableName2.appKey;
等值连接(equiljoin)一个基于测试两表相等的连接。这种连接也被称作内连接。
这里的两个表关系被指定为INNER JOIN.当使用这个语法的时候,连接条件使用on来代替where子句,传递给on的条件和传递给where子句的条件相同。
连接多个表
sql没有明确限制select语句中表连接的数量。
创建连接的基本规则仍然相同,首先列出所有的表,然后定义表的关系。
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 = 20005;