简介:《Oracle APEX深入浅出》是一份面向 Oracle 应用开发初学者与中级开发者的实战型开发指南,围绕基于 Web 的 Oracle APEX 快速构建企业级应用这一主线,帮助读者从环境搭建一路走到部署与集成,解决入门缺少体系、开发缺少范例的问题。压缩包内只有 1 个 doc 文档,体积约 8.11MB,全部章节集中放在这一份文档中,便于离线阅读和打印查阅。内容分为系统探究、开发实践、调试与集成三大板块:既包含 APEX 简介、环境搭建、账户与权限管理等基础章节,也覆盖页面布局美化、控件使用、Report 报表增删改、文件上传下载、CSS 与 JS 脚本、图表可视化,还涉及 Free Plugins、APEX 部署、调试常用技巧与 API,以及 EBS 中调用 APEX 页面的集成配置,读者可以按目录模块逐项查阅并查找、确认关键环节。目前已有 1593 人学习,适合希望系统梳理 APEX 知识脉络、按章节查漏补缺的开发者参考。
1. Oracle APEX 到底解决什么问题:一个把 PL/SQL 直接变网页的运行时
接到一个需求:在 Oracle EBS 环境里给业务方加一套数据填报和审核页面,字段二十来个,要能导入导出、能按角色控制可见性。按标准表单开发流程排期三个月起步,用 Oracle APEX 搭同样的东西,一个下午就能跑通第一版。这份《Oracle APEX 深入浅出》开发指南讲的就是这条快速开发路径:从 11g 自带版本的卸载、4.2.5 的手工安装、EPG 网关配置,一路写到 Workspace 权限、Grid Layout 布局、Dynamic Action 无刷新、Tabular Form 批量增删改和 EBS 集成。适合已经熟悉 SQL 和 PL/SQL、需要在内网快速交付管理页面的开发者。但别把它当无代码工具,页面定义全存在数据表里,每个 URL 请求都被解析成一次 PL/SQL 调用,结果用htp.p拼成 HTML 吐回浏览器——搞不清这条链路,后面每个坑都得踩一遍。
2. 环境搭建拆解:11g 自带的 3.0 怎么卸、4.2.5 怎么装、EPG 怎么配
整个安装流程里最容易翻车的不是安装本身,而是「旧版本没清干净」。11g 的安装介质自带 APEX 3.0,它的 schema 叫APEX_030200,新装的 4.2.5 叫APEX_040200。两个版本同时挂在同一个数据库上,浏览器访问时请求到底落到哪个引擎、认证走哪套用户表,全看网关和 schema 的绑定关系,这就是后面登录一直失败的根本原因。
2.1 版本共存与表空间规划
动手前先确认三件事:数据库版本、$ORACLE_HOME/apex目录里现存的文件、当前的 APEX 版本号。第三项可以通过查APEX_030200下的版本视图,或者直接看dba_registry里component = 'APEX'那一行的version字段确认。确认是 3.0 之后,用sys as sysdba登录跑卸载脚本,这个脚本会把 3.0 的所有对象、同义词、授权一起删掉,比手工 drop 用户干净得多。
# 以 sysdba 身份进入 SQL*Plus(不要在 APPS 或普通用户下执行) sqlplus / as sysdba # 卸载 3.0:脚本会逐个删除 APEX_030200 下的 PL/SQL 对象 SQL> @?/apex/apxremov.sql # 卸载完再把物理目录清空,避免下一步解压时文件混在一起 SQL> host rm -rf $ORACLE_HOME/apex/*apxremov.sql执行完会输出一长串 drop 语句,中间出现若干ORA-00942或ORA-01432属于正常现象——脚本是「能删就删」的容错写法,只要最后没有ORA-00600之类的内部错误就算通过。真的出问题,看的是脚本末尾的汇总输出,不是中间那些红字。
表空间这一步很多人图省事直接塞进SYSTEM或SYSAUX,短期能跑,后期 APEX 的应用元数据、会话状态、日志全挤在系统表空间里,一次大批量导入就能把SYSAUX撑到告警。单独建一个,初始 100M、每次自动扩 100M、上限 1G,对小团队够用很久:
CREATE TABLESPACE apex01 DATAFILE '/d01/oracle/ORCL/db/apps_st/data/apex01.dbf' SIZE 100M AUTOEXTEND ON NEXT 100M MAXSIZE 1000M; -- 顺手确认一下临时表空间名,安装脚本第二个参数要用 SELECT tablespace_name FROM dba_tablespaces WHERE contents = 'TEMPORARY';路径里的 SID 和挂载点按自己机器改,db/apps_st/data是 EBS 环境的常见布局,独立部署的库一般直接放在oradata下。数据文件路径写错会在安装到一半时报ORA-01119,那时回滚比重来还麻烦,所以建完表空间先SELECT file_name FROM dba_data_files核对一下。
2.2 安装脚本的执行顺序与关键参数
把下载的apex_4.2.5.zip上传到$ORACLE_HOME下解压到apex目录,然后按固定顺序跑四个脚本。顺序错了不会报错,但会留下一个「看起来装好了、实际用不了」的环境,这是最坑的地方。
cd $ORACLE_HOME unzip apex_4.2.5.zip # 解压后应当存在 $ORACLE_HOME/apex/apexins.sql cd apex sqlplus / as sysdba -- 1) 主安装:三个参数分别是 APEX 表空间、临时表空间、图片虚拟目录 SQL> @apexins.sql apex01 TEMP /i/ -- 2) 设置 ADMIN 密码,交互式输入,密码要满足大小写+数字+特殊字符 SQL> @apxchpwd.sql -- 3) 解锁匿名用户和公共用户,否则登录页和静态资源都拿不到 SQL> ALTER USER ANONYMOUS ACCOUNT UNLOCK; SQL> ALTER USER APEX_PUBLIC_USER ACCOUNT UNLOCK; -- 4) 中文语言包,装在安装完成后,不要在安装中途跑 SQL> @load_zh_cn.sqlapexins.sql的第三个参数/i/是图片资源的虚拟路径,页面上所有按钮图标、主题样式都从这里取。写成/i(少个斜杠)或者写成绝对路径,页面能打开但样式全丢,看起来像主题坏了,其实是路径不对。这一步耗时最长,十几分钟很正常,中途不要 Ctrl+C,中断后APEX_040200schema 会处于半成品状态,只能删掉重装。
apxchpwd.sql里设的密码就是后面登录apex_admin用的 ADMIN 密码。11g 默认密码大小写敏感,输入时确认没开 Caps Lock,这条听起来像废话,但确实是「密码明明对却登不上」的高频原因之一。
2.3 嵌入式 PL/SQL 网关的端口与 DAD 配置
APEX 本身不含 HTTP 服务器,它靠数据库内置的 EPG(嵌入式 PL/SQL 网关)或者外部的 mod_plsql、APEX Listener 来接收请求。这套指南走的是 EPG 路线,好处是不用额外装中间件,坏处是端口和 DAD 都得手工配,而且配错之后报的是 404,看不出具体哪里错。
-- 1) 改 XDB 的 HTTP 端口,默认 8080,这里改成 8888 避开冲突 BEGIN DBMS_XDB.SETHTTPPORT(8888); END; / -- 2) 建 DAD,把 /apex/* 这个路径映射到数据库连接 BEGIN DBMS_EPG.CREATE_DAD('apex', '/apex/*'); DBMS_EPG.SET_ATTRIBUTE('apex', 'database-username', 'APEX_PUBLIC_USER'); DBMS_EPG.SET_ATTRIBUTE('apex', 'max-request-body-size', '10485760'); END; / -- 3) 关键一步:允许 APEX 引擎所在的 schema 连接任意主机 BEGIN DBMS_NETWORK_ACL_ADMIN.CREATE_ACL( acl => 'apex_net.xml', description => 'apex outbound', principal => 'APEX_040200', is_grant => TRUE, privilege => 'connect'); DBMS_NETWORK_ACL_ADMIN.ASSIGN_ACL('apex_net.xml', '*'); END; /DAD 名字叫apex,访问地址就是http://服务器:8888/apex/,管理后台是http://服务器:8888/apex/apex_admin。端口改完必须重启监听或者重启数据库让 XDB 重新初始化,只改参数不重启,gethttpport返回新端口但实际连接还是被拒。验证方式很直接:
SELECT DBMS_XDB.GETHTTPPORT FROM dual; -- 应返回 8888 SELECT DBMS_EPG.GET_DAD_ATTRIBUTES('apex') FROM dual;第二句能查出 DAD 的属性列表,说明 DAD 建成功了。如果这里返回空,说明 DAD 压根没建上,问题出在CREATE_DAD那一步,跟后面的登录失败没关系,别在认证配置上浪费时间。
3. 账户体系与工作空间:ADMIN、Workspace、Developer、End User 四层权限
APEX 的权限模型和大多数人熟悉的「数据库用户」是两套东西。数据库用户决定你能不能连库,APEX 用户决定你在浏览器里能看哪个应用、能改哪个页面。两套之间靠 Workspace 绑定 schema 打通,这一层想不明白,很容易出现「在 APEX 里建了用户,登录进去一片空白」。
3.1 四层账户的关系与创建顺序
创建顺序是严格自顶向下的:ADMIN 是实例级超级管理员,只能有一个,负责创建和删除 Workspace;Workspace 是一个隔离的开发空间,创建时必须指定一个数据库 schema,这个 schema 决定了工作空间里所有 SQL 的权限边界;Workspace 内部再分三种角色——Workspace 管理员负责加人、分配应用,Developer 负责建页面写逻辑,End User 只能访问发布出来的应用。
-- 用 ADMIN 登录后,可以在 SQL 命令窗口确认工作空间和用户 SELECT workspace, apex_user, is_admin, is_application_developer FROM apex_workspace_apex_users WHERE workspace = 'DEMO_WS';这张视图直接反映「谁属于哪个工作空间、是什么角色」。当有人反馈「我能登录但看不到应用」,先查这里:如果is_application_developer是N,那就是角色给错了,不是应用发布的问题。
建 Workspace 的时候会要求填 schema 名,这个字段后面不能随便改。给 Workspace 起名和给 schema 起名是两件事,很多人图省事两边用同一个名字,后期把 Workspace 迁到另一个 schema 上时就得重建整个工作空间,应用得重新导一遍。我的习惯是 Workspace 名带业务含义(比如DEMO_WS),schema 用独立的名字,两者解耦。
3.2 把 Workspace 绑到 EBS 的 APPS Schema
和 EBS 集成时,最省事的做法是把 Workspace 直接绑到APPSschema 上——所有 EBS 的同义词、视图、API 立刻可见,写 SQL 时不用加 schema 前缀。代价是这个工作空间里的任何一句 SQL 都跑在 APPS 权限下,一张几百行的 Tabular Form 提交,一个DELETE写错条件就能清掉一片业务数据。
比较稳的分层方式是:给 APEX 单独建一个 schema,通过同义词和授权把需要的 EBS 视图暴露过去,只对确实要写库的场景开放包执行权限。
-- 在 APPS 下,只把需要的只读视图和写接口暴露给 APEX 的 schema CREATE OR REPLACE SYNONYM demo_emp_v FOR apps.demo_emp_v; CREATE OR REPLACE SYNONYM demo_save_pkg FOR apps.demo_save_pkg; GRANT SELECT ON apps.demo_emp_v TO demo_schema; GRANT EXECUTE ON apps.demo_save_pkg TO demo_schema;这么做的直接好处是:APEX 页面里只能SELECT视图、只能调包,写不出裸UPDATE。业务规则集中在demo_save_pkg里,改逻辑不用动页面,回归测试也只测包。代价是每加一张表都要多一步授权,前期慢一点,后面接手的开发者不会因为「不知道这个视图背后是什么」而误操作。
3.3 认证方案的选择:APEX Accounts 与 HTTP Header Variable
创建应用时会让选认证方式,APEX 4.2 自带七种。内网自用的小工具选 Application Express Accounts 就行,用户密码存在 APEX 自己的用户表里,跟数据库账号无关,最简单。要和 EBS 打通单点登录,就得用 HTTP Header Variable——EBS 在前面挡一层,把已登录用户的标识塞进 HTTP 头,APEX 从头的值里认人,不再弹自己的登录框。
无论选哪种,最终都落到一个「认证函数」上,签名固定,返回布尔值:
CREATE OR REPLACE FUNCTION demo_auth ( p_username IN VARCHAR2, p_password IN VARCHAR2 ) RETURN BOOLEAN IS l_cnt NUMBER; BEGIN -- 只校验账号是否有效,密码交给上层的统一认证 SELECT COUNT(*) INTO l_cnt FROM demo_user_t WHERE login_name = UPPER(p_username) AND status = 'A'; IF l_cnt = 1 THEN RETURN TRUE; ELSE RETURN FALSE; END IF; EXCEPTION WHEN OTHERS THEN RETURN FALSE; -- 任何异常都按认证失败处理,不要把错误信息暴露到页面 END;p_username是登录框里输入的值,走 Header Variable 时它来自请求头的值。函数里不要直接拼 SQL,用绑定变量或者UPPER()统一大小写,否则用户输入小写就登不进去,而且报的还是「用户名或密码错误」,排查方向直接跑偏。异常块统一返回FALSE是有意为之:让异常冒出去,页面上会显示ORA-06502之类的原始错误,既不安全也不好看。
认证方案在应用建好后还能改,位置在「共享组件 → 认证方案」。改完记得清一次会话,浏览器里存着的旧会话不会自动失效。
4. 页面布局与控件:Grid Layout 背后的 TABLE、Dynamic Action 的无刷新链路
APEX 的「声明式开发」很容易让人误以为不用懂前端。事实是:布局配置的每一个开关,最终都翻译成 HTML 标签;控件的每一个动作,最终都翻译成一次 AJAX 请求或者一段 JS。看懂这层映射,配置起来就是照着结构填参数;看不懂,就只能试。
4.1 Grid Layout 三个开关对应的 HTML 结构
选定主题之后,页面的整体框架由模板决定,开发者的可操作空间是几个固定区域:Body1到Body3在 HTML 里渲染成<table>,Position1到Position4渲染成<div>。绝大多数数据页用的是 Body 区,也就是表格布局。
而每个 Region 在 Grid Layout 里的三个配置项,一一对应着 HTML 结构:
| 配置项 | 对应 HTML | 作用 |
|---|---|---|
| Start New Grid | <table> | 是否另起一张表,即不沿用上一张表的列定义 |
| Start New Row | <tr> | 是否换行,开启则新起一行 |
| Column | 第 n 个<td> | 当前 Region 落在这一行的第几列 |
举个具体的三行布局:顶上一行放三个搜索区Search1、Search2、Search3,四个条件依次占 1、2、2 列;中间一行放三个子区域占 1、2、3 列;底下一行再嵌三个子区域占 1、2、1 列,第三行还要换行。对应的配置就是:
Search1 : Start New Grid=Yes Start New Row=Yes Column=1 Search2 : Start New Grid=No Start New Row=No Column=2 Search3 : Start New Grid=No Start New Row=Yes Column=2 Sub1 : Start New Grid=Yes Start New Row=Yes Column=1 Sub2 : Start New Grid=No Start New Row=No Column=2 Sub3 : Start New Grid=No Start New Row=No Column=3规律只有一条:Column的值是这一行里的第几列,Start New Row决定要不要另起一行,Start New Grid决定要不要另起一张表。搞混之后页面不会报错,只是排出来歪歪扭扭,而且拖动浏览器窗口时错位更明显——因为宽度是按表格列算的,不是按百分比。
早期 4.1.1 版本里,Region 的Column属性在一个 Body 内是全局的,想给子区域重新排布基本没戏;4.2.5 之后每个层级都能单独配 Grid Layout,嵌套布局才真正可用。这也是从 4.1 升上来的人最容易忽略的差异。
4.2 控件属性、事件、校验三件套的配置
APEX 的控件(Text Field、Select List、Date Picker、Button)都挂在同一套属性框架下。真正天天用的就那几个:Form Element Width控制宽度,Value Required控制必填,Default value设默认值,Format Mask控制显示格式(日期最常见),Condition Type控制显示条件,Read Only Condition Type控制只读条件。后两个是条件式渲染的关键——同一个页面,不同角色看到的控件不一样,靠的就是这两个,不需要写一行 JS。
Dynamic Action 是 APEX 里最像「前端框架」的东西,它把浏览器事件和数据库动作串起来:Condition Type决定这个动作要不要注册,When Condition决定每次触发时要不要执行,True Actions和False Actions分别是条件成立和不成立时干的事。执行 PL/SQL 时它走的是异步请求,页面不刷新,这就是所谓的无刷新交互。
一个典型组合:页面上有个文本框,值不为空时隐藏某个区域,为空时显示。配上Change事件、When Condition设成is not null,两个动作分别绑Hide Region和Show Region就完了。另一个高频场景是页面加载时给日期控件赋当前日期:
-- Page Load 型 Dynamic Action 的 True Action,Set Type 选 SQL Statement SELECT SYSDATE FROM dual;Set Type选SQL Statement,Affected Elements的Selection Type选Item(s),再填上目标项名(比如P2_DATA),页面加载完控件里就是当天日期。注意一点:这个动作执行时机在页面渲染之后,如果控件本身带Default value,两边会打架,最终显示哪个取决于执行顺序,我的做法是二选一,不要在同一个控件上既设默认值又加 Page Load 动作。
校验(Validation)是另一套东西,按顺序配:When Button Pressed指定哪个按钮触发,Condition Type选触发前提,Validation Type选校验类型,最后填错误信息和Associated Item。下面这个例子实现「点击搜索前,先确认表里有user_id='123'的记录,有才校验文本框不为空」:
-- Condition Type: Exists (SQL query returns at least one row) SELECT 1 FROM demo_user_t WHERE user_id = '123'; -- Validation Type: Function Returning Boolean BEGIN IF :P1_X_TEXT IS NOT NULL THEN RETURN TRUE; END IF; RETURN FALSE; END;Condition Type用Exists意味着条件不成立时这条校验直接被跳过,不会打扰用户;Validation Type用Function Returning Boolean则把判断逻辑完全交给 PL/SQL,:P1_X_TEXT是绑定变量写法,必须带冒号,写成P1_X_TEXT会被当成列名,报ORA-00904。Error message display location建议设成「Inline in Notification」,错误信息显示在控件旁边,比弹窗打断体验好。
4.3 Tabular Form 的视图建模与 Process 提交
单条记录的增删改,APEX 的做法一般是链接到新页面。要在同一张表里批量改多行,用 Tabular Form。它的开发思路和 EBS 的 Form 很像:页面上展现的是一张视图,行级提交交给一个 Process 处理。
第一步是建视图。视图里必须包含能唯一定位行的主键列,否则提交时 APEX 找不到该更新哪一行,表现是「改了五行只保存了一行」或者「全部覆盖成同一行的值」。
CREATE OR REPLACE VIEW demo_class_v AS SELECT t.user_id, t.resp_id, t.resp_appl_id, t.login_name, c.class_name FROM demo_user_t t, demo_class c WHERE c.class_id = t.class_id;user_id就是那个主键列,建 Tabular Form 时要把它勾成主键(Primary Key),其余列设成可编辑。视图做联接的好处是所有下拉、校验、展示都基于同一份数据源,改字段只改视图。
第二步是挂一个Apply Change按钮,在按钮上建 Process,类型选 PL/SQL:
DECLARE l_cnt NUMBER; BEGIN -- f01 对应 Tabular Form 的第一列,索引顺序按页面列顺序来 FOR i IN 1 .. apex_application.g_f01.COUNT LOOP -- 先校验输入的 class_name 在字典表里是否存在 SELECT COUNT(*) INTO l_cnt FROM demo_class WHERE class_name = apex_application.g_f05(i); IF l_cnt = 0 THEN apex_error.add_error( p_message => '班级名称不存在:' || apex_application.g_f05(i), p_display_location => apex_error.c_inline_in_notification); ELSE -- 存在则把勾选的行写入另一张表 INSERT INTO demo_log_t (user_id, class_name, log_time) VALUES (apex_application.g_f01(i), apex_application.g_f05(i), SYSDATE); END IF; END LOOP; END;apex_application.g_f01、g_f05是 Tabular Form 提交上来的数组,数字对应页面列的顺序,不是视图里的字段名。这个映射关系是硬编码的,页面上调换两列顺序,代码就得跟着改,所以我在项目里会把这层逻辑封装进一个包,页面上的 Process 只调一行demo_save_pkg.apply_change(...),避免每次调列都去翻 PL/SQL。apex_error.add_error把错误挂到页面通知区,多条校验失败能一次性显示出来,比raise_application_error中断整个提交友好。
5. 避坑与排查:认证失败、404 和提交丢行这几笔血泪账
这套流程我照着走过不止一遍,每一遍都能在差不多的地方栽跟头。下面几条是从实际环境里记下来的,按「现象 → 原因 → 解决」整理,遇到同类问题时先对号入座,比从头翻日志快。
5.1 安装期:登录进不去与页面 404
现象一:apex_admin页面能打开,输入 ADMIN 和正确密码,一直提示认证失败。
原因是 3.0 的残留没清干净。apxremov.sql跑过之后,APEX_030200schema 下的部分用户和同义词可能还在,认证请求被路由到旧引擎去校验,密码自然对不上。查一下就很清楚:
SELECT username FROM dba_users WHERE username LIKE 'APEX%';如果结果里除了APEX_040200、APEX_PUBLIC_USER还有APEX_030200,就是它。解决方式是DROP USER APEX_030200 CASCADE;清掉残留,重启数据库再试。这一步做完之前,改多少次 ADMIN 密码都没用。
现象二:访问http://server:8888/apex返回 404。
先确认端口是不是真的起来了:SELECT DBMS_XDB.GETHTTPPORT FROM dual;。返回空或者返回的还是 8080,说明SETHTTPPORT没生效,得重启实例。端口对了还 404,就是 DAD 的路径没对上——CREATE_DAD('apex', '/apex/*')里的第二个参数必须以/*结尾,写成/apex或/apex/都匹配不上请求路径。
现象三:手滑 drop 了APEX_040200,所有页面直接 500。
这个没有后悔药,APEX_040200里存着引擎全部的 PL/SQL 对象和元数据,drop 之后只能重装。重装前必须先跑一遍apxremov.sql清掉残余,否则apexins.sql会在建对象时报ORA-00955(名称已被占用)。重装完还要重新设 ADMIN 密码、重新解锁 ANONYMOUS,之前建的工作空间和应用如果不在备份里,也一并没了。所以装完第一件事就是导一次应用备份,别等出事才想起来。
5.2 开发期:Tabular Form 提交和 Dynamic Action 触发
现象四:Tabular Form 改了多行,点 Apply Change 只有第一行生效。
主键列没配对,或者页面列顺序和 Process 里的g_fxx索引对不上。先在页面上加一个调试用的隐藏项,把apex_application.g_f01.COUNT的值打到页面上,确认数组长度是不是等于勾选行数;再逐列比对页面列顺序和数组下标。这个问题的根因永远是「数组下标按页面显示顺序排,不按视图字段顺序排」,改过页面布局之后尤其容易错位。
现象五:Dynamic Action 配了 Hide Region,页面加载时没反应或者报 JS 错。
两种可能。一是Selection Type和实际目标不匹配——选Item(s)却填了 Region 名,或者反过来;二是用了 Page Load 事件但Condition Type设成了某个依赖用户输入的表达式,页面刚加载时那个值还不存在,条件判断直接短路。排查方法是在浏览器里看网络面板,确认异步请求有没有发出去:请求没发出去是配置问题,请求发了返回 200 但页面没变,是Affected Elements里的选择器写错了。这类前端问题光看 APEX 后台看不出来,必须开开发者工具。
6. 二次开发:把配置沉淀成脚本和模板,别再手工点一遍
照着文档装完第一套环境之后,我的做法是立刻把手工步骤脚本化。理由很实际:这套流程里能手工点错的地方太多,端口号、DAD 名、表空间路径、密码复杂度,每一项都可能在下一台机器上变,但执行顺序永远不变。写成一个可重复执行的脚本,重装一次从两小时压到二十分钟。
安装脚本拆成两段。第一段是 SQL*Plus 能跑的部分,卸载、建表空间、装主安装包、改密码、解锁用户、装语言包,按固定顺序串起来:
#!/bin/bash # 用法:./apex_setup.sh <表空间名> <临时表空间> <数据文件路径> set -e TS_NAME=${1:-apex01} TS_TEMP=${2:-TEMP} DBF_PATH=${3:-/d01/oracle/ORCL/db/apps_st/data/apex01.dbf} sqlplus -s / as sysdba <<EOF WHENEVER SQLERROR EXIT SQL.SQLCODE @\$ORACLE_HOME/apex/apxremov.sql CREATE TABLESPACE ${TS_NAME} DATAFILE '${DBF_PATH}' SIZE 100M AUTOEXTEND ON NEXT 100M MAXSIZE 1000M; @\$ORACLE_HOME/apex/apexins.sql ${TS_NAME} ${TS_TEMP} /i/ ALTER USER ANONYMOUS ACCOUNT UNLOCK; ALTER USER APEX_PUBLIC_USER ACCOUNT UNLOCK; EXIT EOF # 密码和语言包是交互式的,单独跑,不放进自动化里 echo "下一步手动执行:sqlplus / as sysdba @\$ORACLE_HOME/apex/apxchpwd.sql"set -e加上WHENEVER SQLERROR EXIT SQL.SQLCODE是两层保险:前者管 shell 层,后者管 SQL 层,任何一步 SQL 失败都直接退出,不会带着半成品环境往下走。apxremov.sql放在脚本开头是有意的——新机器上它只会报一堆「对象不存在」,不影响后续,但能保证重跑时环境干净。
第二段是应用层面的模板化。把一套常用的布局(顶部搜索区三列、中间列表、底部按钮条)做成一个空应用导出成.sql,新项目直接从它导入,改改页面名和表名就能用。APEX 的导出格式本身就是可执行 SQL,能进 Git,能做 diff,这一点比很多人想象中好用:
-- 在 SQL 命令窗口导出整个应用,输出到 CLOB 后落成文件 DECLARE l_file CLOB; BEGIN l_file := APEX_UTIL.EXPORT_APPLICATION( p_application_id => 100, p_export_format => 'DOS'); -- 实际使用时把 CLOB 写到服务器目录,或者用 SQL Developer 的导出向导 END; /p_export_format选DOS是为了让换行符在各平台一致,避免拿回 Windows 上导入时报奇怪的语法错。导入用APEX_UTIL.INSTALL_APPLICATION,注意应用 ID 在不同环境要错开,同一个库里 ID 冲突会直接覆盖已有应用。
认证方案从 APEX Accounts 切到 Header Variable 时,改动集中在一个函数上,前面那个demo_auth就是模板,把查表的条件换成调 EBS 的用户验证接口即可。切完之后原有的 APEX 用户不需要删,先留着当应急入口,等单点稳定跑一个月再关。
有这么一次我没走完整的重装验证,直接在一套跑了半年的环境上手工升级,结果旧版本的残留用户卡了三天,业务方每天催进度。从那以后我每次动 APEX 环境之前,都强制先在测试库上把「卸载 → 安装 → 建工作空间 → 导入应用 → 用 End User 登录点一遍」这条链路完整跑一遍,跑通了才碰生产。希望帮到你。
本文还有配套的精品资源,点击获取