Postgresql - NULL 的解释类型是错误的

Sam*_*uel 4 postgresql postgresql-9.2

我有以下 CTE 表达式的问题,因为prev_countinnew_values被解释为text,但我正在更新的列counts是 type integer。我在标记线上收到此错误:

ERROR:  column "prev_count" is of type integer but expression is of type text
LINE 12:     prev_count = new_values.prev_count
Run Code Online (Sandbox Code Playgroud)

这是查询:

WITH  
    new_values (word,count,txid,prev_count) AS (
        VALUES ('cat',1,5,NULL)),
    updated AS (
        UPDATE 
            counts t 
        SET 
            count = new_values.count, 
            txid = new_values.txid, 
            prev_count = new_values.prev_count -- ERROR HERE
        FROM 
            new_values 
        WHERE (
            t.word = new_values.word
        ) 
    RETURNING t.*) 
INSERT INTO counts(
    word,count,txid,prev_count
) SELECT 
    word,count,txid,prev_count FROM new_values 
WHERE NOT EXISTS (
    SELECT 1 FROM updated WHERE (updated.word = new_values.word))
Run Code Online (Sandbox Code Playgroud)

我的问题是,修复错误的优雅方法是什么?我宁愿指定prev_countin的类型new_values而不是添加显式强制转换,但我在文档中没有看到类似的内容。

Chr*_*ers 5

在这里添加这个作为明确的答案以及详细的解释。

修复方法是:

WITH  
    new_values (word,count,txid,prev_count) AS (
        VALUES ('cat',1,5,NULL::text)),
Run Code Online (Sandbox Code Playgroud)

正如评论中建议的 a_horse_with_no_name 。

为什么这是必要的?因为行规范来自 VALUES 部分,而 NULL 是未知的。在这种情况下,PostgreSQL 有助于转换为文本。但这不是你想要的,所以你必须给 NULL 一个类型。

这也经常出现在其他情况下,例如UNION列列表中第一个段中的 NULL 可以被赋予隐式类型的语句,该类型与另一个段中的列类型发生冲突。所以这是一个值得了解的棘手角落。