【问题标题】:How can i create a dynamic insert into two tables where both tables depend on each other? (oracle sql)如何在两个表相互依赖的两个表中创建动态插入? (甲骨文)
【发布时间】:2014-05-06 01:15:36
【问题描述】:

我必须创建一个可以在两个表中进行两次插入的过程 - 动态。

两个表相互依赖。

我的想法是这样的:

create or replace PROCEDURE INSERT_DYN( 
  par_table_name_a IN STRING, 
  par_keys_a IN ARRAY, 
  par_values_a IN ARRAY,

  par_table_name_b IN STRING, 
  par_keys_b IN ARRAY, 
  par_values_b IN ARRAY)
AS
BEGIN
  INSERT INTO par_table_name_a(par_keys_a) VALUES(par_values_a);
  INSERT INTO par_table_name_b(par_keys_b) VALUES(par_values_b);

 commit;
END INSERT_DYN;

但是没有像“数组”这样的简单类型,我可以在其中放置数字、日期、字符串或键。

我该如何解决这个问题?

【问题讨论】:

  • 您可以将所有内容作为字符串传递,然后您可以查看。 ANYDATA 类型,但是你为什么要这样做,并且丢失你可以从代码编译中获得的任何模式和类型检查?你需要多少对依赖表才能使这个有价值(它们是如何依赖的;一个对另一个有 FK)?

标签: sql oracle stored-procedures insert


【解决方案1】:

检查包 DBMS_SQL,在那里你可以找到所有的程序。一个未经测试的例子是这个:

CREATE OR REPLACE TYPE VARCHAR_TABLE_TYPE AS TABLE OF VARCHAR2(1000);

create or replace PROCEDURE INSERT_DYN( 
  par_table_name_a IN VARCHAR2, 
  par_keys_a IN VARCHAR_TABLE_TYPE, 
  par_values_a IN VARCHAR_TABLE_TYPE) as

cur INTEGER;
res INTEGER;
sqlcmd VARCHAR2(10000);

begin

sqlcmd := 'INSERT INTO '||par_table_name_a||' (';
FOR i in par_keys_a.first..par_keys_a.last loop
   sqlcmd := sqlcmd ||par_keys_a(i)||',';
end loop;
sqlcmd := REGEXP_REPLACE(sqlcmd, ',$', ')');

sqlcmd := sqlcmd||' values ('
FOR i in par_keys_a.first..par_keys_a.last loop
   sqlcmd := sqlcmd ||':b'||i||',';
end loop;
sqlcmd := REGEXP_REPLACE(sqlcmd, ',$', ')');

-- Check if command is properly composed:
DBMS_OUTPUT.PUT_LINE(sqlcmd);

cur := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(cur, sqlcmd, DBMS_SQL.NATIVE);
FOR i in par_keys_a.first..par_keys_a.last loop
    DBMS_SQL.BIND_VARIABLE(cur, ':b'||i, par_values_a(i));
END LOOP;
res := DBMS_SQL.EXECUTE(cur);
DBMS_SQL.CLOSE_CURSOR(cur);

end;

一个数组(在 Oracle 中称为“嵌套表”)只包含相同数据类型的元素,这里我取的是 VARCHAR2。对于 NUMBER 类型的值,使用相同的嵌套表没有问题。对于 DATE 或类似的值,您必须做一些技巧,例如使用一些模式和正则表达式或提供另一个包含每个字段的数据类型的嵌套表。

另一种解决方案是跳过绑定变量并进行硬解析,即替换它

sqlcmd := sqlcmd||' values ('
FOR i in par_keys_a.first..par_keys_a.last loop
   sqlcmd := sqlcmd ||':b'||i||',';
end loop;
sqlcmd := REGEXP_REPLACE(sqlcmd, ',$', ')');
...
END;

这个

sqlcmd := sqlcmd||' values ('
FOR i in par_keys_a.first..par_keys_a.last loop
   sqlcmd := sqlcmd ||''''||par_values_a(i)||''',';
end loop;
sqlcmd := REGEXP_REPLACE(sqlcmd, ',$', ')');
EXECUTE IMMEDIATE sqlcmd;
END;

但是,这为 SQL 注入打开了大门,您仍然会遇到除 VARCHAR 或 NUMBER 之外的其他数据类型的问题

【讨论】:

    猜你喜欢
    • 2012-12-22
    • 1970-01-01
    • 2015-11-22
    • 1970-01-01
    • 2010-11-11
    • 2011-04-26
    • 1970-01-01
    • 1970-01-01
    • 2017-10-14
    相关资源
    最近更新 更多