Error "PL/SQL: numeric or value error: character string buffer too small" when using optional parameter in stored procedure

StackOverflow https://stackoverflow.com/questions/22834199

Question

I am using the following stored procedure for returning an incremented key value for a specific keyword. It takes an optional parameter of Y or N to determine if the result should be prefixed by another value.

create or replace
PROCEDURE                        "ASGETPRIMARYKEY" 
(
  p_ObjectName IN LASTPRIMARYKEY.OBJECTNAME%type ,
  p_PrimaryKey OUT LASTPRIMARYKEY.NEXTKEY%type,
  useSitePrefix IN NVARCHAR2 Default 'Y'
)
AS
   v_transcount NUMBER := 1;
   v_sys_error NUMBER := 0;
   v_SitePrefix NVARCHAR2(4000);
   v_LastPrimaryKey NUMBER(10,0);
   -- Error Handling Variables
   v_LocalTran NUMBER(1,0);
   v_Error NUMBER(10,0);
BEGIN
   NULL/*TODO:SET XACT_ABORT ON*/;
   NULL/*TODO:SET NOCOUNT ON*/;
   -- STEP 0: Start the transaction
   -- If procedure doesn't need to begin a transaction this can be set to 0
   IF v_transcount > 0 THEN
      v_LocalTran := 0;
   ELSE
      v_LocalTran := 1;
   END IF;

   IF v_LocalTran = 1 THEN
      SET TRANSACTION READ WRITE;
      v_transcount := v_transcount + 1;
   END IF;
   -- STEP 1: Get @SitePrefix
   SELECT settingtext
     INTO v_SitePrefix
     FROM systemsetting
     WHERE settingdescription = 'Site Id Prefix';
   -- Check if there were any errors
   v_Error := v_sys_error;
   IF v_Error != 0 THEN
   BEGIN
      raise_application_error( -20002, 'Error whilst processing GetPrimaryKey.(1a)' || cast(v_error as NVARCHAR2));
      GOTO ErrExit;
   END;
   END IF;
   -- STEP 1b: Check SitePrefix exists
   -- Rollback the transaction if SitePrefix doesn't exist in systemsetting
   IF v_SitePrefix IS NULL THEN
   BEGIN
      raise_application_error( -20002, 'Error whilst processing GetPrimaryKey.(1b)' || cast(v_error as NVARCHAR2));
      GOTO ErrExit;
   END;
   END IF;
   BEGIN
      -- STEP 2: Set NextKey for requested ObjectName
      UPDATE LastPrimaryKey
         SET NextKey = (NextKey + 1)
         WHERE objectname = p_ObjectName;
   EXCEPTION
      WHEN OTHERS THEN
         v_sys_error := SQLCODE;
   END;
   BEGIN
      -- Check if there were any errors
      v_Error := v_sys_error;
   EXCEPTION
      WHEN OTHERS THEN
         v_sys_error := SQLCODE;
   END;
   IF v_Error != 0 THEN
   BEGIN
      raise_application_error( -20002, 'Error whilst processing GetPrimaryKey.(2)' || cast(v_error as NVARCHAR2));
      GOTO ErrExit;
   END;
   END IF;
   -- STEP 3: Set NextKey for for requested ObjectName
   SELECT NextKey - 1
     INTO v_LastPrimaryKey
     FROM LastPrimaryKey
     WHERE objectname = p_ObjectName;
   BEGIN
      -- Check if there were any errors
      v_Error := v_sys_error;
   EXCEPTION
      WHEN OTHERS THEN
         v_sys_error := SQLCODE;
   END;
   IF v_Error != 0 THEN
   BEGIN
      raise_application_error( -20002, 'Error whilst processing GetPrimaryKey.(3)' || cast(v_error as NVARCHAR2));
      GOTO ErrExit;
   END;
   END IF;
   -- STEP 4: Check SitePrefix exists
   -- Rollback the transaction if SitePrefix doesn't exist in systemsetting
   IF v_LastPrimaryKey IS NULL THEN
   BEGIN
      raise_application_error( -20002, 'Error whilst processing GetPrimaryKey.(4)' || cast(v_error as NVARCHAR2));
      GOTO ErrExit;
   END;
   END IF;
   -- STEP 5: Set @p_PrimaryKey by adding prefix
   IF useSitePrefix = 'y' THEN
      p_PrimaryKey := (CAST(v_SitePrefix || CAST(v_LastPrimaryKey AS NVARCHAR2) AS NUMBER));
   ELSE
      p_PrimaryKey := v_lastprimarykey;
   END IF;
   -- Check if there were any errors
   v_Error := v_sys_error;
   IF v_Error != 0 THEN
   BEGIN
      raise_application_error( -20002, 'Error whilst processing GetPrimaryKey.(5)' || cast(v_error as NVARCHAR2));
      GOTO ErrExit;
   END;
   END IF;
   -- STEP 6: If we reach this point, the commands completed successfully
   --         Commit the transaction....
   -- Normal exit
   IF v_LocalTran = 1 THEN
      COMMIT;
      v_transcount := v_transcount - 1;
   END IF;
   -- Error Exit
   <<ErrExit>>
   IF v_LocalTran = 1 THEN
      ROLLBACK;
      v_transcount := v_transcount - 1;
   END IF;
END;

The stored proc is called from a enterpriselibrary using the following vb code:

        Dim sqlCommand As String = "asGetPrimaryKey"
        Dim _db As Database = EnterpriseLibraryContainer.Current.GetInstance(Of Database)(ASDBMSS.clsDBMSS.ConnectionStringName)
        Dim DbCommand As System.Data.Common.DbCommand = _db.GetStoredProcCommand(sqlCommand)
        ' Add primary keys to command wrapper.
        _db.AddInParameter(DbCommand, "p_objectName", DbType.String, ObjectName)

        If pbIgnoreSiteIndex Then
            _db.AddInParameter(DbCommand, "useSitePrefix", DbType.String, "Y")
        Else
            _db.AddInParameter(DbCommand, "useSitePrefix", DbType.String, "N")
        End If

        _db.AddOutParameter(DbCommand, "p_PrimaryKey", DbType.Int32, 8)
        _db.ExecuteNonQuery(DbCommand)

        Dim _result As String = _db.GetParameterValue(DbCommand, "p_PrimaryKey").ToString
        lcl_NextKey = CInt(_result)
        result = 1

The problem arrises when I pass the optional parameter in. If I skip the line with the optional parameter, it works fine. If I use SQL server instead of Oracle, it works fine. If I pass the parameter and use Oracle I get the following error message:

ORA-06502: PL/SQL: numeric or value error: character string buffer too small ORA-06512: at line 1

Any suggestions?

Was it helpful?

Solution 2

I have found the problem!

SQL server does not care in what order the parameters are passed as long as the names match. Oracle it seems, does.

I changed the order in which they are called to this:

        _db.AddInParameter(DbCommand, "p_objectName", DbType.String, ObjectName)
        _db.AddOutParameter(DbCommand, "p_PrimaryKey", DbType.Int32, 8)

        If pbIgnoreSiteIndex Then
            _db.AddInParameter(DbCommand, "useSitePrefix", DbType.String, "Y")
        Else
            _db.AddInParameter(DbCommand, "useSitePrefix", DbType.String, "N")
        End If

        _db.ExecuteNonQuery(DbCommand)

And it now works without error

OTHER TIPS

Change v_LastPrimaryKey from number(10,0) to same as p_PrimaryKey OUT LASTPRIMARYKEY.NEXTKEY%type,

Secondly, you are passing Y or N but inside code comparing y. So flow is always going in "else", where you are not using cast. Hope that helps. Cheers V

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top