【问题标题】:How to write a SELECT statement when I don't know in advance what columns I want?当我事先不知道我想要什么列时,如何编写 SELECT 语句?
【发布时间】:2010-11-01 22:48:58
【问题描述】:

我的应用程序有几个表:一个主 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;

但是如何在“名称”列中获取正确的内容呢?

【问题讨论】:

    标签: sql


    【解决方案1】:

    您似乎在描述一种场景,即用户对数据的看法(对象有名称,我不在乎它们是什么类型)与您用于存储数据的模型不同。

    如果是这种情况,并且假设您对数据库对象有一定的控制权,我可能会创建一个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,而不用关心底层的列名。

    【讨论】:

      【解决方案2】:

      您唯一真正的解决方案基本上归结为同一件事:为每个特定表编写显式语句并将unioning 到单个结果集中。

      您可以在视图中执行此操作(为您提供可以查询的动态数据库对象)或作为查询的一部分(无论是直接 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,因为所有对象都有“名称”的概念)。

      【讨论】:

      • 每个子表的主键是故意分开的。我希望能够同时拥有 cat_id 为 1 的 Cat 记录和 shoe_id 为 1 的 Shoe 记录。
      • @John:在传统的表继承模式中,您没有 cat_id。您的外键 object_id 用作继承表的主键(在本例中为 cat)。
      【解决方案3】:

      【讨论】:

      • 不是简单的join。他想在不知道类型的情况下根据ID逻辑选择正确的列名。
      【解决方案4】:

      你不能。为什么不将它们命名为相同的名称,或者将该名称拉回OBJECT 表。您可以非常轻松地创建一个名为Name 的列并将其放入OBEJCT 表中。这仍然会被规范化。

      【讨论】:

      • 我希望关于特定猫的所有信息都放在一个位置(即 CAT 表的一行)。如果我将名称放在 OBJECT 表中,那么我必须查看两个位置,这是我不想要的。如果您跟踪记录上次更新的时间,它还会引入歧义——如果上周更新了 CAT 记录但昨天更新了该猫的 OBJECT 记录,那么您将显示什么作为“最后更新日期”?
      【解决方案5】:

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

      选择哪个?你在解决什么问题?你在解决什么问题,是谁的解决方案造成了这个问题?

      【讨论】:

        【解决方案6】:

        如果不先SELECTing 找出kind,然后再通过SELECTing 第二次获取实际数据,真的没有办法做到这一点。如果您只有几种不同类型的对象,您可以使用单个 SELECT 和一堆 LEFT JOINs 来一次加入所有表,但如果您有很多,则不能很好地扩展连接器表。

        但只是跳出框框思考一下,用户看到的“标识符”必须与表中的主键完全对应吗?你能在标识符本身中编码对象的“种类”吗?例如,如果object_id 12345 是一只鞋,那么从用户的角度来看,您可以将其“编码”为“S12345”。一本书是“B4567”,一只猫是“C2578”。然后在您的代码中,只需分离出第一个字母并使用它来决定要加入哪个表,其余数字是您的主键。

        【讨论】:

        • 呃,这听起来很难看。这在概念上可能是一个好主意,但请不要像用户看到的那样使用 S12345 和 C2578 来实现它!
        【解决方案7】:

        如果由于依赖关系而无法更改原始表,则可以创建具有统一列名的表视图。更多关于如何创建视图的信息可以在here找到。

        【讨论】:

          【解决方案8】:

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

          在 postgres 中,这类似于 pg_stat_alltables,我认为在 sql server 中也有类似的东西。您可以对此进行查询并计算出您需要什么,然后根据该信息构造一个查询...

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

          【讨论】:

            猜你喜欢
            • 2013-07-28
            • 2016-08-05
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-06-20
            • 2015-08-06
            • 2021-10-04
            • 2013-05-21
            相关资源
            最近更新 更多