programing

PostgreSQL에서 부호 없는 정수를 사용할 수 없는 이유는 무엇입니까?

powerit 2023. 5. 13. 11:02
반응형

PostgreSQL에서 부호 없는 정수를 사용할 수 없는 이유는 무엇입니까?

저는 이 게시물(MySQL에서 tinyint, smallint, mediumint, bigint int의 차이점은 무엇입니까?)을 우연히 발견하고 Postgre를 깨달았습니다.SQL은 부호 없는 정수를 지원하지 않습니다.

누가 왜 그런지 설명하는 것을 도와줄 수 있습니까?

대부분의 경우 MySQL에서 서명되지 않은 정수를 자동 증분 기본 키로 사용합니다.이러한 설계에서 MySQL에서 PostgreSQL로 데이터베이스를 내보낼 때 이 문제를 어떻게 해결할 수 있습니까?

감사해요.

SQL 표준에 포함되어 있지 않기 때문에 일반적으로 SQL 표준을 구현하려는 요구가 낮습니다.

정수 유형이 너무 많으면 유형 분해 시스템이 더 취약해지기 때문에 혼합에 유형을 추가하는 데 약간의 저항이 있습니다.

그렇긴 하지만, 그렇게 하지 못할 이유는 없습니다.그냥 일이 많아요.

postgresql에 서명되지 않은 유형이 없는 이유는 이미 답변되었습니다.그러나 서명되지 않은 유형에는 도메인을 사용하는 것이 좋습니다.

http://www.postgresql.org/docs/9.4/static/sql-createdomain.html

 CREATE DOMAIN name [ AS ] data_type
    [ COLLATE collation ]
    [ DEFAULT expression ]
    [ constraint [ ... ] ]
 where constraint is:
 [ CONSTRAINT constraint_name ]
 { NOT NULL | NULL | CHECK (expression) }

도메인은 유형과 비슷하지만 추가 제약 조건이 있습니다.

구체적인 예로 사용할 수 있습니다.

CREATE DOMAIN uint2 AS int4
   CHECK(VALUE >= 0 AND VALUE < 65536);

다음은 제가 유형을 남용하려고 할 때 psql이 제공하는 것입니다.

DS1=# 선택(346346 :: uint2);

오류: 도메인 uint2의 값이 "uint2_check" 검사 제약 조건을 위반합니다.

CHECK 제약 조건을 사용할 수 있습니다. 예:

CREATE TABLE products (
    id integer,
    name text,
    price numeric CHECK (price > 0)
);

, Postgre.에는 SQL이 있습니다.serial,smallserial그리고.bigserial자동 검색 유형.

도메인에 대한 이야기는 흥미롭지만 그 질문의 유일한 가능한 기원과 관련이 없습니다.부호 없는 int에 대한 욕구는 같은 비트 수로 int의 범위를 두 배로 늘리는 것입니다. 그것은 효율성 논쟁입니다. 음수를 제외하려는 욕구가 아닙니다. 모든 사람이 체크 제약 조건을 추가하는 방법을 알고 있습니다.

그것에 대해 누군가로부터 질문을 받았을 때, Tome Lane은 다음과 같이 말했습니다.

기본적으로 기존의 많은 애플리케이션을 손상시키지 않는 수치 승격 계층 구조에 적합한 방법을 찾지 않는 한 이러한 일이 발생할 가능성은 없습니다.우리는 이것을 한 번 이상 살펴보았지만 POLA를 위반하지 않는 것처럼 보이는 실행 가능한 설계를 생각해내지 못했습니다.

"POLA"란 무엇입니까?구글은 저에게 의미 없는 10가지 결과를 주었습니다.그것이 정치적으로 잘못된 생각인지 아닌지 확신할 수 없고 따라서 검열됩니다.이 검색어는 왜 아무 결과도 얻지 못합니까?신경쓰지 말아요.

서명되지 않은 int를 큰 문제 없이 확장 유형으로 구현할 수 있습니다.C-기능으로 하면 이행강제금이 전혀 없습니다.PgSQL은 문자열을 리터럴로 해석하는 매우 쉬운 방법을 가지고 있기 때문에 리터럴을 다루기 위해 파서를 확장할 필요가 없습니다. 그냥 '4294966272'::uint4를 리터럴로 쓰면 됩니다.출연진들도 큰 문제가 되지 않아야 합니다.범위 예외를 수행할 필요도 없고 '4294966273'::uint4::int의 의미를 -1024로 처리하면 됩니다.아니면 오류를 던질 수도 있습니다.

제가 이걸 원했다면 그렇게 했을 겁니다.하지만 저는 SQL의 반대편에서 Java를 사용하고 있기 때문에 Java에도 부호 없는 정수가 없기 때문에 별로 가치가 없습니다.그래서 저는 아무것도 얻지 못합니다.저는 빅인트 칼럼에서 빅 정수를 언제쯤 받을지 벌써부터 짜증이 납니다.

또 하나, 32비트 또는 64비트 유형을 저장해야 한다면 Postgre를 사용할 수 있습니다.SQL int4 또는 int8은 각각 자연 순서 또는 산술이 안정적으로 작동하지 않는다는 것만 기억합니다.그러나 저장 및 검색은 이에 영향을 받지 않습니다.


다음은 서명되지 않은 간단한 int8을 구현하는 방법입니다.

먼저 사용할 것입니다.

CREATE TYPE name (
    INPUT = uint8_in,
    OUTPUT = uint8_out
    [, RECEIVE = uint8_receive ]
    [, SEND = uint8_send ]
    [, ANALYZE = uint8_analyze ]
    , INTERNALLENGTH = 8
    , PASSEDBYVALUE ]
    , ALIGNMENT = 8
    , STORAGE = plain
    , CATEGORY = N
    , PREFERRED = false
    , DEFAULT = null
)

의 함수 최개 2의함 수소uint8_in그리고.uint8_out먼저 정의해야 합니다.

CREATE FUNCTION uint8_in(cstring)
    RETURNS uint8
    AS 'uint8_funcs'
    LANGUAGE C IMMUTABLE STRICT;

CREATE FUNCTION uint64_out(complex)
    RETURNS cstring
    AS 'uint8_funcs'
    LANGUAGE C IMMUTABLE STRICT;

Cuint8_funcs.c에서 이를 구현해야 합니다.여기서 복잡한 예제를 사용하여 간단히 설명하겠습니다.

PG_FUNCTION_INFO_V1(complex_in);

Datum complex_in(PG_FUNCTION_ARGS) {
    char       *str = PG_GETARG_CSTRING(0);
    uint64_t   result;

    if(sscanf(str, "%llx" , &result) != 1)
        ereport(ERROR,
                (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
                 errmsg("invalid input syntax for uint8: \"%s\"", str)));

    return (Datum)SET_8_BYTES(result);
}

아, 글쎄요, 아니면 그냥 이미 끝났다는 을 알 수 있습니다.

최신 문서에 따르면 서명된 정수는 지원되지만 테이블에는 서명되지 않은 정수가 없습니다.하지만 시리얼 유형은 0에서 시작하는 것이 아니라 1에서 시작하는 것을 제외하면 부호가 없는 것과 약간 비슷합니다.하지만 상한선은 지정된 것과 동일합니다.따라서 이 시스템은 서명되지 않은 지원을 제공하지 않습니다.피터가 지적했듯이 서명되지 않은 버전을 구현할 수 있는 문이 열려 있습니다.코드를 많이 업데이트해야 할 수도 있습니다. 단지 C 프로그래밍 작업 경험에서 얻은 작업이 너무 많습니다.

https://www.postgresql.org/docs/10/datatype-numeric.html

integer     4 bytes     typical choice for integer  -2147483648 to +2147483647
serial      4 bytes     autoincrementing integer    1 to 2147483647

Postgres에는 많은 사람에게 알려지지 않은 부호 없는 정수 유형이 있습니다.

oid 없는 정수으로 구현되어 있습니다.[…]

oid유형 자체에는 비교할 수 없을 정도의 연산이 거의 없습니다.그러나 정수로 캐스팅한 다음 표준 정수 연산자를 사용하여 조작할 수 있습니다. (이 작업을 수행할 경우 서명된 연산자와 서명되지 않은 연산자가 혼동될 수 있습니다.)

그러나 숫자 유형은 아니며, 산술 연산(또는 비트 연산)을 시도하면 실패합니다.또한, 그것은 단지 4바이트입니다.INTEGER), 해당하는 8바이트(BIGINT) 부호 없는 형식입니다.

따라서 직접 사용하는 것은 좋은 생각이 아니며, Postgresql 데이터베이스 설계에서 항상 다음을 사용해야 한다는 다른 모든 답변에 동의합니다.INTEGER또는BIGINT직렬 기본 키의 열 - 음()으로 시작합니다.MINVALUE) 또는 감싸도록 허용(CYCLE전체 도메인을 모두 사용하려는 경우.

그러나 다른 DBMS에서 마이그레이션하는 것과 같이 입력/출력 변환에 매우 유용합니다. 값 삽입2147483648식을 사용하는 동안 정수 열로 "ERROR: integer out of range"가 발생합니다.2147483648::OID잘 작동합니다.
마찬가지로, 정수 열을 텍스트로 선택할 경우mycolumn::TEXT당신은 어느 시점에서 부정적인 값을 얻게 될 것입니다, 하지만.mycolumn::OID::TEXT당신은 항상 자연수를 얻게 될 것입니다.

dbfiddle.uk 의 예를 참조하십시오.

언급URL : https://stackoverflow.com/questions/20810134/why-unsigned-integer-is-not-available-in-postgresql

반응형