ORA-01036: PL/SQL 脚本上的变量名称/编号非法

发布于 2024-10-22 05:56:55 字数 1050 浏览 1 评论 0原文

我对 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() 对其进行参数化

I'm fairly new to the PL/SQL game and I'm attempting to come up with a short script to create logins and grant read-only/read-write privs (making the necessary grants as necessary). However, I am encountering variable scoping issues with it. Can someone please help what I might be doing wrong?

Snipped is as follows:

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;

I'm doing the variable assignments using ODP.NET and parameterizing them using the OracleCommand.Parameters.Add()

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

灼痛 2024-10-29 05:56:55

所有 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;

All the DDL statements (GRANT, REVOKE, CREATE and ALTER) need to be in an EXECUTE IMMEDIATE such as

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

and

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

Actually, I'd simplify it a bit and put all the external variables in one place at the start.

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文