【问题标题】:Whats the equivalent of MySQL Set datatype in Oracle?什么相当于 Oracle 中的 MySQL Set 数据类型?
【发布时间】:2019-05-02 18:34:10
【问题描述】:

在 MySQL 中,我们可以使用 Set 数据类型为任何特定行的每一列选择多个值,如下所示:

CREATE TABLE `staff` ( `StaffID` int(5) NOT NULL AUTO_INCREMENT,
                  `Availability` set('Mon','Tue','Wed','Thur','Fri','SatAM','SatPM','Sun') DEFAULT NULL, 
                  PRIMARY KEY (`StaffID`))

那我就可以了,

INSERT INTO `staff` (`Availability`) VALUES ('Tue,Wed,SatPM')

我试图到处寻找,但找不到任何合适的数据类型来存储上述 Oracle 中的多个选定选项。 Oracle 文档似乎显示没有 MySQL 集的替代品,但我不敢相信他们没有它!那么有人可以帮我澄清一下吗?

Oracle Documentation referenceOriginal link

【问题讨论】:

  • 仅仅因为mysql有一个特性,并不意味着它是一个好主意/rdbms应该有的东西。您可以使用字符串、xml、json 或将有效的多:多关系分解为一组表,这些表通过“staff_availableday”表将“staff”与“availableday”表相关联。在规范化良好的数据库中,只有后者才是真正正确的
  • 我认为您需要在 Oracle 中设计一个不同的表结构。
  • 除了添加到@CaiusJard 的评论中。如果无法使用 InnoDB 的在线 DDL,更改 MySQL 的 SET 数据类型选项很可能需要完整的表重建和/或表锁定。
  • 您所描述的内容听起来与 Oracle SQL 中的 nested table 数据类型隐约相似。虽然有一些差异。首先,Oracle SQL 中没有通用的嵌套表类型;你必须首先CREATE TYPE 来命名一个特定的嵌套表数据类型,然后你可以在你的CREATE TABLE 语句中使用它,你可以使用构造函数来INSERT 值。然后,嵌套表是多集(它们允许重复) - 不确定 set 数据类型是否存在(可能不是)。
  • 最后,set 似乎将值限制在CREATE TABLE 中声明的值;不确定 Oracle 中是否存在等效的东西,但如果存在,很可能是通过约束完成的。

标签: mysql sql database oracle oracle12c


【解决方案1】:

在 MySQL 中,set 数据类型是命名的位图数据类型。 Oracle 没有,但如果您真的想使用受约束的整数数据类型,您可以模拟它:

CREATE TABLE staff (
    staffid INTEGER GENERATED BY DEFAULT AS IDENTITY ( START WITH 1 NOCACHE ORDER ) NOT NULL PRIMARY KEY
  , availability INTEGER CHECK ( availability BETWEEN 0 AND 256 )
);

您必须记住或构建一个函数来映射位图值和日期。

另一种选择是使用查找表:

create table availability as
with t1(id, mon, tue, wed, thu, fri, satam, satpm, sun) as (
select 0, 0, 0, 0, 0, 0, 0, 0, 0 from dual
union all
select id+1
     , sign(bitand(id+1,1))
     , sign(bitand(id+1,2))
     , sign(bitand(id+1,4))
     , sign(bitand(id+1,8))
     , sign(bitand(id+1,16))
     , sign(bitand(id+1,32))
     , sign(bitand(id+1,64))
     , sign(bitand(id+1,128))
  from t1 where id+1 <256
)
select * from t1;

alter table availability add primary key (id);

CREATE TABLE staff (
    staffid INTEGER GENERATED BY DEFAULT AS IDENTITY ( START WITH 1 NOCACHE ORDER ) NOT NULL PRIMARY KEY
  , availability INTEGER 
  , CONSTRAINT staff_avail_fk FOREIGN KEY ( availability ) REFERENCES availability ( id ) 
);

【讨论】:

    【解决方案2】:

    哨兵的回答(我赞成)解决了字面上的问题。

    但是,我将退后一步,将问题解决为“我如何在 Oracle 中表示这种类型的数据”,建议解决该问题的更好方法是 模拟 Set 数据类型。

    Set 数据类型可以说违反了第一范式。这不一定是对其用法的道德判断;这样的解决方案使某些查询更容易和/或更有效,而其他查询更困难和/或效率更低。但是标准形式是建立在 RDBMS 多年的经验之上的。对于广泛的应用,坚持前三个范式是避免平衡问题的好方法。

    可以在 Oracle 中实现的规范化解决方案(无需跳过箍来模拟位字段枚举)可能包括一个带有 ID 的 Staff 表,一个带有一行用于集合中每个单独值的 AvailabilityCode 表和StaffAvailability,这是两者之间的交叉引用,其中每个可用性代码值对应一个您想要与员工 ID 关联的行。

    【讨论】:

      猜你喜欢
      • 2011-11-01
      • 1970-01-01
      • 2017-02-24
      • 2014-08-08
      • 1970-01-01
      • 1970-01-01
      • 2011-03-31
      • 1970-01-01
      • 2012-02-21
      相关资源
      最近更新 更多