这里有新鲜出炉的SQL Server教程,程序狗速度看过来!
SQL是英文Structured Query Language的缩写,意思为结构化查询语言。SQL语言的主要功能就是同各种数据库建立联系,进行沟通。按照ANSI(美国国家标准协会)的规定,SQL被作为关系型数据库管理系统的标准语言。
SQL Server 即 Microsoft SQL Server 。
本文主要讲了SQL Server的交叉联接和内部联接,同时也给出了使用需要注意的地方。有需要的朋友可以看下
前言
本节开始我们进入联接学习,关于连接这一块涉及的内容比较多,我们一步一步循序渐进学习,简短内容,深入的理解。
交叉联接(CROSS JOIN)
交叉连接是最简单的联接类型。交叉联接仅执行一个逻辑查询处理阶段-笛卡尔乘积。例如对两个输入表进行操作,联接并生成两个表的笛卡尔乘积,也就是说,将一个表的每一行与另一个表的所有行进行匹配。所以,如果一个表有m行,另一个表有n行,得到的结果中则会有m*n行。我们就拿SQL Server 2012教程中的例子说下
- SELECT C.custid, E.empid
- FROM Sales.Customers AS C
- CROSS JOIN HR.Employees AS E
- ORDER BY E.empid
在Sales.Customers表中有91行数据,HR.Employees表中有9行数据,则利用交叉联接数据则有819(91*9)行数据,简略数据如下。
交叉联接我们可以用如下图表示
交叉联接最大的用途在于生成数字表以便我们用于其他目的,我们一起来看看。
- IF OBJECT_ID('dbo.Digits','U')
- IS NOT NULL DROP TABLE dbo.Digits;
- CREATE TABLE dbo.Digits
- (
- digit INT NOT NULL
- );
插入10条基础数据
- USE TSQL2012
- GO
- INSERT INTO dbo.Digits
- ( digit )
- VALUES ( 0 ), ( 1 ), ( 2 ), ( 3 ), ( 4 ), ( 5 ), ( 6 ), ( 7 ), ( 8 ), ( 9 )
创建数字表
- USE TSQL2012
- GO
- CREATE TABLE Nums
- (
- n INT NOT NULL PRIMARY KEY
- );
利用交叉联接在数字表中插入100万条数据
- USE TSQL2012
- GO
- INSERT INTO dbo.Nums(n)
- SELECT D6.digit * 100000 + D5.digit * 10000 + D4.digit * 1000 + D3.digit * 100 + D2.digit * 10 + D1.digit + 1 AS n
- FROM dbo.Digits AS D1
- CROSS JOIN dbo.Digits AS D2
- CROSS JOIN dbo.Digits AS D3
- CROSS JOIN dbo.Digits AS D4
- CROSS JOIN dbo.Digits AS D5
- CROSS JOIN dbo.Digits AS D6
- ORDER BY n
内部联接(INNER JOIN)
内部联接用法如下
- SELECT *
- FROM table1 AS t1
- INNER JOIN table2 AS t2 ON t1.Id = t2.Id
内部联接返回表中更多数据
我们首先给出如下三个测试表
- USE TSQL2012
- GO
- CREATE TABLE FirstTable (Col1 INT)
- CREATE TABLE SecondTable (Col1 INT)
- CREATE TABLE ThirdTable (Col1 INT)
- GO
- INSERT INTO FirstTable (Col1)
- VALUES (1), (2), (3), (NULL)
- GO
- INSERT INTO SecondTable (Col1)
- VALUES (1), (2), (3), (NULL)
- GO
- INSERT INTO ThirdTable (Col1)
- VALUES (2), (2), (2), (2), (2), (NULL)
- GO
(1)等值条件查询
- SELECT f.Col1 fCol1
- FROM FirstTable f
- INNER JOIN SecondTable s ON s.Col1 = f.col1
- GO
(2)非等值条件查询
- USE TSQL2012
- GO
- SELECT f.Col1 fCol1
- FROM FirstTable f
- INNER JOIN SecondTable s ON s.Col1 <> f.col1
- GO
上述我们同样可以利用交叉连接实现同样效果
- USE TSQL2012
- GO
- SELECT f.Col1 fCol1
- FROM FirstTable AS f
- CROSS JOIN SecondTable AS s
- where s.Col1 <> f.col1
- GO
(3)查询非重复行(NON-DISTINCT)
我们在创建第三个测试表时,插入的数据是5个2,而在第一个表中插入的数据分别是1、2、3,此时我们利用等值联接得到的结果到底是1个2,还是5个2呢?
- USE TSQL2012
- GO
- SELECT f.Col1 fCol1
- FROM FirstTable f
- INNER JOIN ThirdTable s ON s.Col1 = f.col1
- GO
我们得到的结果是5个2,为什么利用内部联接也就是说利用的等值条件不是返回1个2呢,其实我们可以总结如下:
结论:利用内部联接比实际表中返回更多数据的原因在于,内部联接返回的结果集是基于查询条件中的JOIN,若有多行满足条件则返回多条数据。
内部联接安全性
在两个表利用等值条件查询时,我们有两种写法。
ANSI SQL-92写法
- USE TSQL2012
- GO
- SELECT *
- FROM Sales.Orders AS SO
- INNER JOIN Sales.OrderDetails AS SOD ON SOD.orderid = SO.orderid
ANSI SQL-89写法
- USE TSQL2012
- GO
- SELECT *
- FROM Sales.Orders AS SO, Sales.OrderDetails AS SOD
- WHERE SOD.orderid = SO.orderid
虽然这两种写法都可以,都能满足需求,但是SQL Server 2012基础教程强烈建议使用ANSI SQL-92写法,为什么呢,因为用ANSI SQL-89写法时若出现错误,此时解析根本不会生成错误,而对于ANSI SQL-92写法则会,下面我们一起来看下ANSI SQL-89写法的问题
- USE TSQL2012
- GO
- SELECT COUNT(*) AS '利用等值条件查询总数据行'
- FROM Sales.Orders AS SO, Sales.OrderDetails AS SOD
- WHERE SOD.orderid = SO.orderid
上面是我们利用正确的写法得到的正确的总数据行为2155条,下面我们看看有问题的写法
- SELECT COUNT( * ) AS '利用等值条件查询总数据行'FROM Sales.Orders AS SO,
- Sales.OrderDetails AS SOD
此时我们没有给出WHERE条件,而解析未出现错误,当然返回的结果集也就是错误的。当我们利用ANSI SQL-92写法时,我们同样也未给出比较条件,如下
- USE TSQL2012
- GO
- SELECT *
- FROM Sales.Orders AS SO
- INNER JOIN Sales.OrderDetails AS SOD;
此时会出现解析错误,也就是无法再继续查询,自然也就得不到错误的结果。
结论:强烈推荐使用ANSI SQL-92写法,这样一来使得数据不会出现不一致性,同时可读性和可维护性比ANSI SQL-89写法强。
总结
本节我们讲了交叉联接和内部联接,同时也给出了使用需要注意的地方,本节到此结束,我们下节再讲讲自联接和外部联接。简短的内容,深入的理解,我们下节再会,good night。
来源: http://www.phperz.com/article/17/0907/339199.html