在Amazon Redshift中进行动态合并语句(upsert)

问题描述 投票:0回答:1

[我想与您分享我为Amazon Redshift设法制作的东西,它是SCD(缓慢变化的尺寸)Type 2.的动态合并语句

此语句假定的内容事先存在:

  • 数据库中的两个模式-dbimportsrepo。 dbimports模式用作暂存区域,回购将成为2类SCD维度和事实的目标。
  • repo和dbimports模式中的表具有相同的名称以及来自源数据的相同的列名称。
  • repo模式中的表将具有预设的主键。
  • repo]模式中的表将具有三个附加列-scd_keyis_active插入日期。 scd_key是标识列,如果不执行主键约束,则可以省略。
  • [请注意,我没有添加

    end_date

列,因为我发现在特定项目的情况下该列不可用。此语句的作用:

    使用一个参数(table_name varchar(256))在
  • repo模式中创建存储过程。
动态地从table_name参数获取要合并到的表名,并在回购模式中dbimports表及其镜像表之间的匹配行上对is_active标志列(设置为0)执行UPDATE语句。
  • 动态地定义UPDATE语句的连接条件。
  • 从dbimports进行INSERT * INTO到将is_active标志设置为1且当前日期为(GETDATE())的存储库架构。
  • 我知道,如果您在普通的SQL环境中进行构建,这并不是一项艰巨的任务,但是您可能知道,Redshift的SQL是“高度修改的”。这意味着大多数普通SQL的功能都像变量和触发器一样被剪切掉了,这使这项任务很难搞清楚(至少对我来说是如此)。

    希望这对任何人都有帮助。有一个好的。

    我想与您分享我为Amazon Redshift设法做出的一些事情,它是SCD(缓慢变化的维度)类型2的动态合并语句。该语句假定的内容事先存在:两个...

  • sql amazon-redshift
    1个回答
    0
    投票
    CREATE OR REPLACE PROCEDURE repo.inserter(table_name IN varchar(256)) AS $$ DECLARE temp_table_name varchar := table_name || '_temp'; one_liner varchar := temp_table_name || '_one_liner'; query varchar; query_builder varchar; rec record; BEGIN EXECUTE 'DROP TABLE IF EXISTS ' || temp_table_name; EXECUTE 'DROP TABLE IF EXISTS ' || one_liner; EXECUTE 'CREATE TEMP TABLE ' || temp_table_name || ' (column_name varchar(256),ordinal_position int,is_nullable varchar(3));'; EXECUTE 'INSERT INTO ' || temp_table_name || '(column_name,ordinal_position,is_nullable) SELECT column_name,ordinal_position,is_nullable FROM svv_columns WHERE table_schema = ''repo'' AND table_name = ''' || table_name || ''';'; EXECUTE 'CREATE TEMP TABLE ' || one_liner || ' (columns_string varchar(1024));'; EXECUTE 'INSERT INTO ' || one_liner || ' SELECT LISTAGG(column_name,'','') WITHIN GROUP (order by ordinal_position) FROM ' || temp_table_name || ' where column_name not in ( ''scd_key'',''inserted_date'',''is_active'');'; query := 'SELECT column_name FROM ' || temp_table_name || ' WHERE is_nullable = ''NO'' and column_name not in(''scd_key'',''inserted_date'') order by ordinal_position;'; query_builder := 'UPDATE repo.' || table_name || ' SET is_active = 0 FROM dbimports.' || table_name || ' b WHERE '; FOR rec IN EXECUTE query LOOP query_builder := query_builder || 'repo.' || table_name || '.' || rec.column_name || ' = b.' || rec.column_name || ' AND '; END LOOP; query_builder := RTRIM(query_builder,'AND ') || ';'; EXECUTE query_builder; query := 'SELECT columns_string FROM ' || one_liner || ';'; FOR rec IN EXECUTE query LOOP query_builder := 'INSERT INTO repo.' || table_name || '(' || rec.columns_string || ',is_active,inserted_date) (SELECT ' || rec.columns_string || ',1 as is_active,GETDATE() as inserted_date FROM dbimports.' || table_name || ');'; END LOOP; EXECUTE query_builder; END; $$ LANGUAGE plpgsql;
    © www.soinside.com 2019 - 2024. All rights reserved.