【问题标题】:What is the best way to define a column in SQL server that may contain either an integer or a string?在 SQL Server 中定义可能包含整数或字符串的列的最佳方法是什么?
【发布时间】:2010-10-25 21:24:15
【问题描述】:

我有一种情况,两个相同类型的对象有不同类型的父对象。 下面的伪代码最能说明这种情况:

TypeA a1, a2;
TypeB b;
TypeC c;
a1.Parent = b;
a2.Parent = c;

更复杂的是,TypeB 和 TypeC 可能具有不同类型的主键,例如,以下断言可能是正确的:

Assert(b.Id is string && c.Id is int);

我的问题是在 SQL Server 中定义这种父子关系的最佳方式是什么? 我能想到的唯一解决方案是定义 TypeA 表有两列 - ParentId 和 ParentType,其中:

  • ParentId 是 sql_variant - 能够同时保存数字和字符串
  • ParentType 是字符串 - 保留父类型的程序集限定名称。

但是,当我基于 sql_variant 定义用户数据类型时,它将字段大小指定为固定的 8016 字节,这似乎太多了。

必须有更好的方法。任何人? 谢谢。

【问题讨论】:

  • 出于兴趣,如果您使用这种方法,索引和性能会受到怎样的影响?
  • +1。没有理由不赞成这个问题。正如 marc_s 所说,不要,但问题本身是明确和有效的。我们都在这里学习。

标签: sql sql-server sql-variant


【解决方案1】:

一个字:不要

这是非常糟糕的做法 - 列具有一个单一的数据类型是有原因的。不要滥用这个,把所有东西都变成变种......

马克

【讨论】:

  • marc_s 是绝对正确的。建立在这种关系之上只会导致更多问题。
  • 有非常正当的理由需要这样的东西。想象一个通用实体框架,其中实体按层次排列。添加以下两个要求,您将被引导到所描述的情况: 1. 给定一个实体类型,它没有任何关于哪些实体类型可能是其有效父级的硬编码知识。这是在部署时解决的,取决于其他实体的说法。 2. 实体 ID 不必是整数。它也可以是 GUID 或字符串。鉴于这些,不能将 ParentId 列类型指定为 int。
【解决方案2】:

如果 NEITHER 列永远不会参与任何数学运算,请将它们设为 CHAR() 或 VARCHAR(),因为您将处理一系列字符,而不是数字。在这种情况下,“1”与“A”一样有效。

【讨论】:

    【解决方案3】:

    我不确定我是否完全理解您的情况,但在类似的情况下,我在 TableA 上创建了两列,一列存储字符串键,一列存储 int 键;最终它们都可以为 NULLable(但不在同一记录中)。

    【讨论】:

      【解决方案4】:

      通过使用一列,您消除了设置外键关系的能力,从而引入了不良数据的可能性。您需要将每个表的键存储在不同的字段中,因为它们是表示不同事物的不同数据。将它们存储在一列中是一个非常糟糕的主意。

      【讨论】:

        【解决方案5】:

        嗯,有两个问题。首先是 OO 设计,在您的模型中 TypeA 可以有不同类型的父级,而这些类型(TypeB 和 TypeC)没有共同的父级。显然,我不相信它会是真实的。但是我不知道这些类型的含义...如果你从一些TypeX继承TypeB和TypeC就可以解决这个问题,在这种情况下我将在TypeA中引用TypeX。

        第二个是数据库设计。由于 OO 设计中的错误,您在 DB 端遇到问题。解决方案是一样的 - 为 TypeX 创建单独的表,并将 TypeA 和 TypeB 之间的所有公共属性放在此处,为 TypeA 和 TypeB 创建单独的表。 TypeX 与 TypeA 以及 TypeB 的关系为 1:1。 在这种情况下,TypeA 创建看起来是这样的——在 TypeX 中插入新行,获取 ID,在 TypeA 中插入行。在此解决方案中,您将在 TypeX 和 TypeA 或 TypeX 和 TypeB 中找到匹配的行。

        TypeX(TypexID int not null 主键标识 (1,1), SomeCommonColumn int) TypeA(TypexID int not null 主键,TypeASpecific int) TypeB(TypexID int not null primary key, TypeBSpecific varchar)

        只有用关系理论来实现这种情况的方法——清晰且非冗余的方式。它看起来不是很简单,但通常这些表被视图和存储过程覆盖,因此这些表可以被应用程序用作单个(虚拟)表。

        谢谢你, 亚历山大

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-07-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-12-21
          • 1970-01-01
          • 2012-06-15
          相关资源
          最近更新 更多