Redshift

即使值在範圍內,Redshift也會為字元類型字元變化(100)拋出值太長

  • July 19, 2019

我知道此錯誤消息Value too long for character type character varying(100)的含義。所以我經常尋找導致問題的行,並根據要求適當地修復它們。

但是我今天遇到了一個奇怪的問題,即使沒有粗略的行也會發生錯誤。

插入查詢失敗:

INSERT INTO training.archive_temp1 (id, booking, email, pcd_temp, property_id)
WITH x_pcd AS (
   SELECT e.id,
       e.booking,
       e.email,
       CASE
           WHEN LENGTH(e.pch) > 0 THEN (e.pch || ':' || e.pcd)
           ELSE e.pcd
       END AS pcd_temp,
       e.pcd
   FROM public.extracts_temp AS e WHERE e.id BETWEEN 274939128 AND 275083166
)
SELECT x.id,
   x.booking,
   x.email,
   x.pcd_temp,
   COALESCE(c2.property_id, c.property_id)
FROM x_pcd AS x
        LEFT JOIN public.property_codes AS c ON x.pcd_temp = c.code
        LEFT JOIN public.property_codes AS c2 ON x.pcd = c2.code
WHERE COALESCE(c2.property_id,c.property_id, 0) <> 0;

如果我改變x.email它的x.email::varchar(100)工作原理。

這就是問題所在。

SELECT max(length(email)) FROM training.archive_temp1;
-- returns 64

奇怪的。所以我檢查了

SELECT max(length(email)) FROM (
SELECT e.id,
       e.booking,
       e.email,
       CASE
           WHEN LENGTH(e.pch) > 0 THEN (e.pch || ':' || e.pcd)
           ELSE e.pcd
       END AS pcd_temp,
       e.pcd
   FROM public.extracts_temp AS e WHERE e.id BETWEEN 274939128 AND 275083166
)
-- returns 66

如果沒有行超過 100 個字元限制,為什麼會拋出錯誤?這裡發生了什麼?

如果您需要我分享您的任何查詢的結果,請告訴我。由於行在 100000 範圍內,因此無法在此處共享整個數據,如果我可以共享該案例的最小可驗證範例,我就不會問這個問題。

Redshift 可以將多字節字元串儲存到 varchar 欄位中。但是,如果您將欄位定義為varchar(100)它並不意味著 100 個字元。相反,它意味著 100 個字節。因此,如果字元串中的所有字元都是兩個字節字元,則該欄位最多可以儲存 50 個字元。

文件中,

使用 VARCHAR 或 CHARACTER VARYING 列儲存具有固定限制的可變長度字元串。這些字元串沒有用空格填充,因此 VARCHAR(120) 列最多包含 120 個單字節字元、60 個二字節字元、40 個三字節字元或 30 個四字節字元。

問題是LENGTH函式只返回字元數,而不是不包括尾隨空格的字節數。因此,獲取多字節字元的長度僅返回 1。這在此處記錄。

替代的OCTET_LENGTH可以返回字節數而不是字元數。

執行 OCTET_LENGTH 發現了麻煩製造者,現在已修復。

引用自:https://dba.stackexchange.com/questions/243277