이 질문에 대한 재귀 CTE 솔루션을 논의하는 동안 :
@ypercube 는 놀라운 예외를 우연히 발견하여 유형 수정 자의 처리를 조사했습니다. 우리는 놀라운 행동을 발견했습니다.
1. 유형 캐스트는 일부 상황에서 유형 수정자를 유지합니다.
지시하지 않더라도. 가장 기본적인 예 :
SELECT 'vc8'::varchar(8)::varchar
varchar
적어도 나는 아마 수정자를 기대 하지 않을 것입니다. 그러나 결과는 varchar(8)
(수정 자 포함)입니다. 아래 바이올린의 많은 관련 사례.
2. 일부 상황에서는 배열 연결이 유형 수정자를 잃습니다.
필요하지 않으므로 반대쪽에서 오류가 발생합니다.
SELECT ARRAY['vc8']::varchar(8)[]
, ARRAY['vc8']::varchar(8)[] || 'vc8'::varchar(8)
첫 번째 표현은 varchar(8)[]
예상대로 산출 됩니다.
그러나 두 번째 varchar(8)
는 다른 하나를 연결 한 후 varchar[]
수정 자 없음으로 물을 뿌립니다 . 의 유사한 행동array_append()
, 아래 바이올린의 예.
이 모든 것은 대부분의 상황에서 중요하지 않습니다. Postgres는 데이터를 잃지 않으며 열에 할당되면 값이 올바른 유형으로 강제됩니다. 하나 반대 방향으로 잘못하면 놀라운 예외가 발생합니다.
3. 재귀 CTE는 정확하게 일치하는 데이터 유형을 요구합니다
이 단순화 된 테이블이 주어지면 :
CREATE TABLE a (
vc8 varchar(8) -- with modifier
, vc varchar -- without
);
INSERT INTO a VALUES ('a', 'a'), ('bb', 'bb');
이 rCTE가 작동하는 동안 varchar
열 vc
, 그것은 실패 varchar(8)
열 vc8
:
WITH RECURSIVE cte AS (
(
SELECT ARRAY[vc8] AS arr -- produces varchar(8)[]
FROM a
ORDER BY vc8
LIMIT 1
)
UNION ALL
(
SELECT a.vc8 || c.arr -- produces varchar[] !!
FROM cte c
JOIN a ON a.vc8 > c.arr[1]
ORDER BY vc8
LIMIT 1
)
)
TABLE cte;
오류 : 재귀 쿼리 "cte"열 1에는 비 재귀 용어로 유형 문자 varying (8) []이 있지만 전체적으로 유형 문자 가변 []이 있습니다. 힌트 : 비 재귀 항의 출력을 올바른 유형으로 캐스트하십시오. 위치 : 103
한 가지 빠른 해결 방법은로 캐스팅하는 것 text
입니다.
일반 UNION
쿼리는 동일한 문제를 나타내지 않습니다. 수정자가없는 유형에 대해 해결되므로 모든 정보가 보존됩니다. 그러나 rCTE는 더 까다 롭습니다.
또한 친구 max(vc8)
는 ORDER BY
/ 대신에 일반적으로 사용되는 문제 (또는 수정자가없는 각 기본 유형) LIMIT 1
때문에 문제가 발생하지 않습니다 .max()
text
3 가지를 보여주는 SQL Fiddle :
- 놀라운 결과를 포함한 다양한 표현 예.
varchar
수정 자없이 작동하는 간단한 rCTE .varchar(n)
(수정자를 사용 하여) 예외를 발생시키는 동일한 rCTE .
바이올린은 9.3 페이지입니다. pg 9.4.4에 대해 동일한 결과를 로컬에서 얻습니다.
수정자를 포함하여 정확한 데이터 유형을 표시 할 수 있도록 데모 표현식에서 테이블을 작성했습니다. pgAdmin은이 정보를 즉시 표시하지만 sqlfiddle에서는 사용할 수 없습니다. 놀랍게도 psql
(!) 에서는 사용할 수 없습니다 . 이것은 psql의 단점으로 알려져 있으며 가능한 해결책은 pgsql-hackers에 대해 논의 되었지만 아직 구현되지 않았습니다. 이것이 문제가 아직 감지되어 해결되지 않은 이유 중 하나 일 수 있습니다.
SQL 레벨 pg_typeof()
에서 유형을 얻는 데 사용할 수 있습니다 (그러나 수정자는 아님).
질문
세 가지 문제가 함께 엉망이됩니다.
정확히 말해서, 이슈 1 은 직접적으로 관여하지는 않지만 비 재귀적인 용어로 캐스트로 보이는 것처럼 보이는 명백한 수정을 파괴합니다 ARRAY[vc8]::varchar[]
.
이 중 어느 것이 버그, 결함 또는 그 방식일까요?
뭔가 빠졌거나 버그를 신고해야합니까?
UNION
쿼리 보다 더 엄격해야하는 이유는 없습니다 . 한 번에 세 개의 독립적 인 작은 버그를 발견했을 수 있습니까? (몇 달과 몇 달이 지난 후에도 찾을 수 없었습니다.) 어떤 것들을 버그로 신고해야한다고 생각하십니까?