为啥这个 PL/SQL 查询不使用 ODP.NET 执行

Posted

技术标签:

【中文标题】为啥这个 PL/SQL 查询不使用 ODP.NET 执行【英文标题】:Why this PL/SQL query doesn't execute using ODP.NET为什么这个 PL/SQL 查询不使用 ODP.NET 执行 【发布时间】:2014-01-21 11:55:54 【问题描述】:

在我的代码中某处生成了一个查询,它将使用以下命令执行:

command.ExecuteNonQuery();

但是对于下面的查询,它会抛出这个异常:

"ORA-01036: illegal variable name/number"

奇怪的是,如果我把这个查询复制到Toad 并设置它的参数值,它执行没有任何问题。

我在command.CommandText 中设置的查询是:

declare vv2 number ; 
BEGIN 
:vv := '';

begin SKY.BUSINESS_OBJECT_PKG.REGISTER(B_TYPE_ID=>:B_a_TYPE_ID, B_ID=>:B_b_ID); end;

INSERT INTO GALAXY.E_CONTENTS(
    CONTENT,
    HASH_CODE,
    FILE_NAME,
    THUMBNAIL,
    ID,
    LOCKED_BY_ID,
    TYPE_ID
)
VALUES 
(
    :P_c_CONTENT,
    :P_d_HASH_CODE,
    :P_e_FILE_NAME,
    :P_f_THUMBNAIL,
    :P_g_ID,
    :P_h_LOCKED_BY_ID,
    :P_i_TYPE_ID
);

begin SKY.BUSINESS_OBJECT_PKG.REGISTER(B_TYPE_ID=>:B_j_TYPE_ID, B_ID=>:B_k_ID); end;

INSERT INTO EVENT_MANAGEMENT.UI_EVENT(
    NOTIFICATION_PORT,
    WORK_ITEM,
    WORK_ITEM_DESC,
    BO_DESC,
    BO_CHANGES_ID,
    SMART_SERVICE_VALUE,
    CONTEXT_ID,
    CONTEXT_TYPE_ID,
    DESCRIPTION,
    EVENT_DATE,
    CREATION_DATE,
    SENDER_ID,
    MACHINE,
    EVENT_CATEGORY,
    REFERENCE_ID,
    EVENT_MODE,
    HANDLED_DATE,
    HISTORY,
    IS_VIEWED,
    IS_ACTIVE,
    ID,
    LOCKED_BY_ID,
    TYPE_ID
)
VALUES 
(
    :P_l_NOTIFICATION_PORT,
    :P_m_WORK_ITEM,
    :P_m_WORK_ITEM_DESC,
    :P_o_BO_DESC,
    :P_p_BO_CHANGES_ID,
    :P_q_SMART_SERVICE_VALUE,
    :P_r_CONTEXT_ID,
    :P_s_CONTEXT_TYPE_ID,
    :P_t_DESCRIPTION,
    :P_u_EVENT_DATE,
    :P_v_CREATION_DATE,
    :P_w_SENDER_ID,
    :P_x_MACHINE,
    :P_y_EVENT_CATEGORY,
    :P_z_REFERENCE_ID,
    :P_aa_EVENT_MODE,
    :P_ab_HANDLED_DATE,
    :P_ac_HISTORY,
    :P_ad_IS_VIEWED,
    :P_ae_IS_ACTIVE,
    :P_af_ID,
    :P_ag_LOCKED_BY_ID,
    :P_ah_TYPE_ID
);

begin SKY.BUSINESS_OBJECT_PKG.REGISTER(B_TYPE_ID=>:B_ai_TYPE_ID, B_ID=>:B_aj_ID); end;

INSERT INTO ACCOUNTING.TRANSACTIONS(
    TITLE,
    LAST_CHANGE_ID,
    EFFECTIVE_DATE,
    CREATE_DATE,
    BO_REFRENCE_ID,
    CREATOR_ID,
    COMPANY_ID,
    VOUCHER_ID,
    TRANSACTION_TYPE_VALUE,
    FISCAL_YEAR_ID,
    TRANSACTION_STATE_VALUE,
    FYTB_ID,
    REVISORY_TRANSACTION_ID,
    BO_TYPE_VALUE,
    TRANSACTION_NUMBER,
    ID,
    LOCKED_BY_ID,
    TYPE_ID
)
VALUES 
(
    :P_ak_TITLE,
    :P_al_LAST_CHANGE_ID,
    :P_am_EFFECTIVE_DATE,
    :P_an_CREATE_DATE,
    :P_ao_BO_REFRENCE_ID,
    :P_ap_CREATOR_ID,
    :P_aq_COMPANY_ID,
    :P_ar_VOUCHER_ID,
    :P_as_TRANSACTION_TYPE_VALUE,
    :P_at_FISCAL_YEAR_ID,
    :P_au_TRANSACTION_STATE_VALUE,
    :P_av_FYTB_ID,
    :P_aw_REVISORY_TRANSACTION_ID,
    :P_ax_BO_TYPE_VALUE,
    :P_ay_TRANSACTION_NUMBER,
    :P_az_ID,
    :P_ba_LOCKED_BY_ID,
    :P_bb_TYPE_ID
);

END;

仅供参考,我使用的是ODP.NET

为什么这样的查询会抛出这个异常?

更新 1: 在此问题之前,我曾遇到过此类问题,以下提示解决了这些问题。但在这种情况下,这些提示不起作用。

从查询中删除所有 "\n""\r""\t" 字符。 重命名名称超过 31 个字符的所有变量。

【问题讨论】:

尝试删除 DECLARE 语句。 @BobJarvis 为什么!?此查询适用于这种结构,但插入到其他表! 【参考方案1】:

可能是因为ODP.NET在某些情况下不支持'\r'字符...尝试替换

command.ExecuteNonQuery();

通过

command.CommandText = command.CommandText.Replace("\r", string.Empty);
command.ExecuteNonQuery();

【讨论】:

其实我之前测试过。但不幸的是它仍然不起作用。【参考方案2】:

您应该发布其余的 .net 代码,特别是您要添加到命令中的参数。无论如何,我看到了几个潜在的问题:

一个,也许 toad 正在做一些特殊的事情,但是以下在 sql-plus 窗口中无效:

declare vv2 number ; 
BEGIN 
:vv := '';
end;
/

用冒号绑定变量实际上是在sql-plus“var”语句中声明的,而不是在匿名pl-sql块的declare语句中。无论如何,您似乎都没有使用该变量。仅此一项就可能是问题所在,因为它会丢弃需要绑定的参数数量。

二,这可能是典型的参数不匹配问题(再次,需要查看您的 Parameter.Add 调用)。可能是参数个数、参数类型、参数顺序等不匹配,请参考我之前的blog post。

最后,我没有尝试在一个语句中执行两个匿名块。也许一次尝试一个只是为了排除它们?我也有一个in-depth write up of calling sql-plus scripts.

【讨论】:

谢谢。我会检查你有用的建议。如果没有帮助,我会提供有关参数的更多详细信息。

以上是关于为啥这个 PL/SQL 查询不使用 ODP.NET 执行的主要内容,如果未能解决你的问题,请参考以下文章

为啥这个 PL/SQL 过程不起作用?

PL/SQL 异常和错误处理

为啥我在调用 DbDataAdapter.Update 时使用 ODP.NET OracleDataAdapter 而不是使用 System.Data.OracleClient 的适配器得到 Orac

将 ODP.Net 与 NHibernate 与 .net System.decimal 一起使用

在 oracle sql developer 中加入查询快,在 odp.net 中超慢

为啥这个 PL/SQL 不起作用?