当前位置: 首页 > 知识库问答 >
问题:

POSTGRES插入/更新冲突使用与CTE

袁弘化
2023-03-14

我有一张像下面这样的桌子。我试图根据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值更新表,但它失败并出错。

它应该实现的是

>

如果cte_输入_数据。数据类型id=2更新主配置详细信息集合编号cte。价值

如果cte_输入_数据。数据类型id=3更新主配置详细信息设置字符串值cte。价值

下面的代码应该更新表master_config_的详细信息。number_value=22,因为该组合中已经有一条记录(master_config_id、account_id、row_status),即(1,11,1)(运行此命令可查看从master_config_details中选择*的记录;)但它却抛出了一个错误

   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';



   

共有1个答案

孙和安
2023-03-14

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

 类似资料:
  • 我有一个表,它有,,和 在常规插入时自动递增。 的值介于1到10之间,因为有10个问题,但对表来说不是唯一的,并且依赖于列。 用于引用单独表中的报表。 我要实现的是,如果对于特定的没有冲突的,则插入新的记录。如果有冲突,则用新的

  • 我试图将Postgres用作文档存储,但在Postgres解析器似乎不喜欢JSONB操作符的情况下,当我试图有效地向上插入文档时,遇到了一个问题。 我有一张桌子: 我尝试用以下方式插入数据: 我收到这条错误消息: 我试过数据- 我想将标识符列(示例中的a)留在JSON中,而不是使其成为表上的列。 我正在尝试做的事情目前是否得到支持?

  • 我正在写一个数据挖掘程序,可以批量插入用户数据。 当前SQL只是一个普通的批量插入: 如果发生冲突,如何进行更新?我试过: 但它抛出

  • Postgres 10和11的插入说明: 关于冲突[冲突目标]冲突行动 我有一张桌子: 而我想做的 但是我得到一个错误: ON CONFLICT DO UPDATE需要推理规范或约束名称提示:例如,ON CONFLICT(column_name) 为什么我必须提供一个确定的目标?如何提供主键或其他列集?

  • 当您正在向上插入一行时(PostgreSQL) 还有更短的路吗?也就是说:使用所有排除值。 在SQLite中,我曾经做过:

  • 然后使用来获得我想要的内容。这样做的问题是引入了一个与数据本身无关的附加列。