无法解析FORALL中的立即执行中的绑定变量

时间:2020-08-13 14:50:54

标签: oracle plsql

我有一个使用 For循环的PL / SQL过程,并插入了大约5000条记录。

由于 For循环出现性能问题,因此我尝试使用 FORALL

我正在传递表名称,序列ID,列名称列表( I_columnnames 作为逗号分隔的字符串),列数据类型(作为逗号分隔的字符串),多个记录级别数据(作为逗号分隔的字符串)

I_columnnames 将具有多个列名(每次执行的列数各不相同) 我已经按照一个集合 v_tab 中的相应数据类型格式化了每个记录级别的数据(例如,'REC01',1500,100,100,TO_TIMESTAMP('2019-10-10','YYYY- MM-DD HH:MM:SS.FF3')

现在,我必须在该动态表中插入记录级别的数据,为此,我正在使用FORALL语句,其执行立即执行如下:

FORALL i IN v_tab.first .. v_tab.last 
   
EXECUTE IMMEDIATE 'INSERT INTO ' ||I_tablename||'  (BLCK_ID, SEQ_ID, '||I_columnnames|| ')
   values ('''|| I_blckid||''' ,'||I_sequence||' ,'||':1'||')' using v_tab(i);

但是我得到 ORA-值不足错误,因为绑定变量:1被认为是单个字符串(尽管它具有多个逗号分隔的值)

请帮助。

2 个答案:

答案 0 :(得分:1)

:1 是一个包含逗号分隔值的单个字符串,它不会扩展到所有单个元素。

您发现,请串联字符串:

...I_sequence||' ,'|| v_tab(i) ||')';

得到“ PLS-00435:不能在FORALL内部使用没有BULK In-BIND的DML语句。”

您仍然可以连接字符串,但是可以在普通的for循环中而不是在forall中进行连接:

for i in v_tab.first .. v_tab.last loop
  execute immediate 'INSERT INTO ' ||i_tablename||' (BLCK_ID, SEQ_ID, '||i_columnnames|| ')'
      || ' values ('''|| i_blckid||''' ,'||i_sequence||' ,' || v_tab(i) || ')';
end loop;

假定您的CSV字符串中包含适当的引号并进行任何必要的转换,尽管您的示例无效,这似乎是事实-从SQL注入的角度来看这是有风险的。

db<>fiddle

您可以考虑使用dbms_sql而不是execute immediate,但我认为不会带来太大的改进。您可能最好重新考虑构造v_tab的方式和原因。您还可以在现有的PL / SQL块中使用通过操纵字符串构建的动态PL / SQL块;但是只有5000行时,通过简单循环获得的任何速度或效率提高都不值得。但这可以避免SQL注入问题。

答案 1 :(得分:0)

由于绑定变量与动态列,因此extension Double { func toFahrenheit() -> Double { // current temperature is always in Kelvin let temperature = Measurement<UnitTemperature>(value: self, unit: .kelvin) let formatter = MeasurementFormatter() formatter.numberFormatter.maximumFractionDigits = 0 // convert to fahrenheit from Kelvin let convertedTemperature = temperature.converted(to: .fahrenheit) return Double(formatter.string(from: convertedTemperature))! } 中的

EXECUTE IMMEDIATE无法正常工作。

使用FORALL代替常规的INSERT ALL可以很好地工作并改善了性能。

相关问题