【问题标题】:POSTGRES INSERT/UPDATE ON CONFLICT using WITH CTEPOSTGRES INSERT/UPDATE ON CONFLICT 使用 WITH CTE
【发布时间】:2020-11-18 20:16:35
【问题描述】:

我有一张如下表。我正在尝试根据 CTE 中的值合并到此表中。但是当我尝试在发生冲突时更新表时,它无法获取 CTE 中的值

CREATE TABLE IF NOT EXISTS master_config_details
(
    master_config_id    INT          NOT NULL,
    account_id          INT          NOT NULL,
    date_value          TIMESTAMP(3) NULL,
    number_value        BIGINT       NULL,
    string_value        VARCHAR(50)  NULL,
    row_status          SMALLINT     NOT NULL,
    created_date        TIMESTAMP(3) NOT NULL,
    modified_date       TIMESTAMP(3) NULL,
    CONSTRAINT pk_master_config_details PRIMARY KEY (master_config_id, account_id, row_status)
);

INSERT INTO master_config_details VALUES (
    1,  11, NULL,100,NULL,          0,  '2020-11-18 12:01:18',  '2020-11-18 12:02:31');

select * from master_config_details;`

现在使用 cte 我想在此表中插入/更新记录。下面是我用来做同样事情的代码。当表中已经存在记录时,我想根据 cte (cte_input_data.data_type_id) 中的 data_type_id 值更新表,但它失败并出现错误。

SQL 错误 [42703]: 错误: 列被排除.data_type_id 不存在

它应该实现的是

  • 如果 cte_input_data.data_type_id = 1 更新 master_config_details 设置 date_value = cte.value

  • 如果 cte_input_data.data_type_id = 2 更新 master_config_details 设置 number_value = cte.value

  • 如果 cte_input_data.data_type_id = 3 更新 master_config_details 设置 string_value = cte.value

下面的代码应该对表 master_config_details.number_value = 22 进行更新,因为该组合 (master_config_id, account_id, row_status) 中已经有一条记录,即 (1,11,1)(运行此命令以查看记录select * from master_config_details;) 但它会抛出错误

SQL 错误 [42703]: 错误: 列被排除.data_type_id 不存在

   WITH cte_input_data AS (
                select
                        1 AS master_config_id 
                        ,11 AS account_id
                        ,2 AS data_type_id 
                        ,'22' AS value
                        ,1 AS row_status)

    INSERT INTO master_config_details  
        SELECT 
                cte.master_config_id
                ,cte.account_id
                ,CASE WHEN cte.data_type_id  = 1 THEN cte.value::timestamp(3) ELSE NULL END AS date_time_value  
                ,CASE WHEN cte.data_type_id  = 2 THEN cte.value::integer ELSE NULL END AS number_value  
                ,CASE WHEN cte.data_type_id  = 3 THEN cte.value ELSE NULL END AS string_value 
                ,1
                ,NOW() AT TIME ZONE 'utc'
                ,NOW() AT TIME ZONE 'utc'
        FROM cte_input_data cte  
        ON CONFLICT (master_config_id,account_id,row_status)
        DO UPDATE SET
            date_value              = CASE WHEN  excluded.data_type_id = 1 THEN excluded.date_time_value::timestamp(3) ELSE NULL END 
            ,number_value               = CASE WHEN  excluded.data_type_id = 2 THEN excluded.number_value::integer ELSE NULL END 
     
            ,string_value           = CASE WHEN  excluded.data_type_id = 3 THEN excluded.string_value ELSE NULL END 
            ,modified_date = NOW() AT TIME ZONE 'utc';



   

【问题讨论】:

    标签: postgresql insert-update postgresql-9.5


    【解决方案1】:

    特殊排除表用于引用最初建议插入的值。 所以你得到这个错误是因为这个列在你的目标表中不存在,所以在特殊的排除表中。它仅存在于您的 cte 中。 作为一种解决方法,您可以在冲突语句中使用嵌套选择从 cte 中选择它。

    【讨论】:

    • 嗨,你能解释一下解决方法吗?请
    • 代替CASE WHEN excluded.data_type_id = 1 THEN ... 尝试写类似CASE WHEN (select data_type_id from cte_input_data) = 1 THEN ...的东西
    猜你喜欢
    • 1970-01-01
    • 2018-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-21
    • 2018-08-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多