Postgres BIGINT的最大值

时间:2015-03-10 09:50:06

标签: postgresql types biginteger

是否可以在没有硬编码的情况下获得BIGINT类型的最大值?

我知道限制是众所周知的,但我不想对其进行硬编码。

3 个答案:

答案 0 :(得分:8)

您可以使用pg_column_size,它会为您提供bigint的字节大小。使用它你可以得到它的最大和最小尺寸:

select  (2^(8*pg_column_size(1::bigint)-2))::bigint << 1 as min_bigint_value;
select  -(((2^(8*pg_column_size(1::bigint)-2))::bigint << 1)+1) as max_bigint_value;

因此,如果你将依赖这些计算出的值,那么如果将来bigint最大值会以某种方式发生变化(非常非常不可能),你的代码仍会有效。

您可以为方便起见编写函数:

CREATE OR REPLACE FUNCTION "get_max_bigint_value"() RETURNS BIGINT as $$
DECLARE
    max_bigint_value BIGINT;
BEGIN
    SELECT  -(((2^(8*pg_column_size(1::BIGINT)-2))::BIGINT << 1)+1) INTO max_bigint_value;
    RETURN max_bigint_value;
END
$$ LANGUAGE "plpgsql";

CREATE OR REPLACE FUNCTION "get_min_bigint_value"() RETURNS BIGINT as $$
DECLARE
    min_bigint_value BIGINT;
BEGIN
    SELECT  (2^(8*pg_column_size(1::bigint)-2))::bigint << 1 INTO min_bigint_value;
    RETURN min_bigint_value;
END
$$ LANGUAGE "plpgsql";

然后:

SELECT get_min_bigint_value();
SELECT get_max_bigint_value();

答案 1 :(得分:1)

&#34;理想&#34;解决方案是创建一些只暴露相关定义的C函数(如下)。但假设你更喜欢SQL中的东西,我认为你能做的最好的是:

CREATE OR REPLACE FUNCTION bigint_min() RETURNS bigint LANGUAGE sql AS 'SELECT 1::bigint<<63';
CREATE OR REPLACE FUNCTION bigint_max() RETURNS bigint LANGUAGE sql AS 'SELECT ~bigint_min()';
CREATE OR REPLACE FUNCTION int_min() RETURNS int LANGUAGE sql AS 'SELECT 1<<31';
CREATE OR REPLACE FUNCTION int_max() RETURNS int LANGUAGE sql AS 'SELECT ~int_min()';

这些是在C级别定义的内容。 bigint使用PG_INT64 _ *:

#define PG_INT8_MIN     (-0x7F-1)
#define PG_INT8_MAX     (0x7F)
#define PG_UINT8_MAX    (0xFF)
#define PG_INT16_MIN    (-0x7FFF-1)
#define PG_INT16_MAX    (0x7FFF)
#define PG_UINT16_MAX   (0xFFFF)
#define PG_INT32_MIN    (-0x7FFFFFFF-1)
#define PG_INT32_MAX    (0x7FFFFFFF)
#define PG_UINT32_MAX   (0xFFFFFFFFU)
#define PG_INT64_MIN    (-INT64CONST(0x7FFFFFFFFFFFFFFF) - 1)
#define PG_INT64_MAX    INT64CONST(0x7FFFFFFFFFFFFFFF)
#define PG_UINT64_MAX   UINT64CONST(0xFFFFFFFFFFFFFFFF)

答案 2 :(得分:0)

你可以在~100ms内达到它并在代码中使用或保存到临时表 - 这里有一个或多或少的快速获取最大值来提高它的例子:

do
$$
declare
 i bigint =2;
 r record;
begin
  begin
  for r in 2::int..999::int loop
    i=power(2,r);
    raise info '%', i::text;
  end loop;
  exception when others then raise info '%', 'fast roll on (power to 2) ended - switching to slow (multiplying by 2)'||i::text;
  end;
  begin
  for r in 2::int..999::int loop
    i=i*2;
    raise info '%', i::text;
  end loop;
  exception when others then raise info '%', 'max reached:'||(1+(i-1)*2)::text;
  end;
end;
$$
;