【问题标题】:Oracle Stored Procedure to insert values from query, if values do not exist in target如果目标中不存在值,则 Oracle 存储过程从查询中插入值
【发布时间】:2018-04-06 22:10:39
【问题描述】:

Oracle 存储过程:我想要一个将表名和列名插入另一个表的存储过程(目标:add_definitions)。我希望能够随时运行此过程以获取可能已添加到数据库中的新表/列。此外,我只想添加属于特定所有者(Oracle 术语 - 又名“PUBUSER”)的项目,并尽量避免使用“系统”表。解决方案必须是存储过程。

当前不工作的存储过程

create or replace procedure test_adding as
    sqlcmd varchar2(2000);

begin
    sqlcmd := 'insert into add_definitions (table_name, column_name) ' ||
      'select aa.table_name, aa.column_name ' ||
      'from all_tab_columns aa ' ||
      'where (instr(aa.table_name, ''$'') = 0 and aa.owner = ''PUBUSER'') and ' ||
      '(not exists (select item_id from add_definitions cc where cc.table_name = aa.table_name and cc.column_name = aa.column_name))';
    execute immediate sqlcmd;

end test_adding;

我首先手动填充 add_definitions 表(使用所有正确的值)来检查上述内容。然后我删除了 2 行。然后,当我运行上述代码时,不会添加回这 2 行。我检查了上述 INSERT 的 SELECT 部分,它确实返回了我删除的 2 项(table_name 和 column_name)。

注意:我简化了代码,我需要在插入过程中添加从其他代码 sn-ps 计算的其他值(我计划执行 EXECUTE IMMEDIATE 的“使用”部分...将这些值替换为sql 命令)。但是我无法首先完成这个非常基本的步骤。所以请不要提出“不做”存储过程等的建议。30小时后,我要开枪了。

更新:根据其中一个 cmets,我试图让它在不立即执行的情况下运行 - 只是直接执行了“INSERT INTO ... SELECT ...”它仍然无法恢复删除的值(我使用直接 INSERT 方法多次重新测试了上述步骤)。这非常令人沮丧,因为其他回复之一说这对他们来说很好......??? (我使用的是 Oracle 11g Express Edition - 但我当然希望这不会产生影响)。

【问题讨论】:

  • 我看不到这里需要动态sql。为什么不简单地运行 INSERT INTO SELECT * ?使用动态 sql 会使代码更难调试,因为它会将编译时错误转变为运行时错误。所以,只有在绝对需要时才使用它。
  • 其他需要添加的部分将来自传递到存储过程中的用户提供的数据。所以我最终将不得不投入一些东西来防止 SQL 注入等等。这就是我从动态 SQL 开始的原因。您是否建议动态 SQL 的运行方式与直接 SQL 不同(调试功能除外)?
  • 我只是建议你先运行你的静态 sql(带简单插入),然后尝试将其放入动态块中。是否需要动态 sql 取决于您要使用的参数。如果它们只是您想在插入语句中使用的值,则可能不需要动态 sql。如果它们是动态表名和列名或整个 where 子句,您可能不得不使用它,因为没有其他方法。

标签: oracle stored-procedures insert


【解决方案1】:

您的代码似乎没有问题,除了在插入语句中不包括和不填充item_id 列:

SQL> create table add_definitions (item_id int, table_name varchar2(100), column_name varchar2(100));
SQL> create sequence seq_test start with 1;
SQL> create or replace procedure test_adding as
    sqlcmd varchar2(2000);
begin
    sqlcmd := 'insert into add_definitions (item_id,table_name, column_name) ' ||
      'select seq_test.nextval,aa.table_name, aa.column_name ' ||
      'from all_tab_columns aa ' ||
      'where (instr(aa.table_name, ''$'') = 0 and aa.owner = ''PUBUSER'') and ' ||
      '(not exists (select item_id from add_definitions cc where cc.table_name = aa.table_name and cc.column_name = aa.column_name))';
    --dbms_output.put_line(sqlcmd);
      execute immediate sqlcmd;
end test_adding;

SQL> exec test_adding; -- Assume 100 rows inserted

SQL> select count(1) from add_definitions;

  COUNT(1)
----------
       100

SQL> delete add_definitions where item_id in (99,100);  

SQL> select count(1) from add_definitions;

  COUNT(1)
----------
        98

SQL> exec test_adding; 

SQL> select count(1) from add_definitions;

  COUNT(1)
----------
       100             

SQL> commit;

【讨论】:

    猜你喜欢
    • 2014-09-23
    • 1970-01-01
    • 2023-03-21
    • 2015-06-16
    • 2021-07-10
    • 2022-12-15
    • 2010-12-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多