当我事先不知道我想要哪些列时,如何编写SELECT语句?

时间:2010-11-01 22:48:58

标签: sql

我的应用程序有几个表:一个主OBJECT表和几个 用于存储特定种类对象的表:CAT,SHOE和BOOK。

以下是表格列的外观:

物体

object_id    (primary key)
object_type  (string)

cat_id       (primary key)
object_id    (foreign key)
name         (string)
color        (string)

shoe_id      (primary key)
object_id    (foreign key)
model        (string)
size         (string)

book_id      (primary key)
object_id    (foreign key)
title        (string)
author       (string)

从用户的角度来看,主要识别每个特定对象 按名称,每个表的列不同。对于CAT表 它的名字,对于SHOE表它的模型,以及它的BOOK表 标题。

假设我在没有预先知道什么样的情况下交了一个object_id 它代表的对象 - 猫,鞋或书。我怎么写一个 SELECT语句获取此信息?

显然它看起来有点像这样:

SELECT object_type,name FROM object WHERE object_id = 12345;

但是如何在“名称”栏中找到正确的内容?

8 个答案:

答案 0 :(得分:8)

您好像在描述用户对数据的看法(对象有名称,我不关心它们是什么类型)与您用来存储数据的模型不同的场景。

如果是这种情况,假设您对数据库对象有一定的控制权,我可能会创建一个VIEW,允许您为每种类型的对象合并类似的数据。

SQL Server上的示例:

CREATE VIEW object_names AS
SELECT object_id, name FROM cat
UNION ALL
SELECT object_id, model AS name FROM shoe
UNION ALL
SELECT object_id, title AS name FROM book
GO

然后,您可以SELECT name FROM object_names WHERE object_id = 12345,而不必考虑基础列名称。

答案 1 :(得分:1)

你唯一真正的解决方案基本归结为同样的事情:为每个特定的表编写显式语句,并union将它们组合成一个结果集。

您可以在视图中执行此操作(为您提供可以查询的动态数据库对象)或作为查询的一部分(无论是直接SQL还是存储过程)。您没有提到您正在使用的数据库,但基本查询是这样的:

select object_id, name from cat where object_id = 12345 union all
select object_id, model from shoe where object_id = 12345 union all
select object_id, title from book where object_id = 12345 

对于SQL Server,创建视图的语法为:

create view object_view as
select 'cat' as type, object_id, name from cat union all
select 'shoe', object_id, model from shoe union all
select 'book', object_id, title from book

您可以查询:

select type, name from object_view where object_id = 12345

但是,你所拥有的是一个基本的表继承模式,但它实现得不正确,因为:

  • 子表(catshoebook)的主键也应该是父表(object)的外键。你不应该有一个不同的密钥,除非两个cat记录可以代表相同的object(在这种情况下,这根本不是继承)
  • 公共元素(例如名称)应该适当地在层次结构的最高级别表示(在本例中为object,因为所有对象都具有“名称”的概念)。 / LI>

答案 2 :(得分:0)

答案 3 :(得分:0)

你做不到。为什么不将它们命名为相同的东西,或者将该名称拉回OBJECT表。您可以非常轻松地创建名为Name的列,并将其放在OBEJCT表中。这仍然会正常化。

答案 4 :(得分:0)

看起来你有几个选择。您可以使用配置文件或“架构”表。您可以重命名表,以便ye列的名称始终相同。您可以让代码中的类知道它的表。您可以使您的架构不那么通用,并允许数据访问层理解它正在访问的数据。

选择哪个?你在解决什么问题?您解决了什么问题,其解决方案是否产生了这个问题?

答案 5 :(得分:0)

如果没有先SELECT找出kind,然后SELECT第二次获取实际数据,就没有办法做到这一点。如果你只有几种不同类型的对象,你可以用一个SELECT和一堆LEFT JOIN来同时加入所有表,但如果你不能很好地扩展它有很多木工桌。

但是只是稍微考虑一下,用户看到的“标识符”是否与表中的主键完全对应?你能在标识符本身中编码对象的“种类”吗?因此,例如,如果object_id 12345是鞋子,您可以从用户的角度将其“编码”为“S12345”。一本书是“B4567”和一只猫“C2578”。然后在你的代码中,只需将第一个字母分开并使用它来决定加入哪个表,剩下的数字就是你的主键。

答案 6 :(得分:0)

如果由于依赖性而无法更改原始表,则可以使用统一列名创建表的视图。有关如何创建视图的更多信息,请参见here

答案 7 :(得分:0)

您可以查看一个表,告诉您数据库中所有表(和列属性)的属性。

在postgres中这类似于pg_stat_alltables,我认为在sql server中有类似的东西。您可以查询并找出所需内容,然后根据该信息构建查询...

编辑:抱歉重读这个问题,我认为这不是你所需要的。 - 我之前通过一个代理键表解决了一个类似的问题 - 一个表包含所有id和一个类型id,然后是一个包含该表主键的串行/标识列 - 这是你应该使用的id ...然后您可以创建一个视图,该视图根据该表中的类型ID查找其他信息。 'entity ref'表将包含列'entityref'(PK),'id','type id'等...(假设你无法重组以使用继承)