ORA-01036: неправилно име/номер на променлива в PL/SQL скрипт

Аз съм сравнително нов в играта PL/SQL и се опитвам да измисля кратък скрипт за създаване на влизания и предоставяне на права само за четене/четене и запис (правейки необходимите разрешения, ако е необходимо). Въпреки това срещам проблеми с обхвата на променливи с него. Може ли някой да ми помогне какво може да правя погрешно?

Изрязаният е както следва:

DECLARE CNT INTEGER; 

BEGIN

  SELECT COUNT(*) 
    INTO CNT 
    FROM dba_users 
   WHERE username = :ParamUserName

  IF (CNT > 0) THEN
    IF (INSTR(:ParamSelectedRole, 'WRITE') = 0) THEN 
      REVOKE UNLIMITED TABLESPACE FROM :ParamUserName; 
      REVOKE READ_WRITE FROM :ParamUserName; 

      GRANT READ_ONLY TO :ParamUserName; 
    ELSE 
      GRANT UNLIMITED TABLESPACE TO :ParamUserName; 
    END IF; 
  ELSE 
    CREATE USER :ParamUserName DEFAULT TABLESPACE USERS TEMPORARY TABLESPACE TEMP IDENTIFIED BY ":ParamUserPassword" PROFILE ELEV_USER; 
    ALTER USER :ParamUserName PASSWORD EXPIRE;

    GRANT :ParamSelectedRole TO :ParamUserName; 
    GRANT CREATE SESSION TO :ParamUserName; 

    IF (INSTR(:ParamSelectedRole, 'WRITE') > 0 ) THEN
      GRANT UNLIMITED TABLESPACE TO :ParamUserName; 
    END IF; 
  END IF;
END;

Правя присвояването на променливи с помощта на ODP.NET и ги параметризирам с помощта на OracleCommand.Parameters.Add()


person yungun    schedule 17.03.2011    source източник
comment
Публикувайте примера parameters.add - Променливите на Oracle BIND изискват стойност на променлива BIND за всеки екземпляр. BIND променливите не са именувани -- едно и също име не означава, че стойността се използва във всеки екземпляр.   -  person OMG Ponies    schedule 17.03.2011


Отговори (1)


Всички DDL изрази (GRANT, REVOKE, CREATE и ALTER) трябва да бъдат в EXECUTE IMMEDIATE, като например

EXECUTE IMMEDIATE 'REVOKE UNLIMITED TABLESPACE FROM '||:ParamUserName; 

и

EXECUTE IMMEDIATE 'ALTER USER '||:ParamUserName||' PASSWORD EXPIRE';

Всъщност бих го опростил малко и бих поставил всички външни променливи на едно място в началото.

DECLARE 
   V_CNT INTEGER; 
   V_USER VARCHAR2(30);
   V_ROLE VARCHAR2(30);
BEGIN
  --
  V_USER := :ParamUserName;
  V_ROLE := :ParamSelectedRole;
  V_PWD  := :ParamUserPassword;
  --
  SELECT COUNT(*) 
    INTO V_CNT 
    FROM dba_users 
   WHERE username = v_user

  IF (CNT > 0) THEN
    IF (INSTR(v_role, 'WRITE') = 0) THEN 
      EXECUTE IMMEDIATE 'REVOKE UNLIMITED TABLESPACE FROM '||v_user; 
      EXECUTE IMMEDIATE 'REVOKE READ_WRITE FROM '||v_user; 
      EXECUTE IMMEDIATE 'GRANT READ_ONLY TO '||v_user; 
    ELSE 
      EXECUTE IMMEDIATE 'GRANT UNLIMITED TABLESPACE TO '||v_user;
    END IF; 
  ELSE 
    EXECUTE IMMEDIATE 'CREATE USER '||v_user||
                      'DEFAULT TABLESPACE USERS TEMPORARY TABLESPACE TEMP '||
                      'IDENTIFIED BY '||v_pwd||' PROFILE ELEV_USER'; 
    EXECUTE IMMEDIATE 'ALTER USER '||v_user||' PASSWORD EXPIRE;

    EXECUTE IMMEDIATE 'GRANT '||v_role||' TO '||v_user; 
    EXECUTE IMMEDIATE 'GRANT CREATE SESSION TO '||v_user; 

    IF (INSTR(v_role, 'WRITE') > 0 ) THEN
      EXECUTE IMMEDIATE 'GRANT UNLIMITED TABLESPACE TO '||v_user; 
    END IF; 
  END IF;
END;
person Gary Myers    schedule 17.03.2011
comment
Еха. Благодаря. Никога не съм чувал за незабавно изпълнение до днес. Наистина помага! - person yungun; 17.03.2011