How to Create Form in Oracle Forms (Step-by-Step)

This guide walks you through building a simple data-entry form in Oracle Forms from scratch. We will connect to a database, create a data block, design the layout, add validations and buttons, compile, and run the form. The instructions use plain language and focus on the essentials so you can get productive quickly.

Who is this for?
New Oracle Forms developers, and developers coming from tools like Visual FoxPro or MS Access who want a clear, practical path to their first working form.


Prerequisites

  • Oracle Database access (any recent version with a schema you can use).
  • Oracle Forms Builder installed and configured (commonly Oracle Forms 12c).
  • A database user with privileges to create/modify tables or at least to insert/update into an existing table.
  • A working tnsnames.ora (or an EZCONNECT string) so Forms Builder can log in.

Tip: If you know Visual FoxPro: think of a Data Block as a data source/buffer like a VFP table/cursor bound to controls; a Canvas is like a form surface; Triggers are event handlers.


Create a Simple Table for the Demo (Optional but Recommended)

If you do not already have a table to work with, run this SQL in your schema:

-- Table
CREATE TABLE emp (
  emp_id     NUMBER PRIMARY KEY,
  full_name  VARCHAR2(100) NOT NULL,
  email      VARCHAR2(100),
  hire_date  DATE DEFAULT SYSDATE NOT NULL,
  salary     NUMBER(10,2),
  dept_id    NUMBER
);

-- Sequence for primary key
CREATE SEQUENCE emp_seq START WITH 1 INCREMENT BY 1;

You can add foreign keys (e.g., to a departments table) later. For the first form, the above is enough.


Step 1: Start a New Form Module

  1. Open Oracle Forms Builder.
  2. In the Object Navigator, right-click FormsNew → choose Form.
  3. Save the module immediately as emp_form.fmb in your working folder.

Step 2: Create the Data Block (Data Block Wizard)

  1. In Object Navigator, right-click Data BlocksCreate.
  2. Choose Use the Data Block WizardTable/ViewNext.
  3. Connect to the database when prompted.
  4. Select table EMP → move these columns to Items:
    • EMP_ID (we will set it non-enterable and auto-fill using a sequence)
    • FULL_NAME (required)
    • EMAIL
    • HIRE_DATE (default to SYSDATE)
    • SALARY
    • DEPT_ID
  5. Finish the wizard.

Step 3: Create the Layout (Layout Wizard)

Right after the Data Block Wizard, the Layout Wizard opens:

  1. Select your data block EMP.
  2. Choose Content Canvas (default) and Form layout style for single-record entry.
  3. Select all items.
  4. Arrange items in two columns if you like; accept defaults for prompt alignment and spacing.
  5. Finish. Forms Builder creates a Canvas, a Window, and items with labels.

Step 4: Clean Up Item Properties (Property Palette)

For each item (in the Object Navigator or by clicking the item and pressing F4):

  • EMP_ID
    • Set Item Type: Text Item
    • Set Database Item: Yes
    • Set Enabled: No (user should not type into the PK)
    • Set Insert Allowed / Update Allowed: No
  • FULL_NAME
    • Set Required: Yes
    • Set Maximum Length: 100
  • EMAIL
    • Set Maximum Length: 100
  • HIRE_DATE
    • Set Format Mask: DD-MON-YYYY (or your preferred standard)
  • SALARY
    • Set Hint: “Enter positive amount”
  • DEPT_ID (we will attach a List of Values in a later step)

Opinion: Keep prompts short and consistent (e.g., Full Name, Hire Date) and use Hint for tooltips. It results in a cleaner UI and fewer user errors.


Step 5: Add an Auto-Number for EMP_ID (PRE-INSERT Trigger)

Instead of a database trigger, we will show the Forms way for learning purposes.

  1. In Object Navigator, expand Triggers under the EMP block.
  2. Create a PRE-INSERT trigger: :emp.emp_id := emp_seq.NEXTVAL;
  3. Compile the trigger (menu ProgramCompile). Fix typos if any.

Note: In production, I prefer database-side identity/trigger logic for integrity. For your first form, PRE-INSERT is easier to understand.


Step 6: Add Basic Validations (WHEN-VALIDATE-ITEM)

We will ensure SALARY is not negative:

  1. Under item EMP.SALARY, create trigger WHEN-VALIDATE-ITEM:
IF :emp.salary IS NOT NULL AND :emp.salary < 0 THEN
MESSAGE('Salary cannot be negative.');
RAISE FORM_TRIGGER_FAILURE;
END IF;

Optional: Validate EMAIL with a simple pattern (basic check):

IF :emp.email IS NOT NULL THEN
  IF INSTR(:emp.email, '@') = 0 OR INSTR(:emp.email, '.') = 0 THEN
    MESSAGE('Please enter a valid email address.');
    RAISE FORM_TRIGGER_FAILURE;
  END IF;
END IF;

Step 7: Add a Default on Startup (WHEN-NEW-FORM-INSTANCE)

Set defaults (for example, default HIRE_DATE to today if empty):

Create form-level trigger WHEN-NEW-FORM-INSTANCE:

IF :system.form_status = 'NEW' THEN
IF :emp.hire_date IS NULL THEN
:emp.hire_date := TRUNC(SYSDATE);
END IF;
END IF;

Step 8: Add Buttons (Save, Delete, Clear, Exit)

Create four command buttons on the canvas (use the Button tool). For each:

  • BTN_SAVEWHEN-BUTTON-PRESSED DO_KEY('COMMIT_FORM');
  • BTN_DELETEWHEN-BUTTON-PRESSED DO_KEY('DELETE_RECORD');
  • BTN_CLEARWHEN-BUTTON-PRESSED CLEAR_FORM;
  • BTN_EXITWHEN-BUTTON-PRESSED EXIT_FORM(ASK_COMMIT);

Opinion: Use EXIT_FORM(ASK_COMMIT) to reduce accidental data loss. It is friendlier for new users.


Step 9: Add a List of Values (LOV) for DEPT_ID (Optional but Useful)

If you have a DEPARTMENTS table (e.g., DEPT_ID, DEPT_NAME), provide a picklist.

  1. Record Group: In Object Navigator → Record GroupsCreate → name it RG_DEPT.
    Query: SELECT dept_id, dept_name FROM departments ORDER BY dept_name
  2. LOV: In LOVsCreate → base it on RG_DEPT.
    • Display two columns (ID and Name).
    • Return value: map dept_id to EMP.DEPT_ID.
  3. On item EMP.DEPT_ID, set List of Values to the LOV you created.
  4. Set item property Validate from List = Yes to restrict to valid values.

Step 10: Compile and Run

  • Compile the module: ProgramCompile Module (or Ctrl+T).
  • Run: Click Run Form (or press Ctrl+R).
    Your runtime should open, and the form should be ready for insert/update.

Try it now:

  1. Press Insert (or navigate to a new record).
  2. Enter Full Name, Email, Hire Date, Salary, Dept (via LOV).
  3. Click Save.
  4. Ensure no errors appear, and confirm that EMP_ID was filled.

(Optional) Create a Master-Detail Form

Once you are comfortable, try adding a detail block (e.g., EMP_SKILLS) linked to EMP.EMP_ID.

  • Use Data Block Wizard for the child table.
  • In the wizard, specify the relation columns (master EMP.EMP_ID → detail EMP_SKILLS.EMP_ID).
  • Choose a Tabular layout for the detail block to show multiple rows.

(Optional) Deploy the Form for Others

For a basic first deployment:

  1. Generate FMX: ProgramCompile Module → choose All to create emp_form.fmx.
  2. Place FMX on your server in a directory included in FORMS_PATH.
  3. Ensure your Forms runtime (e.g., WebLogic Managed Server for Forms) is running.
  4. Add/update a runtime configuration (e.g., in formsweb configuration) to point to your module if needed.
  5. Users can launch the form using your standard runtime method (browser-launched runtime or FSAL).

Advice: Keep a consistent build/deploy folder structure. It simplifies maintenance and troubleshooting.


Troubleshooting Checklist

  • Cannot connect to DB
    Verify your tnsnames entry, network reachability, and credentials. Test the connection in SQL*Plus or SQL Developer.
  • FRM/ORA errors during Save
    Read the full error message. Common causes: missing privileges, invalid date/number formats, unhandled nulls on required columns.
  • PK not generated
    Check the PRE-INSERT trigger compiles and that emp_seq exists. Make sure EMP_ID is non-enterable.
  • LOV does not open or is empty
    Ensure the Record Group query works in SQL. Rebuild the LOV if the record group name changed.
  • Item not updating
    Check item properties: Database Item should be Yes and Update Allowed should be Yes where appropriate.

Good Practices from Day One

  • Consistent formats for dates and numbers (set Format Mask).
  • Required property for non-nullable fields to catch issues early.
  • Meaningful prompts and hints (clean labels improve user adoption).
  • Minimal triggers at first; prefer built-ins like COMMIT_FORM, CLEAR_FORM.
  • Keep logic close to data: prefer DB constraints and sequences for integrity; use Forms triggers for UI logic and convenience.

Conclusion

You have built a working Oracle Form that connects to a table, manages primary keys, validates user input, and provides basic navigation and actions. From here, explore master-detail relationships, menus, alerts, parameter forms, and libraries (PLL) to reuse code across modules. Keep your first forms simple and reliable; polish the UI and validations; and move shared rules to the database for robustness.

Vinish Kapoor
Vinish Kapoor

Vinish Kapoor is a seasoned software development professional and a fervent enthusiast of artificial intelligence (AI). His impressive career spans over 25+ years, marked by a relentless pursuit of innovation and excellence in the field of information technology. As an Oracle ACE, Vinish has distinguished himself as a leading expert in Oracle technologies, a title awarded to individuals who have demonstrated their deep commitment, leadership, and expertise in the Oracle community.

guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments