【问题标题】:How to handle large string coming as an input parameter to the procedure? [closed]如何处理作为过程输入参数的大字符串? [关闭]
【发布时间】:2012-10-30 12:00:43
【问题描述】:

我得到 200 个供应商名称作为存储过程的输入参数。我尝试在 CLOB、VARCHAR2(32767) 中声明。但是当我尝试执行时它不接受。 请任何人帮助我如何处理。

CREATE OR REPLACE PROCEDURE GMMT_PROC.or_rmce_RB_grid_sp (
   p_plant_cd        IN VARCHAR2,
   p_region_cd       IN VARCHAR2,
   p_matrl_nbr       IN OUT VARCHAR2,
   p_supplier_nbr    IN OUT VARCHAR2,
   p_supplier_name   IN OUT CLOB,
   p_mrpcontrollercd IN OUT VARCHAR2,
   p_currency        IN   VARCHAR2,
   oresultset        OUT  sys_refcursor,
   p_err_cd          OUT  NUMBER,
   p_err_msg         OUT  VARCHAR2
)
IS
sqlquery varchar2(10000);
p1 varchar2(10);
p2 varchar2(20);
p3 varchar2(20);
p4 varchar2(20);
v_percent varchar2(10):='%';
V_FROM_CURRENCY VARCHAR2(5);
V_EX_RATE NUMBER;
v_matrl_nbr       VARCHAR2(10000);
v_supplier_nbr    VARCHAR2(10000);
v_supplier_name   CLOB;
v_mrpcontrollercd  VARCHAR2(10000);

BEGIN
p1:='matrl_nbr';
 v_matrl_nbr:=p_matrl_nbr;
 p2:='supplier_nbr';
 v_supplier_nbr :=p_supplier_nbr;
 p3:='supplier_name_txt';
 v_supplier_name :=p_supplier_name;
 p4:='mrp_controller_cd';
 v_mrpcontrollercd:=p_mrpcontrollercd; 
sqlquery:='select wk_nbr, nbr_working_days,'||p1||' as matrl_nbr ,'||p2||' as supplier_nbr,'||p3||' as supplier_name_txt,'||p4||' as mrp_controller_cd,sum(reqmnt_qty)reqmnt_qty , sum(proj_inven_qty)proj_inven_qty, sum(doh) doh,sum(proj_recpt_1) proj_recpt_1, sum(proj_recpt_2) proj_recpt_2, sum(proj_recpt_3) proj_recpt_3, sum(proj_recpt_4) proj_recpt_4,sum( proj_recpt_total_qty) proj_recpt_total_qty,sum(consumption_qty) consumption_qty, sum(consumption_var_qty) consumption_var_qty , sum(final_recpt_qty) final_recpt_qty,sum(recpt_var_qty) recpt_var_qty from GMMT_OWNER.OR_RMCE_GTT_PROJ_RECPT_T ';
sqlquery:=sqlquery||' where ('''||v_matrl_nbr||''' IS NULL) OR matrl_nbr IN (SELECT * FROM TABLE(GMMT_PROC.OR_in_list_RPT5_FN('''||v_matrl_nbr||'''))) OR matrl_nbr like '''|| v_matrl_nbr||v_percent||'''';
sqlquery:=sqlquery||' AND ('''||v_supplier_nbr||''' IS NULL) OR supplier_nbr IN (SELECT * FROM TABLE(GMMT_PROC.OR_in_list_RPT5_FN('''||v_supplier_nbr||'''))) OR supplier_nbr like '''|| v_supplier_nbr||v_percent||'''';
sqlquery:=sqlquery||' AND ('''||v_supplier_name||''' IS NULL) OR supplier_name_txt IN (SELECT * FROM TABLE(GMMT_PROC.OR_in_list_RPT5_FN('''||v_supplier_name||'''))) OR supplier_name_txt like '''|| v_supplier_name||v_percent||'''';
sqlquery:=sqlquery||' AND ('''||v_mrpcontrollercd||''' IS NULL) OR mrp_controller_cd IN (SELECT * FROM TABLE(GMMT_PROC.OR_in_list_RPT5_FN('''||v_mrpcontrollercd||'''))) OR mrp_controller_cd like '''|| v_mrpcontrollercd||v_percent||'''';
sqlquery:=sqlquery||' group by wk_nbr, nbr_working_days,'||p1||','||p2||','||p3||','||p4||' order by wk_nbr';

OPEN oresultset FOR sqlquery;

dbms_output.put_line(sqlquery);
END;                

【问题讨论】:

  • 声明 CLOB 应该可以工作,你遇到了什么错误
  • 我正在尝试打印作为输入参数获取的供应商名称。我正在获取未执行的语句句柄。
  • 邮政编码和错误信息(CLOB版本)
  • @mani.gkn 请更新您的问题
  • -1:请不要在此处编辑您的代码:直接从您的真实环境中复制粘贴即可。

标签: sql oracle plsql plsqldeveloper


【解决方案1】:

您需要了解绑定变量!永远不要,永远连接传递给 SQL 语句的值。

请参阅 http://docs.oracle.com/cd/E14072_01/appdev.112/e10472/dynamic.htm#CHDFCHHJ 了解为什么这是一个坏主意。

现在您遇到的问题是由于插入到 SQL 语句中的值很大,导致 very 长字符串 -- 对于 varchar 来说太长了。

请参阅http://docs.oracle.com/cd/E14072_01/appdev.112/e10472/dynamic.htm#BJEDAHEE,了解如何将绑定变量与 PL/SQL 中的动态 SQL 结合使用。

【讨论】:

  • 嗨,你能告诉我如何解决这个问题。在我增加 Sqlquery 的大小后,它给出 ORA-00604:递归 SQL 级别 1 发生错误 ORA-01003:没有解析语句..I din 知道除此之外的其他选项,所以我使用了此。你能告诉我我能做些什么吗
  • 阅读我回答的最后一个链接!它描述了如何使用绑定变量来解决所有问题。
【解决方案2】:

动态 SQL:不要这样做。

您永远不应该,永远不要将包含值的变量连接到 SQL。 Never, please 它会降低性能,产生难以重现/发现的错误,并且公然对 SQL 注入开放。

可以使用动态 SQL 进行动态分组,因为 P1...P4 不是值,而是列名,因此无法绑定。

ALL other variables should be passed as binds:

您的 OPEN 语句应该是:

OPEN oresultset FOR '
SELECT wk_nbr,
       nbr_working_days,
       ' || dbms_assert.simple_sql_name(p1) || ' AS matrl_nbr,
       ' || dbms_assert.simple_sql_name(p2) || ' AS supplier_nbr,
       ' || dbms_assert.simple_sql_name(p3) || ' AS supplier_name_txt,
       ' || dbms_assert.simple_sql_name(p4) || ' AS mrp_controller_cd,
       sum(reqmnt_qty) reqmnt_qty,
       [...]
  FROM GMMT_OWNER.OR_RMCE_GTT_PROJ_RECPT_T
 WHERE (:VAR1 IS NULL)
    OR matrl_nbr IN (SELECT * FROM TABLE(GMMT_PROC.OR_in_list_RPT5_FN(:VAR1)))
    OR matrl_nbr LIKE :VAR1 || ''%''
    AND (:VAR2 IS NULL)
    OR supplier_nbr IN (SELECT * FROM TABLE(GMMT_PROC.OR_in_list_RPT5_FN(:VAR2)))
    OR supplier_nbr LIKE :VAR2 || ''%''
    [...]
GROUP BY wk_nbr,
         nbr_working_days,
         ' || p1 || ', ' || p2 || ', ' || p3 || ', ' || p4 || '
ORDER BY wk_nbr' 
   USING v_matrl_nbr, v_matrl_nbr, v_matrl_nbr, 
         v_supplier_nbr, v_supplier_nbr, v_supplier_nbr,
         [...];

为防止用户滥用此动态 SQL 片段,您必须确保 p1...p4 已从您定义的列表中预先批准或使用上述DBMS_ASSERT

实际上,如果列表很小,您可以使用简单的静态 SQL:

OPEN cc FOR 
    SELECT wk_nbr,
           nbr_working_days,
           decode(p1, 'column1', column1, 'column2', column2 [...]) AS matrl_nbr,
           [...]
     GROUP BY [...]
              decode(p1, 'column1', column1, 'column2', column2 [...]),
              [...];

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-05
    • 1970-01-01
    • 2018-01-17
    • 1970-01-01
    • 2013-08-30
    • 2012-01-27
    • 1970-01-01
    相关资源
    最近更新 更多