Sql 我有一个删除-插入CTE,它以一种奇怪的方式失败

Sql 我有一个删除-插入CTE,它以一种奇怪的方式失败,sql,postgresql,casting,common-table-expression,Sql,Postgresql,Casting,Common Table Expression,这是it成功的一个例子: with x as ( delete from common.companies where id = '0f8ed160-370a-47bb-b4bf-2dcf79100a52' returning row_to_json(companies) as old_data, null as new_data, 'common.companies' as model, id, 'delete' as action) insert into edit_hi

这是it成功的一个例子:

with x as ( 
    delete from common.companies where id = '0f8ed160-370a-47bb-b4bf-2dcf79100a52' 
    returning row_to_json(companies) as old_data, null as new_data, 'common.companies' as model, id, 'delete' as action)
insert into edit_history (old_data, new_data, model, model_pk, action, submitter)
select old_data, null, model, id, action, '0b392013-f680-45a6-b19a-34f3d42d0120' from x;

INSERT 0 1
请注意,insert select中的第二列显式为null

以下是一个失败的示例:

with x as (
    delete from common.companies where id = '160d7ef2-807c-4fe0-bfed-7d282c031610' 
    returning row_to_json(companies) as old_data, null as new_data, 'common.companies' as model, id, 'delete' as action)
insert into edit_history (old_data, new_data, model, model_pk, action, submitter)                                                                   
select old_data, new_data, model, id, action, '0b392013-f680-45a6-b19a-34f3d42d0120' from x;

ERROR:  failed to find conversion function from unknown to json
请注意,在本例中,我得到的是
new_data
,而不是第二列中的显式null,它从delete语句返回为null


如果两个值都为null,为什么第二个示例会用这个错误来打击我?我已经仔细考虑了这两个问题,这是唯一的功能区别。

技巧似乎是将null转换为列类型应该是什么(在我的例子中是json):


这需要在returning子句中完成,因为这将创建一个temp/pseudo表,该表(没有强制转换)由谁知道如何定义。。。Postgres无法从该值推断类型。因此,当您尝试将该值插入其他类型时,会出现转换错误。

在第一个示例中,您为
insert
语句提供了一个但未键入的NULL

在第二个示例中,您在前面一步(在CTE中)提供了NULL,必须键入表达式,并将其指定为类型
unknown
。对于其他(如数值常量:
123
),Postgres可以派生出更合适的默认数据类型,但NULL(或字符串文本
'foo'
)可以是任何类型。而且在
unknown
json
之间没有定义类型转换

在CTE中将NULL强制转换为正确的数据类型以避免问题(正如您现在发现的那样)。
或者使用
text
作为铸造链中的垫脚石,如果为时已晚。所有内容都可以在
文本中进行转换

您可以将演示简化为以下内容:

作品:

SELECT NULL::json;
失败:

SELECT new_data::json
FROM  (SELECT NULL AS new_data) t;
再次工作:

SELECT new_data
FROM  (SELECT NULL::json AS new_data) t;
或:

SELECT new_data
FROM  (SELECT NULL::json AS new_data) t;
SELECT new_data::text::json
FROM  (SELECT NULL AS new_data) t;