是否可以在没有硬编码的情况下获得BIGINT
类型的最大值?
我知道限制是众所周知的,但我不想对其进行硬编码。
答案 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;
$$
;