Oracle中的布尔字段


145

昨天,我想向Oracle表中添加一个布尔字段。但是,Oracle中实际上没有布尔数据类型。这里有人知道模拟布尔的最佳方法吗?搜寻主题时发现了几种方法

  1. 使用整数,不要为它分配0或1之外的任何东西。

  2. 使用字符字段“ Y”或“ N”作为仅有的两个值。

  3. 使用带有CHECK约束的枚举。

有经验的Oracle开发人员是否知道哪种方法是首选/规范的?


195
我希望Oracle具有wall数据类型,以便在使用布尔值时可以反对它。
格雷格

Answers:


82

我发现链接很有用。

以下段落重点介绍了每种方法的一些优点/缺点。

最常见的设计是模仿Oracle数据字典视图使用的许多类似Boolean的标志,选择'Y'表示true,选择'N'表示false。但是,要与主机环境(例如JDBC,OCCI和其他编程环境)正确交互,最好为false选择0,为true选择1,以便可以与getBoolean和setBoolean函数一起正常工作。

基本上,为了效率起见,他们提倡方法2,使用

  • 0/1(由于与JDBC getBoolean()等具有互操作性),并且带有检查约束
  • 一种CHAR 类型(因为它使用的空间少于NUMBER)。

他们的例子:

create table tbool (bool char check (bool in (0,1));
insert into tbool values(0);
insert into tbool values(1);`

31
我建议不要使用“ N”和“ Y”,因为它取决于语言。英语国家的人有时会忘记,世界上大多数国家并没有用字母Y表示真理的概念。相反,0和1的含义在语言障碍中是不变的。
Andrew Spencer 2013年

7
在计算机科学中,布尔值0和1不一致-Shell脚本类型语言的成功率通常为0,失败的率通常为非零,而C类型语言的失败率通常为0,成功率则为非零。
Phil

41
作为布尔值,它们是明确的。流程返回码不是布尔值。
Andrew Spencer

13
为什么在此答案中忽略提供的链接中的整个段落?“最常见的设计是模仿Oracle数据字典视图使用的许多类似Boolean的标志,为'true'选择'Y',为false选择'N'。但是,为了与JDBC,OCCI,在其他编程环境中,最好为false选择0,为true选择1,以便它可以与getBoolean和setBoolean函数一起正常工作。” 他们指出,虽然“ Y / N”很常见,但建议使用“ 0/1”来增加与主机环境的兼容性。
justin.hughey 2014年

28

Oracle本身对布尔值使用Y / N。为了完整起见,应注意pl / sql具有布尔类型,只有表没有。

如果您使用该字段指示是否需要处理记录,则可以考虑使用Y和NULL作为值。这使得占用空间很小的索引非常小(快速读取)。


7
+1关于使用Y / N的Oracle内部视图和表的要点。如果甲骨文这样做,那一定是对的!:)
Jeffrey Kemp 2012年

您能解释一下Y和NULL与Y和N相比如何产生小的索引吗?
styfle

6
在Oracle中,没有对NULL进行索引,因此,如果您的索引包含一些Y字符,但大多数情况下为NULL,则索引将非常小。
Leigh Riffel

25

要使用最少的空间,应使用限制为“ Y”或“ N”的CHAR字段。Oracle不支持BOOLEAN,BIT或TINYINT数据类型,因此CHAR的一个字节尽可能小。


19

最好的选择是0和1(作为数字-另一个答案建议将0和1作为CHAR来提高空间效率,但这对我来说有点太扭曲了),使用NOT NULL和检查约束将内容限制为那些值。(如果您需要该列可为空,那么您要处理的不是布尔值,而是具有三个值的枚举...)

0/1的优点:

  • 语言无关。如果每个人都使用'Y'和'N'会很好。但是他们没有。在法国,他们使用“ O”和“ N”(我亲眼所见)。我没有在芬兰编程,看他们在那儿是否使用'E'和'K'-毫无疑问,他们比那更聪明,但是您不确定。
  • 与广泛使用的编程语言(C,C ++,Perl,Javascript)的实践保持一致
  • 在应用程序层(例如休眠)中发挥更好
  • 导致更简洁的SQL,例如,找出准备吃多少香蕉select sum(is_ripe) from bananas而不是select count(*) from bananas where is_ripe = 'Y'(yuk)select sum(case is_ripe when 'Y' then 1 else 0) from bananas

“ Y” /“ N”的优点:

  • 占用的空间少于0/1
  • 这就是甲骨文的建议,所以也许是某些人更习惯的

另一位张贴者建议将“ Y” / null表示为性能提升。如果您已经证明需要性能,那么就足够公平了,但要避免使用它,因为它会使查询变得不那么自然(some_column is null而不是some_column = 0),并且在左联接中,您会将错误与不存在的记录混合在一起。


3
您发现,如今,布尔值很多都是TriState,即true,false和unknown。这完全符合数据库null的想法。仅仅因为很多时候不知道答案是至关重要的
MikeT 2013年

1
是的,可能需要true-false-unknown,尽管如果我很挑剔(我是),我会说它实际上不应被描述为布尔值,因为不是。
Andrew Spencer 2013年

2
如果您要变得挑剔,那么可以为每种数据类型设置相同的参数。如严格定义的整数,双精度(我猜我应该说双精度双精度补码浮点数),二进制,字符串等。所有假定都提供了一个值,但是数据库实现总是添加一个空值选项布尔值没有什么不同
MikeT

1
是的,如果您正确配置了数字,则还可以将其与c​​har字段存储在同一字节中,这会使size参数无效(使用0/1),但我目前找不到链接,但是取决于配置22个字节-从1存储为多个范围
MikeT

4
我怀疑这种否定投票是由于在选择最具内存效率的实现上的传统观点造成的。当今的内存效率远不如优先考虑,在可用性和兼容性之后应予以考虑。对于可能对此评论做出回应的任何人,我建议您阅读有关过早优化的内容。正是基于纯粹的内存效率选择“ Y / N”,这正是发生的情况。由于该决定,您将失去与一组常用框架的本机兼容性。
justin.hughey 2014年

5

具有检查约束的1/0或Y / N。以太的方式很好。我个人更喜欢1/0,因为我在perl中做了很多工作,这使得在数据库字段上执行perl布尔运算非常容易。

如果您想与一位甲骨文公司主管进行深入的讨论,请查看汤姆·凯特(Tom Kyte)关于此的评论


1/0据说“内存效率较低”,但是...我也更喜欢它(并且休眠状态显然需要1/0的布尔值)
rogerdpack

1/0是Hibernate的默认布尔值,但是您可以定义任何喜欢的自定义映射。
Andrew Spencer 2013年

@rogerdpack那是因为char字段是1个字节,或者nchar是2个字节,根据数字的定义方式,数字可以是1到22个字节
MikeT

4

我完成大部分工作的数据库使用'Y'/'N'作为布尔值。通过该实现,您可以实现一些技巧,例如:

  1. 计算正确的行:
    SELECT SUM(当BOOLEAN_FLAG ='Y'然后为1,否则为0时)为X

  2. 在对行进行分组时,强制执行“如果一行为真,则所有为真”逻辑:
    SELECT MAX(BOOLEAN_FLAG)FROM Y
    相反,如果一行为假,则使用MIN强制分组为false。


4
实际上,所示示例对于0/1方法也很有用-恕我直言,更快。
igorsantos12年

2

通过在Oracle数据库中的现有表(使用number类型)中添加“布尔”列来实现可接受的答案的工作示例:

ALTER TABLE my_table_name ADD (
my_new_boolean_column number(1) DEFAULT 0 NOT NULL
CONSTRAINT my_new_boolean_column CHECK (my_new_boolean_column in (1,0))
);

这会创建一个my_table_name名为的新列my_new_boolean_column,默认值为0。该列将不接受NULL值,并将接受的值限制为01


1

在我们的数据库中,我们使用一个枚举来确保将其传递为TRUE或FALSE。如果您采用前两种方式中的任何一种,则很容易要么不经过适当的设计就开始向整数添加新含义,要么以具有Y,y,N,n,T,t的char字段结尾, F,f值,并且必须记住代码的哪个部分使用哪个表以及它使用的是哪个版本的true。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.