如何指定银行帐号的最小和最大位数?

Mic*_*ski 3 sql postgresql database-design types constraints

是否可以约束PostgreSQL中整数数据类型列中允许的位数.我有以下示例:

CREATE TABLE bank_accounts (    
    id              SERIAL       PRIMARY KEY
  , number_account  INTEGER(26)  NOT NULL
);
Run Code Online (Sandbox Code Playgroud)

我们可以输入如下内容:

1 -- one digit
23 -- two digits
444 -- three digits
5555 -- four digits
Run Code Online (Sandbox Code Playgroud)

等等......最多26位数.

但我想我的约束列来存储恰好 26个数字,而不是更少而不是更多.怎么实现呢?

Erw*_*ter 6

银行帐号本质上不是整数.26个十进制数字是太多integer还是bigint反正.

真的,银行帐号根本不是数值,即使我们可以使用该类型numeric进行存储.它可以轻松处理26位小数.但它也允许小数位(和其他装饰者,如@klin评论).您可以限制numeric(26),这是短期的numeric(26,0),从存储删除小数位数.但是仍然允许输入的小数位数,然后四舍五入.和其他装饰者.所有这些似乎都不适合银行帐号:

SELECT numeric(26) '12345678901234567890123456'
     , numeric(26) '12345678901234567890123456.4'  -- rounded down
     , numeric(26) '12345678901234567890123456.5'  -- rounded up
     , numeric(26) '1e25'
     , numeric(26) '1.2345e25'
     , numeric(26) '+12345678901234567890123456.5'

SELECT numeric(26) '99999999999999999999999999.5'  -- error after rounding up
Run Code Online (Sandbox Code Playgroud)

银行帐号本质上更像是文本,因此数据类型text似乎更合适(如@klin提供的),即使它在磁盘上占用更多空间(如@a_horse提到的那样).27个字节对17个字节numeric- 或30个对20个字节的RAM.看到:

但是,您不希望将排序规则应用于银行帐号.出现这种情况与collat​​able类型,如text或者varchar如果你的数据库集群与非C语言环境中运行.只有数字才能开始无效.但是你仍然会得到更慢的排序和更慢的索引等.值得注意的是,Postgres 9.5或更高版本中的"缩写键"功能目前(包括Postgres 10)已禁用非C语言环境.

把所有东西放在一起,我建议:

CREATE TABLE bank_account (
   bank_account_id serial  PRIMARY KEY
-- bank_account_id integer PRIMARY KEY GENERATED ALWAYS AS IDENTITY  -- in Postgres 10+
 , number_account  text COLLATE "C" NOT NULL  -- disable collation rules
 , CONSTRAINT number_account_has_26_digits CHECK (number_account ~ '^\d{26}$')
);
Run Code Online (Sandbox Code Playgroud)

旁白:

  • 整理"C"确实有所作为.在我的测试中,在较大的表上排序非索引的26位数列是约.快3倍. (4认同)
  • 一则轶事强调"银行账号不是一个整数":我的英国经常账号以"0"开头; 因此,我无法设置直接借记给某个慈善机构,因为他们的系统截断了输入然后拒绝了它.即使您当前的格式要求第一个数字在"[1-9]"中,如果格式发生变化,使用数字类型将会引起未来的痛苦. (3认同)