Skip to main content

Command Palette

Search for a command to run...

How to Generate a Database User Password with Special Characters?

Updated
•View as Markdown
How to Generate a Database User Password with Special Characters?
D
Oracle ACE Pro, founder of Enrol Consulting, and Oracle Database and APEX developer with more than two decades of experience building data-driven business applications. I write about Oracle Database, APEX, cloud and AI-assisted development.

At first glance, this doesn’t seem like a difficult task. Yet, I couldn’t find a simple and reliable solution.

Since I am developing an APEX application to manage multiple databases, I needed a function that could generate a new password for a user and send it to a given email address.

In my case, I am working with OCI Autonomous Transaction Processing (ATP) databases, where users are assigned to the DEFAULT profile:

SELECT profile, resource_name, limit
FROM dba_profiles WHERE profile = 'DEFAULT' AND resource_type = 'PASSWORD';

The password rules are validated by the CLOUD_VERIFY_FUNCTION:

SELECT text
FROM dba_source WHERE name = 'CLOUD_VERIFY_FUNCTION' ORDER BY line;

From the code, we can see that complexity is checked through the call: ORA_COMPLEXITY_CHECK(password, 12, null, 1, 1, 1, null);

This means the password must be at least 12 characters long and contain at least one lowercase letter, one uppercase letter, and one number.
But what about special characters?

The DEFAULT user profile does not enforce them, but for security reasons I wanted to ensure that generated passwords also contain at least one special character.

After checking the ORA_COMPLEXITY_CHECK function itself:

SELECT text
FROM dba_source WHERE name = 'ORA_COMPLEXITY_CHECK' ORDER BY line;

My Password Generator

I created my own password generator function using the DBMS_RANDOM package:

create function f_pwd_gen(p_length number default 20) return varchar2 as
    a number:=0;
    k number;
    i number;
    r varchar2(100); -- result
    v_check varchar2(100);
begin
    loop
      -- The password must begin with a character!
      a:=a+1; -- iteration counter
      r:=upper(dbms_random.string('u',1));
      v_check:='';
      
      for k in 2..least(p_length,100) loop -- max 100 chars
          i:=round(dbms_random.value(0,9));  
          if i between 0 and 3 then -- lower
            r:=r || lower(dbms_random.string('u',1));
            v_check:=v_check || 'L';
          elsif i between 4 and 6 then -- upper
            r:=r || upper(dbms_random.string('u',1));
            v_check:=v_check || 'U';              
          elsif i between 7 and 8 then -- number
            r:=r || lower(round(dbms_random.value(0,9)));
            v_check:=v_check || 'N';              
          else -- special
            r:=r || SUBSTR('#$_', dbms_random.value(1, 3), 1);
            v_check:=v_check || 'S';              
          end if;  
      end loop;  
      
      -- Replace potentially misleading characters
      r:=replace(r,'o','f');  
      r:=replace(r,'0','3');                
      r:=replace(r,'O','G');    
      r:=replace(r,'l','t');    

      exit when a>100 
        or (instr(v_check,'L')>0 and instr(v_check,'U')>0 
        and instr(v_check,'N')>0 and instr(v_check,'S')>0 );
   end loop;   

   return r;
end;

At first, I tried including as many symbols as possible in the “special character” line. However, when setting the new password, I constantly received error messages.


The Real Issue

Passwords are usually set with a command like:

ALTER USER SCOTT IDENTIFIED BY fsd32fasSD_FS;

If you don’t wrap the password in quotes, the SQL parser interprets many special characters incorrectly. That’s why it may look like only #, $, or _ are allowed.

✅ The fix is simple: enclose the password in double quotes. (Of course, I only realized this much later.)

ALTER USER SCOTT IDENTIFIED BY "N3w!Pass@2025";

When quoted, Oracle accepts almost any character (except the double quote " itself and the null character).

⚠️ Be aware that some shells and tools (SQL*Plus, terminals, scripts) interpret certain characters (!, &, \) before they reach the database. In those cases, escape them at the client level or use EXECUTE IMMEDIATE in PL/SQL to set the password.


Conclusion & Best Practices

Even though Oracle’s ORA_COMPLEXITY_CHECK function doesn’t require special characters by default, you can and should include them for stronger security. The key is to quote your password in the ALTER USER statement so all special characters are accepted.

If you’re building workflows in Oracle APEX (or any automation around database password resets), keep in mind:

  • Always quote the password in ALTER USER.

  • Test which characters your client environment accepts without extra escaping.

  • Replace ambiguous characters (O, 0, l) to avoid confusion.

  • Consider sending passwords securely.

  • Require users to change their generated password upon first login.

👉 By quoting the password properly, you can safely generate and use strong passwords containing a full range of special characters.

More from this blog

David Pataki

15 posts

Oracle ACE Pro, founder of Enrol Consulting, and Oracle Database and APEX developer with more than two decades of experience building data-driven business applications. I write about Oracle Database, APEX, cloud and AI-assisted development.