ChatGPT解决这个技术问题 Extra ChatGPT

Oracle 中的布尔字段

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

使用一个整数,不要费心为它分配除 0 或 1 以外的任何东西。使用带有 'Y' 或 'N' 作为仅有的两个值的 char 字段。使用带有 CHECK 约束的枚举。

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

我希望 Oracle 有一个 wall 数据类型,这样我就可以在使用布尔值时撞到它。

S
Shog9

我发现 this 链接很有用。

这是强调每种方法的一些优点/缺点的段落。

最常见的设计是模仿 Oracle 的数据字典视图使用的许多类似布尔值的标志,选择“Y”代表真,“N”代表假。但是,要与主机环境(例如 JDBC、OCCI 和其他编程环境)正确交互,最好选择 0 代表 false 和 1 代表 true,以便它可以正确使用 getBoolean 和 setBoolean 函数。

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

具有检查约束的 0/1 值(因为与 JDBC 的 getBoolean() 等的互操作性)

一种 CHAR(因为它使用的空间比 NUMBER 少)。

他们的例子:

创建表 tbool(bool char 检查(bool in (0,1));插入 tbool 值(0);插入 tbool 值(1);`


我建议不要使用“N”和“Y”,因为它取决于语言。讲英语的人有时会忘记,世界上大多数地方并不用字母 Y 来代表真理的概念。相比之下,0 和 1 的含义跨越语言障碍是不变的。
0 和 1 作为布尔值在计算机科学中并不一致 - shell 脚本类型语言倾向于将 0 表示为成功,非零表示失败,而 C 类型语言倾向于将 0 表示为失败,非零表示成功。
作为布尔值,它们是明确的。进程返回码不是布尔值。
为什么此答案中忽略了提供的链接中的整个段落? “最常见的设计是模仿 Oracle 的数据字典视图使用的许多类似布尔值的标志,选择“Y”代表真,“N”代表假。但是,要与主机环境正确交互,例如 JDBC、OCCI、和其他编程环境,最好选择 0 代表 false 和 1 代表 true 以便它可以正确使用 getBoolean 和 setBoolean 函数。"他们指出,虽然“Y/N”很常见,但建议使用“0/1”来增加与主机环境的兼容性。
L
Leigh Riffel

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

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


+1 关于使用 Y/N 的 Oracle 内部视图和表的要点。如果 Oracle 这样做,那一定是对的! :)
你能解释一下与 Y 和 N 相比,Y 和 NULL 是如何创建一个小索引的吗?
NULL 在 Oracle 中没有索引,因此如果您的索引包含几个 Y 字符,但大多数是 NULL,那么您将拥有一个非常小的索引。
B
Bill the Lizard

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


A
Andrew Spencer

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

0/1 的优点:

语言无关。如果每个人都使用它,“Y”和“N”就可以了。但他们没有。在法国,他们使用“O”和“N”(我亲眼目睹了这一点)。我没有在芬兰编程看看他们是否在那里使用“E”和“K”——毫无疑问他们比那更聪明,但你不能确定。

与广泛使用的编程语言(C、C++、Perl、Javascript)的实践一致

与应用程序层(例如 Hibernate)配合得更好

导致更简洁的 SQL,例如,找出有多少香蕉可以吃is_ripe when 'Y' then 1 else 0) from bananas

“Y”/“N”的优点:

占用空间小于 0/1

这是甲骨文建议的,所以可能是一些人更习惯的

另一张海报建议使用“Y”/null 来提高性能。如果您证明您需要性能,那么就足够公平了,但否则请避免,因为它会使查询变得不那么自然(some_column is null 而不是 some_column = 0),并且在左连接中你会混为一谈虚假与不存在的记录。


你发现现在很多布尔值都是三态的,即真、假和未知。这完全符合数据库空的想法。仅仅因为很多时候知道没有答案是至关重要的
是的,可能需要真假未知,但如果我很挑剔(我就是这样),我会说它不应该被描述为布尔值,因为它不是。
如果您要那么挑剔,那么您可以为每种数据类型提出相同的论点。正如在严格定义下的整数、双精度(我想我应该说双倍长度二进制补码浮点)、二进制、字符串等都假设提供了一个值,但数据库实现总是添加一个空值选项布尔没有任何不同
是的,如果您正确配置了您的数字,它也可以存储在与 char 字段相同的单个字节中,这会使使用 0 / 1 的大小参数无效,我目前找不到链接但是数字的存储范围为 1 - 22 个字节,具体取决于配置
我怀疑这些反对意见是由于对选择内存效率最高的实现的传统观点造成的。当今时代的内存效率远没有那么重要,应该在可用性和兼容性之后考虑。对于任何可能对此评论做出回应的人,我建议阅读有关过早优化的内容。这正是纯粹基于内存效率选择“Y/N”所发生的情况。由于该决定,您将失去与一组常用框架的本机兼容性。
M
Matthew Watson

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

如果您想与 Oracle 的一位大佬深入讨论这个问题,请查看 Tom Kyte 对此Here的看法


1/0 被认为是“内存效率较低”,但是......我也更喜欢它(而且休眠显然需要 1/0 作为布尔值)
1/0 是 Hibernate 的默认布尔值,但您可以定义任何您喜欢的自定义映射。
@rogerdpack 那是因为 char 字段是 1 个字节,或者 nchar 是 2 个字节,其中取决于它的定义方式,数字可以是 1 到 22 个字节
E
Erick B

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

计算为真的行数:SELECT SUM(CASE WHEN BOOLEAN_FLAG = 'Y' THEN 1 ELSE 0) FROM X 对行进行分组时,强制执行“如果一行为真,则全部为真”逻辑:SELECT MAX(BOOLEAN_FLAG) FROM Y 相反,如果一行为假,则使用 MIN 强制分组为假。


事实上,显示的示例对于 0/1 方法也很有用 - 而且,恕我直言,更快。
B
Ben.12

通过将“布尔”列添加到 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


R
Ryan Ahearn

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