基于源表的 SQL INSERT、UPDATE 和 DELETE

标签 sql snowflake-cloud-data-platform scd

我有一个源表,其中包含字段 ID NAMEDESIG

create or replace table emp_source
(
    id number, 
    name string,
    desig string
);

我的目标表有列ID NAME DESIG META_CRT_DT(插入记录的日期)META_UPD_DT(更新记录的日期)META_IUD_FLG(根据执行的插入、删除或更新操作进行更新)CURRENT_FLAG(如果记录被删除,我必须让这个错误)

create or replace table emp_des
(
    id number, 
    name string, 
    desig string,
    META_CRT_DT timestamp_ntz,
    META_UPD_DT timestamp_ntz,
    META_IUD_FLG char,
    current_flag boolean
);

我正在像这样插入新记录

INSERT INTO emp_des (id, name, desig,META_CRT_DT, 
                     meta_upd_dt, meta_iud_flg, current_flag)
SELECT
    id, name, desig, 
    to_date(current_timestamp) as crt,   
    to_date(current_timestamp) as upd, 
    'I' as iud, TRUE as flag 
FROM
    emp_source 
WHERE
    NOT EXISTS (SELECT * FROM emp_des 
                WHERE emp_source.id = emp_des.id);

当源表中的记录更新时,假设名称发生更改,在 EMP_DES 表中我需要更新 DESIGMETA_UPD_DT > 和 META_IUD_FLG 为“U”。

同样,当删除记录时,我需要将 META_UPD_DTMETA_IUD_FLG 更新为“D”。

我是 SQL 新手,因此非常感谢您的帮助。谢谢。

当源表中的记录更新时,假设名称发生更改,在 EMP_DES 表中我需要更新 DESIGMETA_UPD_DT > 和 META_IUD_FLG 为“U”。我尝试过此操作,但它将所有标志更改为“U”。

UPDATE emp_des 
SET desig = s.desig, 
    meta_upd_dt = to_date(current_timestamp), 
    meta_iud_flg = 'U', 
    current_flag = 'TRUE' 
FROM emp_source AS s 
WHERE EXISTS (SELECT * FROM emp_des WHERE id = emp_des.id);

同样,当删除记录时,我需要将 META_UPD_DTMETA_IUD_FLG 更新为“D”。

我是 SQL 新手,所以我想让它尽可能简单。感谢您抽出宝贵时间。

最佳答案

您要求采用非触发方法(有什么方法可以在没有触发器的情况下进行更新吗?比如只有当我运行命令时才会进行更新?)。虽然我非常喜欢基于触发器的方法,但这里有一个示例存储过程:

请注意,与触发器不同,“current_timestamp”的使用不会是在每个单独事件实际发生时,而是在执行存储过程时,而这些根本不是同一件事。

CREATE OR REPLACE PROCEDURE update_emp_des()
AS
BEGIN
    -- Update existing records
    UPDATE emp_des
    SET desig = s.desig,
        meta_upd_dt = CURRENT_TIMESTAMP,
        meta_iud_flg = 'U',
        current_flag = TRUE
    FROM emp_source AS s
    WHERE emp_des.id = s.id AND emp_des.desig != s.desig;

    -- Insert new records
    INSERT INTO emp_des (id, name, desig, META_CRT_DT,
                         meta_upd_dt, meta_iud_flg, current_flag)
    SELECT id, name, desig,
           CURRENT_TIMESTAMP AS crt,
           CURRENT_TIMESTAMP AS upd,
           'I' AS iud, TRUE AS flag
    FROM emp_source
    WHERE NOT EXISTS (SELECT * FROM emp_des WHERE emp_source.id = emp_des.id);

    -- Delete records
    UPDATE emp_des
    SET meta_upd_dt = CURRENT_TIMESTAMP,
        meta_iud_flg = 'D',
        current_flag = FALSE
    WHERE NOT EXISTS (SELECT * FROM emp_source WHERE emp_source.id = emp_des.id);
END;

此存储过程更新 emp_des 表中现有记录的 desig、meta_upd_dt 和 meta_iud_flg 列,其中 desig 列在 emp_source 表中已更改。

它还会将 emp_source 表中的新记录插入到 emp_des 表中,并更新已从 emp_source 表中删除的记录的 meta_upd_dt、meta_iud_flg 和 current_flag 列。

您可以将此存储过程分成 3 个部分并分别运行它们,如果卷很大并且您希望最大程度地减少任何锁定效果,这可能会很有用(存储过程方法的另一个缺点是如何管理锁)。

关于基于源表的 SQL INSERT、UPDATE 和 DELETE,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76186829/

相关文章:

mysql - 使用 session 变量时如何在存储过程中运行此查询

c# - Linq 到 SQL : Updating dataGridView after SubmitChanges isn't working

snowflake-cloud-data-platform - 如何在 Snowflake 中显示所有角色的所有授权?

mysql - 从表的特定字段中删除字符

amazon-web-services - Quicksight - Snowflake 数据源为 "No tables found"

按类型 2 SC 维度月份划分的状态总值 SQL 汇总

MYSQL查询: query displays the second to last line of data

sql - 如何实现这个多表数据库设计/约束,规范化?