이것은 흥미로운 발견입니다. 일반적으로 NULL은 다음과 같이 가정 된 데이터 유형이 없습니다.
SELECT pg_typeof(NULL);
pg_typeof
───────────
unknown
VALUES
테이블이 그림에 오면 변경됩니다 .
SELECT pg_typeof(core) FROM (
VALUES (NULL)
) new_values (core);
pg_typeof
───────────
text
이 동작은 https://doxygen.postgresql.org/parse__coerce_8c.html#l01373 의 소스 코드에 설명되어 있습니다 .
/*
* If all the inputs were UNKNOWN type --- ie, unknown-type literals ---
* then resolve as type TEXT. This situation comes up with constructs
* like SELECT (CASE WHEN foo THEN 'bar' ELSE 'baz' END); SELECT 'foo'
* UNION SELECT 'bar'; It might seem desirable to leave the construct's
* output type as UNKNOWN, but that really doesn't work, because we'd
* probably end up needing a runtime coercion from UNKNOWN to something
* else, and we usually won't have it. We need to coerce the unknown
* literals while they are still literals, so a decision has to be made
* now.
*/
(예, PostgreSQL 소스 코드는 우수한 주석 덕분에 이해하기 쉽고 대부분의 위치에 있습니다.)
그러나 탈출구는 다음과 같습니다. VALUES
주어진 테이블의 모든 열과 일치하는 것을 항상 생성한다고 가정 해 봅시다 (다른 경우 아래 두 번째 참고 참조). 귀하의 예에서 작은 트릭이 도움이 될 수 있습니다.
SELECT (x).* FROM (VALUES ((TRUE, NULL, 1234)::fields)) t(x);
active │ core │ id
────────┼──────┼──────
t │ │ 1234
여기서는 테이블 유형으로 캐스트 된 행 표현식 을 사용한 다음 다시 테이블로 추출합니다.
상기 내용을 토대로, 당신은 UPDATE
같이 할 수
UPDATE fields AS t set active = (x).active, core = (x).core
FROM ( VALUES
((true, NULL, 3419)::fields),
((false, NULL, 3420)::fields)
) AS new_values(x) WHERE (x).id = t.id;
노트:
- 사람의 가독성을 높이기 위해 큰 따옴표를 제거했지만 (열) 이름을 생성 할 때 도움을 줄 수 있습니다.
- 열의 하위 집합 만 필요한 경우이 용도로 사용자 지정 유형 을 만들 수 있습니다 . 위에서와 동일한 방식으로 사용하십시오 (테이블에서 자동으로 생성 된 유형을 사용하고 후자의 행 구조를 유지합니다).
dbfiddle에서 작동하는 모든 것을 살펴보십시오 .
Cannot cast type boolean to bigint in column 1
(첫 번째 필드 진술 사이 ::에서 오류 지점) 생성 합니다.