代码之家  ›  专栏  ›  技术社区  ›  John Gordon

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

sql
  •  1
  • John Gordon  · 技术社区  · 15 年前

    存放特定物品的桌子:猫、鞋和书。

    对象

    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)
    

    从用户的角度来看,每个特定的对象主要是 名字,鞋柜是模特,书桌是

    假设我拿到了一个物品的id,却事先不知道是什么 它所代表的对象——猫、鞋或书。我怎么写

    很明显会有点像这样:

    SELECT object_type,name FROM object WHERE object_id = 12345;
    

    但如何才能在“姓名”栏中找到正确的内容呢?

    8 回复  |  直到 15 年前
        1
  •  8
  •   Dan J    15 年前

    似乎您正在描述一个场景,其中用户对数据的视图(对象有名称,我不在乎它们是什么类型)与您用于存储数据的模型不同。

    如果是这样,并且假设您对数据库对象有一些控制权,我可能会创建一个 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
  •  1
  •   Adam Robinson    15 年前

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

    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
    

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

    • 子表的主键( cat , shoe book )也应该是父表的外键( object ). 你不应该有不同的钥匙,除非有两个 记录可以表示相同的 对象
    • 公共元素(如名称)应在层次结构的最高级别(在本例中是 对象
        3
  •  0
  •   Breezer    15 年前
        4
  •  0
  •   Dustin Laine    15 年前

    你不能。为什么不给他们起同样的名字,或者把那个名字拉回到 OBJECT 桌子。您可以很容易地创建一个名为 Name OBEJCT 桌子。这仍将正常化。

        5
  •  0
  •   atk    15 年前

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

        6
  •  0
  •   Dean Harding    15 年前

    如果没有第一个 SELECT kind ,然后 选择 选择 还有一堆 LEFT JOIN

    但只要稍微考虑一下,用户看到的“标识符”是不是 不得不 object_id 12345是一款鞋,你可以从用户的角度将其“编码”为“S12345”。一本书是“B4567”,一只猫是“C2578”。然后在代码中,只需分离出第一个字母并用它来决定要加入哪个表,剩下的数字就是您的主键。

        7
  •  0
  •   rkg    15 年前

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

        8
  •  0
  •   Mr Shoubs    15 年前

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

    在postgres中,这类似于pg_stat_alltables,我认为在sql server中也有类似的东西。你可以查询这个并找出你需要的,然后基于这个信息构造一个查询。。。

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