5

smallintPostgresの列に値32767を挿入する際に問題が発生しました。これにより、範囲外のsmallintエラーが発生します。私ができるので、これは奇妙でした:

SELECT 32767::int2;

これは問題なく機能します。少し髪を引っ張った後、私はついにこれを問題の列のインデックスまで追跡しました。まず、スキーマを次に示します(実際にはそうではありませんが、これを単純化して再現ケースにまとめました)。

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

インデックスが2つのsmallintの合計に適用されているにもかかわらず、idx_test_totaltimeの最大値を期待しているようです。int2

これはPostgresのバグですか、それとも単純なものが欠けていますか?この制限を回避する方法はありますか、またはこれらの列int4を作成し、CHECK制約を使用して各値を32767に制限する必要がありますか?Postgres 9.0.0を使用しています(はい、アップグレードする必要があります!)が、9.1.4でこのエラーを示すSQLフィドルを作成しました。

4

2 に答える 2

5

あなたの問題はそれint2 + int2が別のものでint2あるため、あなたのインデックスの式、、が。(cooktime + preptime)のためにオーバーフローすること(32767, 10)です。この問題は、インデックス式に少しキャストすることで回避できます。

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

必要なキャストは1つだけですが、両方を使用しても問題はありません。

于 2012-08-05T05:37:29.093 に答える
3

時間間隔でINTERVALを使用してみませんか?それはあなたの問題に対する完璧な解決策です。

于 2012-08-05T10:27:49.017 に答える