提高插入游标的性能?

Posted

技术标签:

【中文标题】提高插入游标的性能?【英文标题】:Increase performance on insert cursor? 【发布时间】:2012-01-22 17:04:37 【问题描述】:

我想问你如何提高这段代码中插入光标的性能? 我需要使用动态 plsql 来获取数据,但不知道如何以最佳方式改进 INSERT。可能像批量插入? 如果可能,请通过代码示例告诉我。

// 这就是我使用 cur_handle 的方式:

    cur_HANDLE integer;
cur_HANDLE := dbms_sql.open_cursor;
DBMS_SQL.PARSE(cur_HANDLE, W_STMT, DBMS_SQL.NATIVE);
DBMS_SQL.DESCRIBE_COLUMNS2(cur_HANDLE, W_NO_OF_COLS, W_DESC_TAB);

LOOP
-- Fetch a row   
IF DBMS_SQL.FETCH_ROWS(cur_HANDLE) > 0 THEN
    DBMS_SQL.column_value(cur_HANDLE, 9, cont_ID); 
    DBMS_SQL.COLUMN_VALUE(cur_HANDLE, 3, proj_NR);    
ELSE
    EXIT;
END IF;

  Insert into w_Contracts values(counter, cont_ID, proj_NR);
counter := counter + 1;
END LOOP;

【问题讨论】:

为什么您认为必须为游标使用动态 SQL?如果您希望我们帮助您,您需要解释您的用例。 因为 select 语句是从网站组装而成的,例如,如果用户选择包含更详细的搜索,则 select 语句会更改,最终结果看起来会有所不同。整个应用程序是一个基于动态 plsql 代码构建的网站。 【参考方案1】:

您应该尽可能在集合中执行数据库操作,而不是逐行插入。你没有告诉我们CUR_HANDLE 是什么,所以我不能真正重写它,但你可能应该这样做:

INSERT INTO w_contracts
SELECT ROWNUM, cont_id, proj_nr
  FROM ( ... some table or joined tables or whatever... )

虽然如果你的第一个值有一个主键,那么从序列中分配它可能会更好。

【讨论】:

抱歉信息缺失。这是我使用 cur_handle 的方法: cur_HANDLE integer; -- 声明 cur_HANDLE := dbms_sql.open_cursor; DBMS_SQL.PARSE(cur_HANDLE, W_STMT, DBMS_SQL.NATIVE); DBMS_SQL.DESCRIBE_COLUMNS2(cur_HANDLE, W_NO_OF_COLS, W_DESC_TAB); 但是光标的选择语句是什么? W_STMT 是语句变量的名称。 很明显,但是声明是什么? 我没有表或连接表,我只想使用循环中的 cont_ID 和 proj_NR 并通过批量插入将其插入!【参考方案2】:

解决方案 1)您可以在循环内填充一个 PL/SQL 数组,然后在循环之后使用以下步骤一步插入整个数组:

FORALL i in contracts_tab.first .. contracts_tab.last
  INSERT INTO w_contracts VALUES contracts_tab(i);

解决方案 2)如果 v_stmt 包含有效的 SQL 语句,您可以使用直接将数据插入表中

EXECUTE IMMEDIATE 'INSERT INTO w_contracts (counter, cont_id, proj_nr) 
    SELECT rownum, 9, 3 FROM ('||v_stmt||')';

【讨论】:

现有循环内部?恐怕它会使整个操作变慢,因为它会为它获取的每一行进行插入!【参考方案3】:

"select 语句是从网站组装的,例如,如果用户选择 包括更详细的搜索,然后更改选择语句并 结果最终看起来不同。整个应用程序是一个网络 网站基于动态 plsql 代码构建。”

这是一个危险的提议,因为它会打开您的数据库以进行 SQL 注入。这是坏人破坏您的参数以扩展他们可以检索的数据或提升权限的场景。至少您需要使用 DBMS_ASSERT 来验证用户输入。 Find out more.

当然,如果您允许用户传递整个 SQL 字符串(您没有提供任何有关构造 W_STMT 的信息),那么所有的赌注都将失败。 DBMS_ASSERT 帮不了你。

无论如何,由于您没有提供我们实际需要的其他信息,请让我为您说明:

SELECT 语句是否总是具有来自相同表名的相同列名,或者用户可以更改这两个? 您会一直对第三列和第九列感兴趣吗? W_STMT 字符串是如何组装的?您对其投影有多少控制权?

【讨论】:

以上是关于提高插入游标的性能?的主要内容,如果未能解决你的问题,请参考以下文章

Solr游标查询提高翻页效率

pgsql游标插入数据失败

ADODB

DB2与oracle游标定义的区别

SQL Server 提高 游标

带有参数化游标的嵌套 for 循环正在插入重复记录