【问题标题】:Create insert record dynamically by changing pk of existing record for passed in table通过更改传入表的现有记录的pk来动态创建插入记录
【发布时间】:2020-06-23 16:54:22
【问题描述】:

我想将表名和模式传递给一个过程,并让它为特定表生成插入、更新和删除语句。这是自动化测试解决方案(在开发环境中)的一部分,我需要在其中测试一些变更数据捕获。我想让这个动态,因为它需要在很长一段时间内为许多不同的表完成,我需要通过 ORDS 通过 REST 请求调用它,所以不想让每个表都有一个端点。

更新和删除相当容易,但是我在插入语句方面遇到了困难。传入的一些表有数百个具有各种约束、fks 等的列,因此我认为仅通过更改主键来操作现有记录是有意义的。我需要能够将主键修改为我事先知道的新值(例如“-1”)。

理想情况下,我会创建一个动态的rowtypeselect into where rownum = 1,然后循环从all_constraints 找到的主键,并用我的新值更新rowtype.pk,然后再将其插入表中。与this基本相同,但事先不知道表。

例如粗略的想法

PROCEDURE manipulate_records(p_owner in varchar2, p_table in varchar2)
IS
   cursor c_pk is
      select column_name
        from all_cons_columns
       where owner = p_owner
         and constraint_name in (select constraint_name
                                   from all_constraints
                                  where table_name = p_table
                                    and constraint_type = 'P');

   l_row  tbl_passed_in%ROWTYPE --(I know this isn't possible but ideally)

BEGIN
   -- dynamic sql or refcursor to collect a record
   select * into tbl_passed_in from tablename where rownum = 1;

   -- now loop through pks and reassign their values to my known value
   for i in c_pk loop
   ...if matches then reassign;
   ...
   end loop;

   -- now insert the record into the table passed in
END manipulate_records;

我四处搜索,但没有找到任何适合这种确切用例的示例,其中需要修改未知列并将其插入表中。

【问题讨论】:

  • 你考虑过dynamic SQL 吗?
  • 是的,但我不确定在这种情况下这对我有什么帮助。你特别想什么?
  • 您使用的是什么版本的 Oracle? (如果 18c+,多态表函数可能会有所帮助。)由于您正在遍历主键列,我假设这意味着您有自然键,其中每列也可以是外键。在这种情况下,-1 在这些列中不起作用。
  • 19c。昨天我在玩多态函数试图获得一个描述表类型,但并没有给我我想要的东西。我再看看。关于。自然键,我认为这不会是我们正在查看的数据集的问题,但绝对需要注意,谢谢。

标签: oracle plsql


【解决方案1】:

根据您的过程的复杂程度,您可以将其作为模板存储在 CLOB 中。然后拉进去,替换table和owner,然后编译。

    DECLARE
    prc_Template        VARCHAR2(4000);
    vc_Owner            VARCHAR2(0008);
    vc_Table            VARCHAR2(0008);
BEGIN
    vc_Table := 'DUAL';
    vc_Owner := 'SYS';
    
    -- Pull code into prc_Template from CLOB, but this demonstrates the concept
    prc_Template := 'CREATE OR REPLACE PROCEDURE xyz AS r_Dual    <Owner>.<Table>%ROWTYPE; BEGIN NULL; END;';
    prc_Template := REPLACE(prc_Template,'<Owner>',vc_Owner);
    prc_Template := REPLACE(prc_Template,'<Table>',vc_Table);
    -- Create the procedure
    EXECUTE IMMEDIATE prc_Template;
END;

那么你就有了合适的 ROWTYPE 可用:

CREATE OR REPLACE PROCEDURE xyz AS r_Dual SYS.DUAL%ROWTYPE; BEGIN NULL; END;

但是你不能创建过程并在同一个代码块中运行它。

【讨论】:

  • 感谢您的建议。由于我调用过程的方式,它不适用于我的用例,但它可能会帮助其他人。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-20
  • 2021-09-25
  • 1970-01-01
  • 2021-08-13
  • 1970-01-01
相关资源
最近更新 更多