Bu soru için özyinelemeli bir CTE çözümü tartışılırken:
@ ypercube , tip değiştiricilerin kullanımını araştırmamıza neden olan şaşırtıcı bir istisna karşısında tökezledi. Şaşırtıcı bir davranış bulduk.
1. Tür döküm, bazı bağlamlarda tür değiştiriciyi korur
Olmaması talimatı verildiğinde bile. En temel örnek:
SELECT 'vc8'::varchar(8)::varchar
Biri bekleyebilir varchar
(değiştirici yok), en azından ben isterim. Ama sonuç varchar(8)
(değiştirici ile). Aşağıdaki kemanda ilgili birçok vaka.
2. Dizi birleştirme, bazı bağlamlarda tür değiştiricisini kaybeder
İhtiyaç yok, bu yüzden karşı tarafta erir:
SELECT ARRAY['vc8']::varchar(8)[]
, ARRAY['vc8']::varchar(8)[] || 'vc8'::varchar(8)
1. ekspresyon varchar(8)[]
beklendiği gibi sonuç verir .
Ancak ikincisi, bir başkasını birleştirdikten sonra varchar(8)
sadece varchar[]
(değiştirici olmadan) sulanır . Benzer davranış array_append()
, aşağıdaki keman örnekleri.
Bütün bunlar çoğu bağlamda önemli değil. Postgres veri kaybetmez ve bir sütuna atandığında, değer yine de doğru türe zorlanır. Bununla birlikte , zıt yönlerde hata, şaşırtıcı bir istisna ile sonuçlanır:
3. Özyinelemeli CTE veri türlerinin tam olarak eşleşmesini ister
Bu basitleştirilmiş tablo göz önüne alındığında:
CREATE TABLE a (
vc8 varchar(8) -- with modifier
, vc varchar -- without
);
INSERT INTO a VALUES ('a', 'a'), ('bb', 'bb');
Bu rCTE işe yararken varchar
sütunda vc
, bu başarısız varchar(8)
sütununda 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;
HATA: özyinelemeli sorgu "cte" sütun 1, özyinelemesiz terimde tip karakteri değişen (8) [] var, ancak genel olarak tür karakter [] genel olarak İpucu: Özyinelemesiz terimin çıktısını doğru türe çevirin. Pozisyon: 103
Hızlı bir çözüm, kullanmaktır text
.
Düz bir UNION
sorgu aynı sorunu göstermez: değiştiricisiz tür için yerleşir ve tüm bilgileri koruyacağı garanti edilir. Ama rCTE daha seçici.
Ayrıca, / max(vc8)
yerine daha yaygın olarak kullanılan sorunlarla karşılaşmazsınız , çünkü arkadaşlar hemen (veya değiştiricisiz ilgili temel tür) için yerleşir .ORDER BY
LIMIT 1
max()
text
3 şey gösteren SQL Fiddle :
- Şaşırtıcı sonuçlar içeren bir dizi örnek ifade.
varchar
(Değiştirici olmadan) ile çalışan basit bir rCTE .- Aynı rCTE
varchar(n)
(değiştirici ile) için bir istisna oluşturur .
Keman pg 9.3 içindir. Aynı sonuçları pg 9.4.4 için yerel olarak alıyorum.
Değiştirici dahil tam veri türünü gösterebilmek için demo ifadelerinden tablolar oluşturdum. PgAdmin bu bilgiyi kutudan çıkarırken, sqlfiddle'da mevcut değildir. Dikkat çekici bir şekilde, psql
(!) 'De de mevcut değildir . Bu psql'de eksiklik olduğu bilinmektedir ve olası bir çözüm daha önce pgsql-hacker'larda tartışılmıştır - ancak henüz uygulanmamıştır. Bu, sorunun henüz tespit edilememesinin ve çözülememesinin nedenlerinden biri olabilir.
SQL düzeyinde, pg_typeof()
türü almak için kullanabilirsiniz (ancak değiştiriciyi değil).
Sorular
3 sayı birlikte ortalığı karıştırıyor.
Kesin olmak gerekirse, sorun 1. doğrudan dahil değildir, ancak görünüşte bariz düzeltmeyi özyinelemesiz terimde bir dökümle mahveder: ARRAY[vc8]::varchar[]
veya benzeri, karışıklığa katkıda bulunur.
Bu öğelerden hangisi bir hata, bir aksaklık ya da nasıl olması gerekiyor?
Bir şey mi kaçırıyorum yoksa bir hatayı rapor etmeli miyiz?
UNION
sorgulardan daha katı (daha az akıllı) olması gerekmiyor . Bulduğumuz olabilir misin üç kerede bağımsız küçük hatalar? (Aylar ve aylar sonra böyle bir buluntu yok.) Bunlardan hangisini böcek olarak dosyalamanız gerektiğini düşünüyorsunuz?