SQL Server创建存储过程实现多表JOIN关联查询方案
实现参考
你写的两表INNER JOIN语法本身没有错误,正常在AdventureWorks2016里执行应该毫秒级返回2万行左右结果,长时间无响应基本是存在会话阻塞:打开SSMS新建查询执行sp_who2,查看BlkBy列找到阻塞当前查询的会话ID,执行KILL 会话ID后重试即可。
下面是满足你需求的四表关联实现,包含存储过程写法:
核心关联逻辑说明
- 以
Person.Person作为人员主表,通过公共字段BusinessEntityID关联邮箱表Person.EmailAddress、电话表Person.PersonPhone - 电话表通过
PhoneNumberTypeID关联号码类型字典表Person.PhoneNumberType,拿到号码类型名称 - 如果需要返回所有人员的全量记录(包含没有登记邮箱、没有登记电话的人员),主表和其他表关联用LEFT JOIN;如果要求必须同时有邮箱和电话才返回,全部换成INNER JOIN即可,符合题目要求用JOIN语法的规则。
可直接运行的代码
基础查询语句
SELECT p.FirstName, p.MiddleName, p.LastName, ea.EmailAddress AS [email address], pp.PhoneNumber AS [phone number], pnt.Name AS [phonenumber type] FROM Person.Person p LEFT JOIN Person.EmailAddress ea ON p.BusinessEntityID = ea.BusinessEntityID LEFT JOIN Person.PersonPhone pp ON p.BusinessEntityID = pp.BusinessEntityID LEFT JOIN Person.PhoneNumberType pnt ON pp.PhoneNumberTypeID = pnt.PhoneNumberTypeID
存储过程创建与调用
-- 创建存储过程 CREATE PROCEDURE Person.GetFullPersonContactList AS BEGIN -- 关闭"影响行数"消息返回,减少不必要的传输开销 SET NOCOUNT ON; SELECT p.FirstName, p.MiddleName, p.LastName, ea.EmailAddress AS [email address], pp.PhoneNumber AS [phone number], pnt.Name AS [phonenumber type] FROM Person.Person p LEFT JOIN Person.EmailAddress ea ON p.BusinessEntityID = ea.BusinessEntityID LEFT JOIN Person.PersonPhone pp ON p.BusinessEntityID = pp.BusinessEntityID LEFT JOIN Person.PhoneNumberType pnt ON pp.PhoneNumberTypeID = pnt.PhoneNumberTypeID END GO -- 测试执行存储过程 EXEC Person.GetFullPersonContactList
初学者注意点
- 多表关联时给表设置短别名(示例里的p/ea/pp/pnt),既能简化代码,也能避免字段归属表写错的问题
- 带空格的字段别名必须用方括号
[]包裹,否则会触发语法错误 - 写JOIN时一定要写全关联条件,漏写条件会产生笛卡尔积,导致返回数据量爆炸式增长、查询超时
- 如果后续遇到查询慢的问题,可以在SSMS里开启「包括实际执行计划」排查,官方示例库默认索引配置完整,2万行规模的数据不会出现性能问题
内容的提问来源于stack exchange,提问作者Affy
相关产品推荐
相关产品推荐

