ORA-06502:PL / SQL:存储过程和ASP.NET MVC的数值或值错误

时间:2017-07-27 23:11:35

标签: c# asp.net-mvc oracle stored-procedures plsql

我正在尝试从ASP.NET MVC应用程序将数据插入Oracle数据库。我使用存储过程来执行此操作,但我收到此错误:

  

ORA-06502:PL / SQL:数字或值错误:字符串缓冲区也是如此   小ORA-06512:在" C ## AET.KATEGORIJA_PKG",第40行ORA-06502:   PL / SQL:数字或值错误:字符串缓冲区太小   ORA-06512:第1行

程序代码是:

PROCEDURE INS_KATEGORIJA
  (
    P_NAZIV IN KATEGORIJA.NAZIV%TYPE,

    P_KATEGORIJA_ID OUT KATEGORIJA.KATEGORIJA_ID%TYPE,
    P_REZULTAT OUT NUMBER,
    P_PORUKA OUT VARCHAR2
  )
  IS
  BEGIN
    P_REZULTAT := 1;

    SELECT KATEGORIJA_SEQ.NEXTVAL INTO P_KATEGORIJA_ID FROM DUAL;

    INSERT INTO KATEGORIJA
    VALUES (P_KATEGORIJA_ID, P_NAZIV);

    P_REZULTAT := 0;
    P_PORUKA := 'DB: Kategorija uspesno uneta.';

    EXCEPTION
    WHEN OTHERS THEN
      P_REZULTAT := 1;
      P_PORUKA := 'DB: ' ||SQLCODE|| ' - ' ||SQLERRM;
  END INS_KATEGORIJA;

调用它的方法:

List<OracleParameter> izvrsiTransakciju(string nazivProcedure, List<OracleParameter> parametri, OracleTransaction transakcija)
        {
            try
            {
                using (OracleCommand komanda = new OracleCommand(nazivProcedure, konekcija))
                {
                    komanda.Transaction = transakcija;
                    komanda.CommandType = CommandType.StoredProcedure;
                    komanda.BindByName = true;

                    List<OracleParameter> izlazniParametri = new List<OracleParameter>();

                    foreach (OracleParameter p in parametri)
                    {
                        komanda.Parameters.Add(p);

                        if (p.Direction != ParameterDirection.Input) izlazniParametri.Add(p);
                    }

                    komanda.ExecuteNonQuery();

                    return izlazniParametri;
                }
            }
            catch (Exception ex)
            {

                throw new Exception("Greška pri izvršavanju transakcije: " + ex.Message);
            }
        }

与数据库通信的方法是:

    public  List<OracleParameter> PokreniTransakciju(string nazivProcedure, List<OracleParameter> parametri)
            {
                try
                {
                    List<OracleParameter> listaParametara;
                    using (konekcija)
                    {
                        konekcija.Open();

                        using (OracleTransaction transakcija = konekcija.BeginTransaction())
                        {
                            listaParametara = izvrsiTransakciju(nazivProcedure, parametri, transakcija);

                            int rezultat = Convert.ToInt32(listaParametara.FirstOrDefault(x => x.ParameterName == "P_REZULTAT"));
                            if (rezultat != 0)
                                transakcija.Rollback();
                            else
                                transakcija.Commit();

                            return listaParametara;
                        }
                    }
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }

    List<OracleParameter> izvrsiTransakciju(string nazivProcedure, List<OracleParameter> parametri, OracleTransaction transakcija)
            {
                try
                {
                    using (OracleCommand komanda = new OracleCommand(nazivProcedure, konekcija))
                    {
                        komanda.Transaction = transakcija;
                        komanda.CommandType = CommandType.StoredProcedure;
                        komanda.BindByName = true;

                        List<OracleParameter> izlazniParametri = new List<OracleParameter>();

                        foreach (OracleParameter p in parametri)
                        {
                            komanda.Parameters.Add(p);

                            if (p.Direction != ParameterDirection.Input) izlazniParametri.Add(p);
                        }

                        komanda.ExecuteNonQuery();

                        return izlazniParametri;
                    }
                }
                catch (Exception ex)
                {

                    throw new Exception("Greška pri izvršavanju transakcije: " + ex.Message);
                }
            }

public OracleParameter NapraviParametar(string naziv, object vrednost, OracleDbType? tip, ParameterDirection pravac)
        {
            OracleParameter param = new OracleParameter();

            param.ParameterName = naziv;
            param.Direction = pravac;

            if (tip != null)
                param.OracleDbType = (OracleDbType)tip;

            dodajVrednost(param, vrednost);

            return param;
        }

        void dodajVrednost(OracleParameter param, object vrednost)
        {
            if (vrednost == null) return;

            if (vrednost is int)
                param.Value = (int)vrednost;
            else if (vrednost is decimal)
                param.Value = (decimal)vrednost;
            else if (vrednost is string)
                param.Value = (string)vrednost;
            else if (vrednost is DateTime)
                param.Value = (DateTime)vrednost;
        }

有什么想法吗?提前谢谢!

[溶液] 非常感谢来自 LauDec 的帮助,我发现在定义Size参数时必须指定OracleParameter对象的Varchar2属性。补充一点,问题就解决了。

1 个答案:

答案 0 :(得分:1)

显然,它来自于调用P_PORUKA过程时受INS_KATEGORIJA输出参数影响的变量,该过程太小而无法存储您尝试输入的消息(基于评论中的讨论)。

如果您从包裹内部调用了INS_KATEGORIJA,我会明白这一行为:

  DECLARE 
    PORUKA VARCHAR2(10); 
    KATEGORIJA_ID NUMBER; 
    REZULTA NUMBER; 
  BEGIN 
    INS_KATEGORIJA('TEST',KATEGORIJA_ID,REZULTA,PORUKA); 
  END;

这肯定会引起提到的错误消息。但我没想到从外面打电话。 (您的代码是直接调用INS_KATEGORIJA还是调用调用INS_KATEGORIJA的程序包中的其他过程?)

我猜你必须更改PokreniTransakciju调用者中的代码,该代码定义用于调用过程的out变量(及其大小)

编辑:根据OP的评论,原因如下:

  

当定义Varchar2类型的OracleParameter时,   OracleParameter.Size是必需的(如果不是,它似乎设置为0   手动设置)。