PostgreSQL - 在多列上创建索引时,Smallint溢出。这是一个错误吗?

时间:2012-08-05 05:11:18

标签: sql postgresql postgresql-9.0

我在将问题32767插入Postgres的smallint列时遇到问题,这会导致错误 smallint超出范围。这很奇怪,因为我能做到:

SELECT 32767::int2;

哪种方法可以正常使用。在拉了一下头发后,我终于将其追踪到了相关列的索引。首先,这是架构(嗯,不是真的,但我把它简化为一个repro案例):

CREATE TABLE Test
(
  id uuid NOT NULL,
  cooktime smallint,
  preptime smallint,
  CONSTRAINT test_pkey PRIMARY KEY (id )
)
WITH (
  OIDS=FALSE
);

我现在创建以下索引:

CREATE INDEX idx_test_totaltime
  ON Test
  USING btree
  ((cooktime + preptime) );

接下来,我尝试创建以下行:

INSERT INTO Test (CookTime, PrepTime, Id)
VALUES (
  (32767)::int2,
  (10)::int2,
  (E'fd47dc1e-c3c6-42c1-b058-689e926a72a4')::uuid
);

我收到错误:

  

错误:smallint超出范围SQL状态:22003

idx_test_totaltime似乎期望最大值int2,即使索引应用于两个小点的总和。

这是一个Postgres错误,还是我错过了一些简单的东西?有没有办法解决这个限制,或者我需要创建这些列int4并使用CHECK约束将每个值限制为32767?我正在使用Postgres 9.0.0(是的,我需要升级!)但是我创建了一个SQL Fiddle,它在9.1.4上演示了这个错误。

2 个答案:

答案 0 :(得分:4)

您的问题是int2 + int2是另一个int2,因此索引中的表达式(cooktime + preptime)会溢出(32767, 10)。您可以通过在索引表达式中进行一些转换来解决此问题:

CREATE INDEX idx_test_totaltime
  ON Test
  USING btree
  ((cooktime::int4 + preptime::int4));

你只需要其中一个演员,但两者都没有受伤。

答案 1 :(得分:3)

为什么不在一段时间内使用INTERVAL?这是解决问题的完美解决方案。