简体   繁体   中英

Invalid number of arguments error in oracle

Please let me know whether there is anything wrong in the insert statement of the below query. It is giving me 'invalid number of arguments' errors

    create or replace PROCEDURE adm_getMaxTableIdLimited
    (
    v_TableName IN VARCHAR2 DEFAULT NULL ,
    v_TableIDColumnName IN VARCHAR2 DEFAULT NULL ,
    v_MaxTableId OUT NUMBER
    )
    AS
    v_Limit NUMBER(10,0);
    v_SQLStatement VARCHAR2(255);

    BEGIN
   v_Limit:= 99999 ;
   v_MaxTableId:= 0 ;
    EXECUTE IMMEDIATE 'DROP TABLE  TempResult';
   EXECUTE IMMEDIATE 'CREATE GLOBAL TEMPORARY TABLE TempResult
   (
     Result NUMBER(10,0) 
   )';

    v_SQLStatement:= 'Insert INTO TempResult(Result) SELECT max(' || v_TableIDColumnName || ')    
    FROM ' || v_TableName || ' WHERE ' || v_TableIDColumnName || ' <= ' || CAST(v_limit AS 
    VARCHAR2) || ';';
     EXECUTE IMMEDIATE v_SQLStatement;
     EXECUTE IMMEDIATE 'SELECT Result INTO v_MaxTableId FROM TempResult' ;
     IF ( v_MaxTableId = v_Limit ) THEN
        v_MaxTableId := -1 ;
    ELSE
       v_MaxTableId := v_MaxTableId + 1 ;
    END IF;  
    EXECUTE IMMEDIATE ' TRUNCATE TABLE TempResult ';
   END;

You don't need a temporary table at all. And your code can be considerably simplified:

create or replace PROCEDURE adm_getMaxTableIdLimited
(
    v_TableName IN VARCHAR2 DEFAULT NULL,
    v_TableIDColumnName IN VARCHAR2 DEFAULT NULL,
    v_MaxTableId OUT NUMBER
)
AS
    v_Limit NUMBER;

BEGIN
    v_Limit:= 99999 ;

    EXECUTE IMMEDIATE
        'SELECT MAX(' || v_TableIDColumnName || ') FROM '
        || v_TableName || ' WHERE ' || v_TableIDColumnName || ' <= :limit'
    INTO v_MaxTableId
    USING v_Limit;

    IF v_MaxTableId = v_Limit THEN
        v_MaxTableId := -1;
    ELSE
       v_MaxTableId := v_MaxTableId + 1;
    END IF;  
END;

BTW: The current problem in your code is:

EXECUTE IMMEDIATE 'SELECT Result INTO v_MaxTableId FROM TempResult';

The correct line would be:

EXECUTE IMMEDIATE 'SELECT Result FROM TempResult' INTO v_MaxTableId;

First off, it seems very, very unlikely that you want to dynamically drop and create your temporary table. A global temporary table is just that-- global. The table definition is visible to other sessions unlike what you might have grown accustomed to in other databases. Just like permanent tables, you would create the temporary table once when you're installing the application. Dropping and recreating the table won't work correctly in a multi-user environment.

Second, there does not appear to be any reason to use a temporary table here. You can just dynamically generate the SELECT statement and store the result in a local variable.

Third, your INSERT statement should not have a semicolon at the end. That's what is generating the ORA-00911: invalid character error.

Fourth, your dynamic SELECT statement should not have an INTO . That INTO clause needs to be part of the EXECUTE IMMEDIATE , not the SQL statement.

My guess, therefore, is that you want something like

create or replace PROCEDURE adm_getMaxTableIdLimited
(
  v_TableName IN VARCHAR2 DEFAULT NULL ,
  v_TableIDColumnName IN VARCHAR2 DEFAULT NULL ,
  v_MaxTableId OUT NUMBER
)
AS
  v_Limit NUMBER(10,0) := 99999;
  v_SQLStatement VARCHAR2(255);
BEGIN
  v_SQLStatement := 
   'SELECT max(' || v_TableIDColumnName || ')  ' ||
   '  FROM ' || v_TableName || 
   ' WHERE ' || v_TableIDColumnName || ' <= :1';
 EXECUTE IMMEDIATE v_SQLStatement 
    INTO v_MaxTableId
   USING v_Limit;
 IF ( v_MaxTableId = v_Limit ) THEN
    v_MaxTableId := -1 ;
ELSE
   v_MaxTableId := v_MaxTableId + 1 ;
END IF;  

END;

Why are you creating this procedure in the first place, though? It appears to be used to return the next value of a key to insert into the table. If that's what you're doing, you need to reconsider your approach. Generating dynamic SQL that scans the primary key index for the maximum value is much less efficient than using a sequence. It also doesn't work correctly outside of a toy system where you can guarantee that there is only one user. In a real system, multiple sessions will get the same value and try to insert rows with the same key. One of the two will block on the INSERT and eventually get a duplicate key error.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM