SQL连接多个表

Posted

技术标签:

【中文标题】SQL连接多个表【英文标题】:SQL joining multiple tables 【发布时间】:2012-01-26 14:02:09 【问题描述】:

使用 Microsoft SQL 2000,我想将多个表(A、B、C 和 D)连接在一起。我知道表 A 始终存在。但是,我只知道至少存在一种表格形式(B,C,D)。

我有什么办法可以做这样的事情来完成我想做的事情吗?

Select * form table a     
If table b exists left Join table b on a.id = b.id    
If table c exists left Join table c on a.id = c.id    
If table d exists left Join table d on a.id = d.id

【问题讨论】:

【参考方案1】:

您必须为此检查数据字典视图并使用动态 SQL

declare @myquery varchar(1000)

set @myquery = 'Select * from a '
if exists (select * from sysobjects where xtype='U' and name = 'b')
begin
   set @myquery = @myquery + 'inner join b on b.id = a.id '
end
if exists (select * from sysobjects where xtype='U' and name = 'c')
begin
   set @myquery = @myquery + 'inner join c on c.id = a.id '
end
if exists (select * from sysobjects where xtype='U' and name = 'd')
begin
   set @myquery = @myquery + 'inner join d on d.id = a.id '
end

exec( @myquery)

我使用过sysobjects,但建议您改用Information Schema Views

而且,动态 SQL 的大免责声明

优势

它提供了灵活性和可扩展性 可以减少编写的代码行数

缺点

它可能变得非常复杂且难以阅读。想想引号中嵌入的引号,以及其他类似的东西。 它会对代码稳定性产生不利影响。一些动态 SQL 错误要到运行时才能知道。 (这方面的一个例子是您引用一个不存在的表) 动态 SQL 代码比等效的静态 SQL 更难测试。也可能无法测试您的 Dynamic SQL 将遇到的所有可能情况,从而引入固有风险。 在您的代码库中对动态 SQL 进行有效的影响分析将更加困难。 SQL 注入和误用 - 动态 SQL 更容易被误用,并且总是比静态 SQL 更不安全 Dynamic SQL 中的查询代码不受查询计划的约束,因此可能会错过优化。因此,它可能比等效的静态 SQL 慢 由于 SQL 查询在运行时才知道,因此可能更难对 SQL 动态代码进行性能调优(例如,确定表上可能需要的索引)

【讨论】:

+1 - 我只会添加这个链接:www.sommarskog.se/dynamic_sql.html 您应该避免在此处使用 *,而应该首选 Object_ID。 @*** 用户:不是这样。 select * 与选择字段名没有明显区别:milambda.blogspot.com/2008/01/whats-wrong-with-count.html @Lieven - 非常感谢...您提供的示例正是我想要的。【参考方案2】:

下面是查询。 * 不应该是查询的一部分,所以最好提及列名。

declare @query varchar(1000)

set @query = 'Select ColumnName from a '
if exists (select Object_ID from sys.tables where name = 'b')
begin
   set @query = @query + 'inner join b on b.id = a.id'
end
if exists (select Object_ID from sys.tables where name = 'c')
begin
   set @query = @query + 'inner join c on b.id = c.id'
end
if exists (select Object_ID from sys.tables where name = 'd')
begin
   set @query = @query + 'inner join d on d.id = a.id'
end

exec( @query)

【讨论】:

它的 sql 2000,sys.tables 只出现在 SQL 2005 中 是的 :) sysobjects 是一个非常通用的术语。所以最好在开发过程中使用可以在特定上下文中理解的特定单词作为开发人员的观点我希望我是对的:) @JamesWiseman 的意思是您使用的是sys.tables,而这在 SQL 2000 中不存在,因此您的查询将无法正常工作【参考方案3】:

您不能以这种方式进行条件连接。

你可以做一个普通的 LEFT JOIN。如果没有行与连接条件匹配,则这些列将为 NULL:

Select *
from table a 
left Join table b on a.id = b.id
left Join table c on a.id = c.id
left Join table d on a.id = d.id

b.* 列可能为 NULL,c.* 列可能为 NULL,d.* 列可能为 NULL。

如果您需要选择第一个非 NULL 列,请使用 COALESCE:

Select *, COALESCE(b.SOMECOLUMN, c.SOMECOLUMN, d.SOMECOLUMN) AS SOMECOLUMN
from table a 
left Join table b on a.id = b.id
left Join table c on a.id = c.id
left Join table d on a.id = d.id

正如评论者所说,如果表不存在,这将不起作用。我想我实际上会提倡继续创建表,以便您的模式始终符合预期。动态 SQL 很难维护和调试,静态 SQL 和模式可以通过元数据进行查询,以确保它们符合预期(即,如果表丢失,过程或视图将无效,并且可以显式查看依赖关系)

【讨论】:

@Cade Roux - 我认为您误读了,OP 不知道 tables B、C 和 D 是否存在。使用动态 SQL 将是解决此问题的一种选择。 这行得通吗?即使 table 不存在(而不是 in 表中的任何行)? 各位,请在盲目投票之前阅读这个问题。 正如@Lieven 所说,如果表 B、C 或 D 不存在,这肯定会失败 @Lieven 我看到了,只是认为它的英语很差。为了避免动态 SQL 和拥有一致的数据库架构(假设他有多个具有不同架构的相似数据库),认为他最好创建缺失的表并将它们留空,这实际上是现实的。【参考方案4】:

我猜你的意思是如果结果不存在而不是表本身。

SELECT * FROM TABLEA
OUTER JOIN TABLEB ON TABLEA.id = TABLEB.id
OUTER JOIN TABLEC ON TABLEA.id = TABLEC.id
OUTER JOIN TABLED ON TABLEA.id = TABLED.id

你只会得到值不匹配的列的空值。

所以你可以过滤

WHERE TABLEB.id is not null

【讨论】:

不,他说的是表本身存在

以上是关于SQL连接多个表的主要内容,如果未能解决你的问题,请参考以下文章

SQL:连接多个表

在连接表语句中访问 SQL 多个 HAVING

(My)SQL:连接多个表

连接多个表后如何从sql查询结果中删除重复记录

SQL:具有相似表的多个左连接

SQL 左连接与 FROM 行上的多个表?