我是一个小型开发团队的开发人员,有些事情使我感到恼火,直到我决定采取行动......
Oracle不支持Bit数据类型 - 或者实际上在真/假场景中明显有意义的任何其他内容。然而,在我加入团队之前,我的祖先决定使用char(1)字段,使用特定的字母来表示是/ true。不幸的是,我们的应用程序已经被世界各地的人们所熟悉,并且由于坦率地无视我理解的所有尝试的原因,所使用的价值因本地化而异。
是的,我知道对于后端用户从未见过的值来说完全没有必要 - 但是...
我注意到这种做法似乎正在被推进到新的发展中,这让我感到很疯狂 - 所以我想为此提出数字(1,0) - 0被认为是假/不,任何事情否则被解释为真/是......
简单的问题 - 任何人都可以想到这可能是一个坏主意的原因吗?
虽然我们是关于它的,有谁知道为什么Oracle不支持简单的布尔类型?这不是一个明智的遗产吗?
期待干杯,
马丁。
答案 0 :(得分:27)
使用CHAR(1)和约束仅允许'1'和'0'。
...
col CHAR(1),
CONSTRAINT cons_atable_col1 CHECK (col1 IN ('1','0'))
答案 1 :(得分:16)
我不是英国人,所以我倾向于使用1和0或'1'和'0'。如果你不是用英语编码,那么使用'Y'和'N'是没有意义的(是的,确实存在母语编码)。使用'SI'和'NO'或'S'和'N'看起来并不专业(就像用重音字母命名变量一样)。相反,如果您使用C,PHP或JavaScript进行编码,那么它们就是非常标准的。在任何情况下,我总是添加适当的约束来禁止任何其他字符。除了主观问题之外,我认为在选择CHAR或NUMBER时不会有明显的性能提升。我更喜欢数字,因为我不需要引用它们。)
我同意这是一个明显的遗漏,但我在一些Oracle论坛上读过关于这个主题的热烈讨论;这是一种宗教问题。一些人声称布尔值属于应用程序数据类型,并且在数据库核心中没有位置。老实说,我相信这是我们在没有它的情况下长得那么久,我们最好说它是用途的。
顺便说一句,MySQL有一个BOOLEAN类型,但它是TINYINT(1)的同义词,所以它最终等于1和0;这很好,因为它还有常量TRUE和FALSE,评估为1和0。
答案 2 :(得分:11)
我更喜欢char(1)而不是数字(1),因为通过一些合理的字符选择,很明显哪个字符具有哪个布尔含义。
当然你应该对抗所有不同的变体,选择一个并通过在列上设置检查约束来确保它的使用。
虽然在您的情况下可能要迟到,但从其他工具生成架构通常至少会考虑一致性问题。我个人更喜欢hibernate用于此目的,但这是特定情况。
当然,这是一个明显的遗憾。更糟糕的是,PL / SQL有一个布尔值,但你不能在SQL语句中使用它。
答案 3 :(得分:8)
以下是关于该主题的Ask Tom讨论。提供有关该问题的以Oracle为中心的观点。
至于存储,char(1)实际上有点(没有双关语)更高效:
SQL> CREATE TABLE xx (c CHAR(1), n NUMBER);
Table created
SQL> insert into xx values('T', 1);
1 row inserted
SQL> select dump(c), dump(n) from xx;
DUMP(C) DUMP(N)
------------------- -------------
Typ=96 Len=1: 84 Typ=2 Len=2: 193,2
答案 4 :(得分:3)
根据此Oracle指南 - 您应该使用NUMBER(3)。疯了,但也是如此。
http://docs.oracle.com/cd/B19306_01/gateways.102/b14270/apa.htm
答案 5 :(得分:2)
Number(1)并不比char(1)好。特别是如果它除了现有的char(1)之外。这只会增加混乱。
FWIW,内部视图中的Oracle(例如USER_TAB_COLUMNS)使用varchar2(3)(YES和NO)。不过,不确定它们是否100%一致。
答案 6 :(得分:0)
问题是陈旧但在使用oracle的最新版本之前,它仍然是一个有效的问题。
我会这样解决问题: 创建一个表,其中包含true / false的可能值以及本地化的显示文本f.e. T $关键词 ITEMNO ITEMTEXT ITEMTEXT_DE ITEMTEXT_FE ...... 0假Falsch 1真实的Wahr
而不是True / False,也可以选择,未选择等等。
然后将列的foreigh键添加到此表中。这样,您只有有效值,并且不会随本地化而改变。
另一个好的解决方案imho正在对您的数据列使用检查约束。如果根据客户端的本地化,您的值在同一数据库/列中可能不同,则此ofc不起作用。
alter table tblLocations add flag number CONSTRAINT <constraintname> CHECK (flag IN (1,0));
答案 7 :(得分:0)
Oracle在不同的数据字典视图中内部使用“位”(不是数据类型本身)。
例如,dba_users视图具有:
..
, DECODE (BITAND (u.spare1, 128), 128, 'YES', 'NO')
..
, DECODE (BITAND (u.spare1, 256), 256, 'Y', 'N')
..
显示了一种以某种方式解决此问题的方法。如果您不必经常修改“布尔”位,则可以使用Oracle自Oracle 6以来的相同方法(至少)。创建一个包含NUMBER列的表格,并在其顶部显示隐藏BITAND操作复杂性的VIEW。
PS。另外,Oracle JDBC有一个“位”数据类型https://docs.oracle.com/cd/E16338_01/appdev.112/e13995/oracle/jdbc/OracleTypes.html#BIT,你已经知道PL / SQL有布尔值。虽然它可能对你没什么帮助。如果适合您的情况,请参阅上面的BITAND方法。
答案 8 :(得分:-1)
https://docs.oracle.com/cd/E17952_01/refman-5.5-en/char.html
正如DCookie所说,char(1)效率更高。 因为VARCHAR2(VARCHAR)为空包含1个字节,但是当我们存储1个字符然后清空1个字节大小+字符1个字节大小 - &gt; 2字节需要在varchar中存储1个字符