【发布时间】: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