ebs mrp可以跨OU妻孝 父子共用一女吗?

在EBS里新建一个OU的步骤
来源:博客园
1. 建立OU组织,关联SOB,LE 2. 系统管理员下运行并发: Replicate seed date 3. 建立PO的职责, 设置 MO:Default Operating Unit ,授权 4. 进入新的PO职责,设置 Financial Options 5. 进入新的PO职责,设置 Purchasing Options Run the Replicate Seed Data request followed by steps: Navigate to System Administration responsibility, Requests -> Run -> Single Request, OK, Select Replicate Seed Data -> Select the Organization which is new created as parameter ->Submit *This will replicate the seed data in your database. You need to do this everytime you make a new Organization. 这个程序指向的地点是: ad_morg.replicate_seed_data(X_org_id,NULL,NULL); 并且, 请求那边, 输入参数只有一个 org_id 实质是 OU, 其他的2个放空, 代表复制这个OU下的所有的OU层次的基础数据. The seed data replication program works in two modes: o
Single organization: This mode applies when the seed data replication program is executed within the context of a particular operating unit (or Org_ID). o
All organizations: This mode applies when the seed data replication program is executed without an operating unit context. 实际复制的表指向是: load_table_list 这个方法, 从这里头可以看到, 复制了 AR,AP,CE, .... 等等 OU 层次的基础DATA. 本质的用途就是: 比如 ap_invoices 里头的 data 复制到 ap_invoices_all ,或者复制到一些语言表里头去. 这个请求有2个用处: (1) 在多组织转换的时候需要使用到. (2) 平时如果跑其实也没啥关系, 不过oracle bug 太多, 不建议自己手动去跑,建议发现问题的时候, 在oracle support下跑. FRM-40735 这个经常都是需要去跑这个玩意的. 对了, 当然会增加点空间, 但是微不足道. 多组织结构 ORACLE EBS一个很大的卖点是它的多组织结构.ORACLE EBS的文档资料里面解释呈现这样一个树型图: 业务组(BG) | HR组织 | 法律实体(LE) | 营运单元(OU) | 库存组织 1. 业务组: 它代表组织结构的最高层次, 它分离了人力资源的信息. 例如, 当你查询人员时, 它会列出所有分配给相应业务组的成员, 而你自己所属于的组织只不过是业务组的一份子. 这样说可能造成一种误解: 一个公司只能有一个业务组, 实际上可能有多个, 但是业务组之间不能共享信息. 2. 帐簿: 它其实不能称为一种组织, 更象组织中的一个层次或性. 一个业务组中可以有一个或者多个帐簿. 3. 法律实体: 法律实体类型赋予组织税码以及其它与法律相关的属性. 一套帐簿可以分配给多个法律实体. 4. 平衡实体: 平衡实体就是帐户结构中的一个段, 即平衡段. 在你准备财务报表的时候它体现你的帐户实体. 5. 运营单元: 如果一个组织应用到现金管理, 订单管理, 运输, 应收, 应付和采购模块, 则它就是一个运营单元. 它可能是一个销售中心, 一个分公司, 或者一个部门. 对于这些应用, EBS按照法律实体分离了业务信息, 每个用户只能访问到他自己所属于的运营单元的信息. 一个法律实体下面可以有一个或者多个运营单元. 6. 库存组织: 当一个组织要用到库存事物(例如接收, 转移等), 或者它要负责制造和分销产品时, 这个组织就是一个库存组织. 它可能是一个制造厂, 仓库, 分销中心或者销售部门. 当用到下列模块时, EBS按照库存组织来分割业务信息: Oracle Inventory, Bills of Material, Engineering, Work in Process, Master Scheduling/MRP, Capacity, and Purchasing receiving functions. 当你登陆到这些 模块时 , ORACLE EBS会提示你选择一个库存组织. 同样, 一个运营单元下面可以有一个或者多个库存组织. 7. 人力资源组织: 它体现了一个公司的基本工作结构. 只有当一个组织是人力资源组织时, 你才能分配人员给这个组织. 一个业务组中可以有一个或者多个人力资源组织. 8. 资产组织: 资产组织属性使组织可以执行与资产相关的功能. 只有当一个组织属于资产组织时, 才能使用 Oracle Assets. 还需要说明一点的是 : EBS的一个组织并非只能归属于一个类型. 例如,
一个组织是一个 运营单元 , 若在这个组织中要用到 Oracle Inventory, 那么它同时还是一个 库存组织 . 所以, 组织类型代表了组织的一种属性, 而不是把组织简单的分类. Oracle 组织结构和安全性的一些关系 Oracle的组织结构和安全性有着密切的联系,如:如何才能屏蔽不同SOB之间的信息的访问,如何才能屏蔽不同OU之间的信息.这些主要是通过responsiblity来实现的. 一般在建好responsiblity后我们需要给这个责任在责任层附上三个profile的值: 1.GL set of book name,这个profile就是用来屏蔽账簿用的,如果你的企业里使用的是多个账簿的话,用它来对责任屏蔽账簿,然后把责任附给用户,如果你的企业里只是使用了一个Book那么当然可以在sit层设置就可以了,一般的做法是在sit设置一个,然后对有特殊的责任再设置. 2.HR: User Type.这个其实是在你安装了HRMS系统后就很有用了,用来屏蔽工资册系统和一般HR用户的数据访问的权限.它有三个选项 HR 用户,含工资单管理系统的 HR 用户,工资单管理系统用户. 一般情况下,我们都是在sit层选择HR用户,因为只有安装了Oracle Payroll 并且使用 HR 安全性功能下面两个才起作用 3.MO: Operating Unit.这个就是屏蔽OU的了,很有用,如果你的企业是多个OU的话.这个值是一定要设置.(INV可以不用设置,因为OU是用来屏蔽OM,AP,AR这些信息的) 在建了上面的这些profile后,系统已经能屏蔽OU级的数据了,如果还要屏蔽Inventoty级的数据的话,可以在Inventory的organization access里面设置可以访问的inventory Org. 这样Oracle做到了不动组织结构,不同组织类型的数据对于用户的访问限制,它的桥梁就是责任. Copying Inventory Organizations You can create and update a large set of inventory organizations and their business entities, such as Subinventories, Items, Bills of material, and Resources. These entities can be copied and customized as part of an inventory organization copy. This aids in the management of inventory organizational setup, which is mandatory for the use of Inventory, Costing, Bills of Material and Work in Process. This feature is useful for companies that have a large number of inventory organizations. You can copy a source inventory organization's parameters, defaults, and settings, in a single operation, to as many new organizations as you wish for the following setup entities: o Bills of Material o Routings o Items o Categories o Subinventories o Shipping Networks o Inventory Parameters o WIP Parameters o BOM Parameters Organization Mass Copy is a two-step process. In order to copy source inventory organization structures, you must first set up entity APIs to load interface tables and then run the Copy Organization concurrent program to export and import the setup data. 拷贝库存组织时,库存现有量为零的料号不能指定给新的组织。库存现有量不为零的料号指定给新组织时,在新组织的库存现有量为零。
免责声明:本站部分内容、图片、文字、视频等来自于互联网,仅供大家学习与交流。相关内容如涉嫌侵犯您的知识产权或其他合法权益,请向本站发送有效通知,我们会及时处理。反馈邮箱&&&&。
学生服务号
在线咨询,奖学金返现,名师点评,等你来互动当前位置: >>
ORACLE ERP 开发基础前言 EBS 入门一周之口水贴 EBS 入门二周之口水贴 EBS 入门三周之口水贴 EBS 入门四周之口水贴 Oracle Forms 基础 Forms 设置部份 设置 ITEM 为必填项 设置 ITEM 的初始值为当前日期 实现按“ENTER”自动跳至下一条记录 使用堆叠画布 深入了解 Forms 的事务触发机制 创建 FO
RMS 数据块的主从关系 FORMS 代码部份 FORMS 触发器的执行顺序 FORMS 变量类型 判断数据块的项是否为空 信息提示框之基本用法 用代码控制 ITEM 属性 用代码控制 ITEM 的焦点转移 用代码控制 WINDOW 属性 判断当前 FORM 的状态 在 when-new-record-instance 控制 BLOCK 的可用状态 实现将 LOV 可以自行录入内容 在 FORMS 调用 WEB 页面 Name_In()\COPY()函数 Forms 数据提交的方式 在一个 FORM 中调用不同的 WINDOW Form 假死锁问题之初步解决 FORM 死锁解决 FORM6i 引入 JAVA 类 FORMS 之列表项动态赋值 FORMS 之 LOV 动态赋给记录组 屏蔽 FORM 系统提示信息 FORM 之间的调用 Tree-层次树之使用 遍历数据块 LOV 动态确保从块记录唯一 Form 实现复制上条记录 控制删除条件的触发器 实现进度条 Form 实现唯一性检查 Oracle Report 基础 Report 页面设置 数据模型、固定框、循环框 实现记录汇总行动态伸缩4 4 5 5 6 6 6 6 7 7 7 9 9 11 11 13 14 14 15 17 17 17 17 18 18 18 19 19 20 22 22 23 24 25 25 25 26 26 27 27 28 28 29 29 29 31 Author:JarWang(王重东)Email: QQ:查询视图无数据 Report 数据域 Report 汇总项 Report 动态条件查询 矩阵报表 Report 编译出错 Oracle 数据库基础 常用函数 substr 函数 Lpad/Rpad 函数 日期函数 随机取前 10 条不同的记录 TRUNC 函数 修改表的一些常用语法 舍入函数 实现类似 BREAK 语句 Oracle 定时器 Over 分析查询 Oracle 层次树查询 Merge into 应用 Truncate table 绑定变量与非绑定变量之比较 取不重复的记录行 查询具有相同薪水的职工 统计 EBS 表数量及 Oracle 概念 Oracle 死锁之解决方法 PL/SQL 过程调用表示法 PL/SQL 调用 Java 类 PL/SQL 操作 EXCEL PL/SQL 异常机制 PL/SQL 面向对象编程 PL/SQL 实现字符串转成数组 PowerDesigner ORA-01403 未找到数据之解决方法 PL/SQL 细粒度事务控制 物化视图 通过游标更新数据 给 PACKAGE 加密 Oracle Advanced Queue 跨数据库的 SQL ORACLE 高级复制 查询某一表或视图中的触发器 EBS 开发基础 开发工具安装 Oracle EBS 工具集 EBS 二次开发包注册231 31 32 33 33 33 34 34 34 34 34 35 35 36 36 36 37 38 40 42 42 42 44 45 45 46 47 47 51 55 56 57 58 59 60 61 62 62 63 65 66 68 68 68 69 72 Author:JarWang(王重东)Email: QQ:利用 TEMPLATE.fmb 模板来开发 Form 注册表单 FORM 注册请求 注册职责 注册值集 注册主从值集 通过应用开发员取得系统管理员职责 查询视图时没有显示数据 注册报表(report) 请求的输出及日志 实现手动提交请求 手动提交请求示例 客制化菜单 客制化右键菜单 客制化工具栏 调用 EBS 日期控件 查询数据时限定语言环境 实现历史记录查询 实现文件夹功能 实现手电筒查找的功能 记录指示器切换标签页 EBS 的条件查询方法 自定义代码 通过科目编码取科目描述 Fnd_Profile 之使用 Form 之间共享参数组织 ID 弹性域 注册关键性弹性域 注册说明性弹性域 条件控制说明性弹性域 PO 行界面启用弹性域 调用会计科目弹性域 EBS11i Form 开发实现 MVC 模式 EBS 预警功能自定义开发 EBS 自定义邮件通知 EBS 配置文件(Profile)常用设置 设置菜单导出的文件格式 IE 打不开 EBS 一个职责下打开多个 FORM 界面 获取 EBS 的查询语句 EBS 调用 JSP 页面 OAF 页面查看历史信息 定义文件夹的管理权限 判断 EBS 提交请求是否成功 FORM 更新多表视图 WorkFlow373 78 80 82 84 87 89 90 90 93 94 95 97 99 99 100 101 101 102 107 110 111 112 115 116 116 117 117 118 120 121 123 124 125 128 132 132 133 133 133 134 136 136 139 140 143 Author:JarWang(王重东)Email: QQ:EBS WorkFlow WorkFow builder 安装 Workflow 查看工作流权限 Workflow Builder 打开 PO 审批流时报错 Workflow 启动报错 Oracle BPM BPM 安装 BPM 基本使用 Discoverer 工具 Discoverer 安装设置 Discoverer 快速入门示例 Discoverer 工作表数值型显示 通过工作簿找到对应的 Discoverer 职责 Discoverer JOIN 之使用 Discoverer 数值型无法正确显示 Discoverer 上钻/下钻 Discoverer 条件 LOV Discoverer 分类汇总求 AP 供应商余额 Oracle DBI 工具 DBI 工具之配置 DBI 之报表开发 DBI 简单报表开发 DBI 维度报表开发 Oracle BIEE 工具 BIEE 工具之安装 BIEE 工具之体念 BI Publisher 工具之体念 数据导入工具 Dataload Loadrunner Oracle ADI GL 日记帐导入 Oracle ADI-客户化开发 Other Notes143 143 143 144 145 145 145 146 146 146 147 150 151 151 153 154 155 156 157 158 160 160 165 171 171 172 173 174 174 175 178 179 180 180前言偶是 2008 年才开始接触,这个传说中的 Oracle ERP。而在此前四年间,特别是在做 JAVA 程序员二 年多的时间中,养成了一种对架构、模式、面向对象的狂热追求,导致对 EBS 亦常失望。因为 EBS11i 没 有软件模式、设计、分层等,只有象面条般的 PL/SQL 语句。4 Author:JarWang(王重东)Email: QQ:EBS 入门一周之口水贴Oracle ERP-ebs11i。近一个周的摸索,算是对这个号称全球 ERP 第二的东东有点“表面”认识了。 在 这个领域,虽然 ORACLE FORMS 也是使用 JVM 来运行,但跟 JAVA 搭不上一点边。官方语言是 PL /SQL。开发工具相当古老 FORMS6i,要靠补丁才能在 XP 下运行。JAVA 当中的模式、设计、分层等等, 根本使用不上。只是拖拉一下控件就好,就算你不想拖拉也不行。因为 ORACLE FORMS 根本不支持,只 允许拖拉式编程。比 VB/DELPHI 这类语言还死心眼。唯一要编程的就是写些 SQL 代码,也谈不上什么分 层,表现层与 SQL 混 在一起。大多数的函数,ORACLE 都内置了,没有内置的,你也非常难去实现。 Forms 的拥护者说是 Oracle 的目的是要减少代码。 这种理由根本站不住脚, 通过属性设置来实现编程, 最终也是要生成代码的。只是这些代码 Oracle 不让你看到而已。于是 Forms 的拥护者又说 FORMS 封装的 好。晕倒!看来是没有使用过 VB 了,VB 是所有语言当中封装最好的了,但照样要被面临淘汰。Why? 再晕?看来 Forms 的拥护者软件工程也没学好。快速开发只是软件一个要求而已,开发工期短嘛,人力成 本就少啦。但软件的可维护性呢?没有一行代码,全部通过设置开发出来的软件,叫人怎么维护。修改一 个地方,从后台到前台全部的修改。这也叫可维护性? 再说说这个 EBS11i,操作非常不人性化。看个报表什么的,都是通过“请求”来实现,终端客户抱怨 操作步骤太多, 点来点去的, 点到最后都快忘了要做什么! ORACLE 的官方顾问却说, 这是国际标准流程。 一说到 ORACLE 的缺点,就拿“国际”两字来压人。报表呢?没一份符合国人习惯。也不知道 ORACLE ERP 凭什么在国内站住脚? EBS 安装包相当大-32G,数据表的冗余量也非常大。一份采购单,在 PO 模块中有,在 PO 接口模块 中也有,另外在 AP 模块也存一份。也就是说一份相同的数据存了三次。 唯一值得一看的亮点就是跟财务管理模块高度集成。EBS 入门二周之口水贴调试,Oracle EBS 二次开发的调试,简直要将人送下地狱。记得刚接触 JAVA 时,还说调试不如 VB 方便。那现在看来,做 Oracle 二次开发简直就是地狱,而且还是十八层的那种。每修改一个东西,都要上 传到 SERVER 上调试。事实这也不叫调试,叫测试比较准确。总之就是对 Oracle EBS 恶心之极,搞不懂 还是有那么多人在追棒。 有点可笑的是, ERP100 论坛上居然有人说, EBS 而不学 SAP, 在 学 是因为 ORACLE 公司大。真是要晕倒。照这种逻辑,那么 Linux 根本上不应该存在,因为 Linux 远没有 MS 大。什么逻辑?EBS 入门三周之口水贴PL/SQL 在语法上与 VB 相似, 都有类似 “IF…THEN…END IF” VB 当中的 Event 事件) , ( 等同于 Forms 的触发器(triiger),只是概念不同而已。对于有过 VB 项目开发经验的我来说,刚接触 Oracle Forms 感觉就 是 VB。二年前在“Think in Java”的影响下,毫不忧郁地从 VB 转到 JAVA 阵营。两年过去了,在 JAVA 阵营,做纯 JSP 的 OA 项目,也做 STRUTS+HIBERNATE 的 MIS 项目,却始终无法逃离“增改删查”这 种技术含量不高的应用程序。从 ERP 的角度来看,我所做过的项目,抛开技术构架来看,只能算是 MIS, 严格上说连 MRPII 都算不了,更别说什么 ERP 了。现在接触的 Oracle EBS 应该算是 ERP 吧。但应用效果 呢?最多也只是 MRPII 的水平。 什么叫 MRP,也就是一些试算物料排程+库存的程序。也叫 MIS。 什么叫 MRPII 呢?MRP+财务管理系统。 什么叫 ERP 呢?MRPII+分销系统+供应链系统+CRM 系统+HR 系统+知识库等等。总之,ERP 有点无 所不含了, 以致于 ERP 的失败率很高。 大多数的公司虽然号称运用的是 ERP, 其实质应用呢?最多是 MRP 或 MRPII,甚至只是一个功能好一点的记账软件。5 Author:JarWang(王重东)Email: QQ:04 年 IBM 推出了 SOA 的概念后,ERP 遭到了前所未有的危机。Service Oriented Architecture 其思想 就是保护原有的 IT 投资,以此为基础进行软件功能的扩充。技术核心就是 Web Service。而 ERP 思想呢? ERP 的思想就是想用一套软件从制造-财务-分销-商业智能全盘搞定企业信息化。这种大而全的做法, 正在遭到 CIO 们的怀疑。 Oracle 也有推出自己的 SOA-(以 JDEVELOPER 为核心的组件化应用) ,这是 否也在预示 PL/SQL 要被 JAVA 代替呢?^_^EBS 入门四周之口水贴除了在 FORM 中使用属性窗口进行对象属性设置外,Oracle 也有提供函数来实现对 FORMS 对象的控 制。 但总体上来说, 给人的感觉就是不直觉, 完全的黑箱操作。 难道这就是 Oracle 所说的减少代码的编写? 事实上 VB 饱受批评,除了不支持全部的 Win API 外,就是封装的太死,连继承都不让使用。但用过 Oracle Forms,就会挺同情 VB 的做法。Oracle 的做法更绝,试图用 PL/SQL 统一前台与后台编程。连面向对象的 概念都没有, 更别谈什么其他的了。 尽管 Forms 最终是要生成 JAVA 的 APLLET 代码进行执行。 还有 Forms 不支持类似于“.”的联想操作,也是让人想不通。如果哪个 C++或是 JAVA 开发工具不支持”.”操作,那么 肯定会进博物馆的。 OVER,即来之,则安之。停止比较,重新学习吧。Oracle Forms 基础Forms 设置部份Forms 基本对象概念 FORMS 的基本对象说明 FORM: 可以有多个 Window。 Window: 只能有一个 CANVAS,但是还可以包括其他的类型的 CANVAS, 比如 CANVAS_STACKED,这种 Canvas 类型将在后面的章节中讲到。 Canvas: Canvas is a surface where visual objects,such as graphics and items,are arranged. 和 Block 没有直接的对应关系,而是直接和 Item 对应。一个 Canvas 上面可以有来自不同的 Block 的多 个 Item.,是我们对 Item 进行位置调整的平台。 Block: Logical owner of items,items in one block are logically related.There are two main tupes of blocks:data block and control block Item: Form 中最基本的组织元素,我们设计的最小单元 Parameter:相当于全局变量,其作用是传递参数,Oracle 标准的 Form 也有单独建一个 Block(多个 I tem)来 传递参数的例子。 Record Group: 主要应用是可以提供给 LOV 与 list item,ftree 作为数据源 A record group is internal Form Builder data structure that has a column/row.framework similar to a database table LOV:List Of Value,会直接对应到 Text Item 上面,点击后会弹出给用户选择数据。 Attached Libraries:存放的是 Oracle 标准的一些 PLL 文件。 Property Classes:Oracle 标准的一些属性类,我们在建立 Window、Canvas、Data Block 等都会选择一个属性类 以继承一些属性和方法 明白了上面的基本概念,就可以开工了。6 Author:JarWang(王重东)Email: QQ:设置 ITEM 为必填项Setup:Effect:此效果与是 set_item_property('test.l_test',required,property_true)一样的。设置 ITEM 的初始值为当前日期实现按“ENTER”自动跳至下一条记录设置 BLOCK 属性:导航器风格:改变记录。7 Author:JarWang(王重东)Email: QQ:使用堆叠画布Effect:1.先将数据块、画布布局好(用向导的方式就可以了,具体操作就不用讲了吧) 。 2.在画布中创建一个堆叠画布。3.将项的画出属性更为堆叠画布(这一步最关键了) 。4.调整后得到下面这效果了。8 Author:JarWang(王重东)Email: QQ:深入了解 Forms 的事务触发机制编写一个健壮的 FORMS 应用程序,免不了要做各种数据的检验动作。所以必须了解 FORMS 事务触发器 的工作原理。其他类型的触发器相对来说比较好理解,就不详说了。 ① FORMS 处理事务分成发送(POST)和提交(COMMIT)两个阶段。这个跟 JAVA 中的事务操作类似, 也就是 Statement 和 Commit 两个阶段。但 FORMS 一些规则比较死,也就是说规定好 POST 之前会触 发 PRE 触发器之类等等。 ② 事务触发器分成三类,PRE-XXX、ON-XXX、POST-XXX,它们的执行顺序可以直接从其英文缩写得 出。 例:执行 INSERT 操作,会按以下顺序进行。 1.1 从数据项复制数据。 1.2 触发 PER-INSERT 触发器。 1.3 检查记录的惟一性。 1.4 插入行到其表或者触发 ON-INSERT 触发器。 1.5 触发 POST-INSERT 触发器。创建 FORMS 数据块的主从关系1、 先创建两个数据块, 当然这两个数据块在 DB 应该有外键的关系(不是一定要创建数据库外键关联哦?)。 2、选择从表的数据块,然后点击菜单数据块向导。9 Author:JarWang(王重东)Email: QQ:3、选择关联属性。非孤立:表示当有从记录时,不允许删除主记录(默认) 。 级联:当删除主记录时,从记录也一起删除(推荐使用) 。 孤立:当删除主记录时,从记录保留不变(不推荐使用) 。 事实上,当选择不同的属性时,FORMS 会在主数据块中,自动创建两个触发器 ON-POPULATE-DETAILS:当插入主数据块记录时,自动将主键赋值给从数据块外键字段。 ON-CHECK-DELETE-MASTER:实现从删除主数据块记录时,从数据块要执行何种操作。 4、设置主键及报 FRM-30100 错误。 ①如果数据块属性设成使用主键, 那么该数据块的 ITEM 必须有一个设成主键, 否则报 FRM-30100 错误。 ②即使数据块设成不使用主键。但该块的查询数据源名称与 DML 数据目标名称不一致时,也是必须设 至少一个 ITEM 为主键。否则报 FRM-30100 错误。如图:注:查询数据源与 DML 数据目标不一致时,数据 INSERT、UPDATE、DELETE 都会发生在 DML 数据 目标那张表。 例如:以视图为查询数据源,而在数据表中仅保留 ID。而查询时,自动匹配查询到相应的 number、 description 将视图的字段设置如下,否则会报无法找到这个字段之错误。10 Author:JarWang(王重东)Email: QQ:5、主键赋值。 按数据库设计模式范式要求,每张表都应该有一个 PRIMARY KEY。而且此字段一般不让用户操作,由 sequence 自动维护。我们可以数据块的 PRE-INSERT 触发器中加入代码: select hek_test_sq.nextval into :hek_test_headers.FORMS 代码部份 FORMS 触发器的执行顺序针对我们所看的 FORM,我们总结了 FORM 的一些操作中 TRIGGER 的执行顺序。其中还有很多触发器没 有被提到,这是因为程序中没有用到。但是在 FORM 运行的过程中,这些触发器的执行过程都是设置好了 的,没有用到的触发器也一样会经过已经设置好的那个时间段,只是什么动作都没有做罢了。 触发器执行顺序: 1. 当打开 FORM 时: (1) PRE-FORM (2) PRE-BLOCK(BLOCK 级) (3) WHEN-NEW-FORM-INSTANCE (4) WHEN-NEW-BLOCK-INSTANCE (5) WHEN-NEW-RECORD-INSTANCE (6) WHEN-NEW-ITEM-INSTANCE 2. 当填写一行记录完成后,光标移动到下一条记录的时候: (1) WHEN-VALIDATE-RECORD (只将填写的记录与数据库中已存在的记录作唯一性的验证,如果只是页面上的数据重复而数据库中没有与 其重复的值则不会报错.) (2) WHEN-NEW-RECORD-INSTANCE (3) WHEN-NEW-ITEM-INSTANCE 3. 当点击“保存”时 (1) WHEN-VALIDATE-RECORD (将页面上的所有数据提交到数据库,若页面上有重复的数据,则提交第一次时成功但只是将数据先写到 数据库中一类似临时表的地方,在提交第二条重复记录的时候报错,执行事务回滚,原来执行成功的指令 也将被撤消) (2) PRE-INSERT (3) ON-INSERT (4) POST-INSERT (5) POST-FORMS-COMMIT (6) PRE-BLOCK(BLOCK 级) (7) KEY-COMMIT (8) WHEN-NEW-ITEM-INSTANCE 4. 当光标移动到当前数据块中已经显示的行上时: (1) WHEN-REMOVE-RECORD (2) WHEN-NEW-RECORD-INSTANCE (3) WHEN-NEW-ITEM-INSTANCE 当在该行上的不同 ITEM 移动时: (4)WHEN-NEW-ITEM-INSTANCE 5. 当要进行修改时(在记录中的某个项上进行了 修改时) :11 Author:JarWang(王重东)Email: QQ:(1)ON-LOCK 6. 在修改完成后进行保存时: (1) WHEN-VALIDATE-RECORD (2) PRE-UPDATE (3) ON-UPDATE (4) POST-FORMS-COMMIT (5) PRE-BLOCK(BLOCK 级) (6) KEY-COMMIT (7) WHEN-NEW-ITEM-INSTANCE 7. 删除一条记录时: (1) ON-LOCK (2) WHEN-REMOVE-RECORD (3) KEY-DELREC (4) WHEN-NEW-RECORD-INSTANCE (5) WHEN-NEW-ITEM-INSTANCE 8. F11 查询过程: (1) WHEN-CLEAR-BLOCK (2) WHEN-NEW-RECORD-INSTANCE (3) WHEN-NEW-ITEM-INSTANCE 在输入查询条件后点 CTRL+F11: (4) PRE-QUERY (5) WHEN-CLEAR-BLOCK (6) POST-QUERY (7) WHEN-NEW-RECORD-INSTANCE (8) WHEN-NEW-ITEM-INSTANCE 9. CRRL+F11: (1) WHEN-CLEAR-BLOCK (2) PRE-QUERY (3) WHEN-CLEAR-BLOCK (4) POST-QUERY(每查一条记录,触发一次) (5) WHEN-NEW-RECORD-INSTANCE (6) WHEN-NEW-ITEM-INSTANCE 10.从查询状态(F11)转为输入状态(F4)时: (1) WHEN-CLEAR-BLOCK (2) KEY-EXIT (3) WHEN-NEW-RECORD-INSTANCE (4) WHEN-NEW-ITEM-INSTANCE 11.手电筒查询过程: (1) QUERY_FIND(BLOCK 级) 输入查询条件后,点击“查询”按钮: (2) WHEN-CLEAR-BLOCK (3) PRE-QUERY (4) WHEN-CLEAR-BLOCK (5) POST-QUERY (6) WHEN-NEW-RECORD-INSTANCE (7) WHEN-NEW-ITEM-INSTANCE12 Author:JarWang(王重东)Email: QQ:12.点击“New”时: (1) WHEN-NEW-RECORD-INSTANCE (2) WHEN-NEW-ITEM-INSTANCE 13.点击“Edit Field”时: (1)KEY-EDIT 14.点击“Window Help”时: (1)KEY-HELP 15.点击“Clear Record”时: (1) WHEN-REMOVE-RECORD (2) POST-QUERY (3) WHEN-NEW-RECORD-INSTANCE (4) WHEN-NEW-ITEM-INSTANCE 16.点击 F4 关闭时: (1) KEY-EXIT (2) POST-FORM 17.点击“Close Form”按钮关闭时: (1) KEY-EXIT (2) POST-FORM 18.点击“Translations”按钮时: (1)TRANSLATIONS 19.点击小叉号关闭时: (1) WHEN-WINDOW-CLOSED (2) CLOSE-WINDOW (3) KEY-EXIT (4) POST-FORM 20.选中 LOV 列表: (1) KEY-LISTVAL (2) WHEN-NEW-ITEM-INSTANCE 21.选中记录前面的小条时: (1) WHEN-NEW-RECORD-INSTANCE (2) WHEN-NEW-ITEM-INSTANCE(数据项级) (3) WHEN-NEW-ITEM-INSTANCE 22.光标上下移动时 (1) WHEN-NEW-RECORD-INSTANCE (2) WHEN-NEW-ITEM-INSTANCE 22. Form 切换到当前窗体时 (1) WHEN-FORM-NAVIGATE (2) WHEN-NEW-ITEM-INSTANCEFORMS 变量类型FORMS 有提供多种变量,提供给 PL/SQL 使用,不同的变量,生存周期是不一致的。 1.项变量:只能在当前的确表单内引用。 语法::blockname.itemname13 Author:JarWang(王重东)Email: QQ:2.全局变量:只能存储字符型数据,可以在当前会话的所有表单内引用。 语法::global.name 例:可以 when-new-form-instance 中声明一个全局变量 Global.name:=’this is a global’; 然后在 when-button-pressed 中引用 Message(:Global.name); 3.参数(Parameter) :在 Forms 中直接创建一个参数。 语法::Parameter.parameter1 := ‘test’; 另外:在 EBS 中,可以通过在注册功能时,给 Parameter 赋值(注意:字符类型赋值是加””双引号) 。4.系统变量:这个是 FORMS 预定义的,直接使用即可 例::SYSTEM.CURRENT_DATETIME判断数据块的项是否为空IF :BlockName.Item1 is null THEN message(‘Item1 为空’); END IF; 这个和一般的编程语言使用字符串比较很不一致,但从 PL/SQL 的语句来看,却也是正常的。信息提示框之基本用法1、message Usage:message('提示信息'); Effect:在 FORMS 左下角会出现这个提示信息。 2、fnd_message 用法大全 2.1 FND_Message.Debug Usage::fnd_message.debug('提示信息'); Effect:会直接弹出一个对话框,与 vb 中的 msgbox(&提示信息&)类似。 2.2、fnd_message.question . Usage: ----------------------------------------------------------------------------declare v_ begin FND_MESSAGE.SET_STRING('确要执行此操作吗?'); v_num := FND_MESSAGE.QUESTION('否', '是',NULL, 1,2); if v_num=2 then fnd_message.debug('选择了是'); elsif v_num=1 then14 Author:JarWang(王重东)Email: QQ:fnd_message.debug('选择了否'); --------------------------------------------------------------------------------Effect: Effect:会直接弹出一个选择框,与 vb 中的 msgbox(&提示信息&,vbokcancel)类似。 2.3、FND_MESSAGE.show 这是一个 Procedure,把信息以最基本的方式显示给用户,和 FND_MESSAGE.DEBUG 一样的效 果。但分成了两步来写。 begin fnd_message.set_string('show a string!); fnd_message.2.4、FND_MESSAGE.hint 这是一个 Procedure 这种方式不会弹出对话框给用户,而是显示在左下脚的状态栏上面。2.5、FND_MESSAGE.error 这是一个 Procedure 以 Error 信息的方式显示给用户用代码控制 ITEM 属性1、SET_ITEM_PROPERTY 和 SET_ITEM_INSTANCE_PROPERTY 区别: 如果是控制单行记录或者多行记录中的全部记录:SET_ITEM_PROPERTY 如果是控制多行记录中的单一行记录:SET_ITEM_INSTANCE_PROPERTY 理解它们的最好区别就是亲自动手写一例子。 ①控制数据块 T_TEST(多条记录)的 ITEM 的某一条记录是否可更改。 在 post-query 触发中加入:SET_ITEM_INSTANCE_PROPERTY(‘T_TEST.TID’15 Author:JarWang(王重东)Email: QQ:SET_ITEM_INSTANCE_PROPERTY('T_TEST.TID',CURRENT_RECORD,INSERT_ALLOWED,PROPERTY _FALSE);Effect:②控制数据块 T_TEST(多条记录)的单个 ITEM 的全部记录是否可更改。SET_ITEM_PROPERTY('T_TEST.TID',ENABLED,PROPERTY_FALSE);--ITEM不可获得焦点或:SET_ITEM_PROPERTY('T_TEST.TID’,INSERT_ALLOWED,PROPERTY_FALSE);-- ITEM可以获得焦点 SET_ITEM_PROPERTY('T_TEST.TID',UPDATE_ALLOWED,PROPERTY_FALSE);提示: 如果此时使用 SET_ITEM_INSTANCE_PROPERTY 进行更改可用状态,必须先使用 SET_ITEM_PROPERTY 改 回可写属性,之后方可使用 SET_ITEM_INSTANCE_PROPERTY。 Effect:③控制数据块某个 ITEM 只允许 insert,不允许 delete.在 when-new-form-instance 触发器中加入--先将数据块设为不可删除 set_block_property('T_TEST ',delete_allowed,property_false); --然后对ITEM设为不可update set_item_property(' T_TEST .TID',update_allowed,property_false); 2、用代码控制 ITEM 的可见性 SET_ITEM_PROPERTY('CONTROL.ITEM1', ENABLED, PROPERTY_FALSE); 3、用代码控制 ITEM 必填 Set_Item_Property(‘CONTROL.ITEM1’,REQUIRED,Property_True); 4、用代码控制 ITEM 不可更新 Set_Item_Property(' CONTROL.ITEM1',INSERT_ALLOWED ,Property_false); Set_Item_Property(' CONTROL.ITEM1',UPDATE_ALLOWED ,Property_false); 提示:与 enable 属性最大的区别就是该 ITEM 框是否允许获得焦点。16 Author:JarWang(王重东)Email: QQ:用代码控制 ITEM 的焦点转移此功能,如果不使用代码。可以直接的 block 中拖动 ITEM 的顺序,从而达到 ITEM 获取焦点的顺序。 但如果想做一些特殊的控制,就种方法就办不到了。例:有两个 ITEM,ITEM1 输入省份,ITEM2 输入市 级。在省份 ITEM 为空时,市级 ITEM 是不允许输入了。 在 ITEM2 的的 WHEN-NEW-ITEM-INSTANCE 加入if :block.item1 is null then fnd_message.debug('年度不能为空'); Go_Item(‘block.item1');用代码控制 WINDOW 属性在 pre-form 触发器下,加入:BEGIN SET_WINDOW_PROPERTY('MAIN_WINDOW',TITLE,'HEK_工单自动生成'); --设置标题 END;判断当前 FORM 的状态判断当前 FORM 的状态,如:修改、新增、查询状态。 :SYSTEM.Form_Status 返回三种值:CHANGED、NEW、QUERY。在 when-new-record-instance 控制 BLOCK 的可用状态这个触发器很好用,例如:可以根据主块的某个项的值,来控制子块是否可操作。Begin If :blockname.test = ‘Y’ thenset_block_property('blockname',DELETE_ALLOWED,PROPERTY_FALSE); set_block_property('blockname',INSERT_ALLOWED,PROPERTY_FALSE); set_block_property('blockname',UPDATE_ALLOWED,PROPERTY_FALSE);17 Author:JarWang(王重东)Email: QQ:实现将 LOV 可以自行录入内容在 WHEN-NEW-ITEM-INSTANCE 触发器加入begin set_item_property('block.item1', VALIDATE_FROM_LIST, property_false);在 FORMS 调用 WEB 页面web.show_document('.cn','_blank'); 第二参数为页面的加载方式,有四种选择。 _SELF _PARENT _TOP _BLANK Effect:自己可以去 show 一下,印象会比较深。Name_In()\COPY()函数1、Name_In()函数有点奇怪,丢进去是字符串,返回也是字符串。Oracle 官方文档说是为了实现 indirect reference。 例: IF :emp.ename = 'smith' -- direct reference IF NAME_IN('emp.ename') = 'smith' -- indirect reference 另 外 : Name_In()可 以 用 来 间 接 引 用 一 些 系 统 函 数 。 例 : var t_form varchar2(50):=Name_In( ‘system.current_form’); 2、Copy()函数呢?也是一样,也是为了实现 indirect reference。 例: :emp.ename := 'smith'; -- direct reference Copy('smith','emp.ename'); -- indirect reference 3、后来在 ITPUB 上面看到,说此两个函数是为了实现类似于 C++中宏定义。 3.1 NAME_IN 实现宏定义的例子 FUNCTION FUN_JF (PRE_BLOCK_NAME IN VARCHAR) RETURN BOOLEAN IS BEGIN if name_in(pre_block_name'sj.dwjtc')&name_in(pre_block_name'yj.dwjtc') then message(' 测试!'); END; -- PRE_BLOCK_NAME 是形参,实际调用时,通过 Name_in()函数来实现变量宏替换成 FORMS.ITEM。18 Author:JarWang(王重东)Email: QQ:3.2 COPY 实现宏定义的例子: BEGIN DELCATE strItemName varchar2(20); BEGIN for I in 1 …6 loop strItemName:=':b.l&to_char(i); copy(null,strItemName); --strItemName 由变量宏替换成 Forms 中 Item。 END; 4、通过上面两个例子,应该可以明白 indirect reference 与 direct reference 的区别。但我个人觉得 C++的宏 定义很少这样作用,一般都是起常量的作用。例:#difned BUFFER 100。而且 ANSI C++推荐使用 const 来代 替宏定义。Forms 数据提交的方式1、commit_form 先针对 form 上面的数据变动进行 commit,然后对于代码中的类似 DML 语句也进行提交; 如果 form 上面的数据变动和代码中的数据变动有冲突,最后以 FORM 上的为准。 适用:一般来在直接修改 Form 上的数据时,就使用 commit_form。 2、commit 对 form 和数据库进行提交。如果 form 上面的数据和代码中的数据变动有冲突,最后以 FORM 上的 为准。 适用:一般来在直接使用 DML 代码修改数据时,就使用 commit。 3、do_key('commit_form') 会首先寻找 form 下的 triggers 中的 KEY-COMMIT 这个 trigger, 并执行 KEY-COMMIT 中所写的代码。 如果没有 KEY-COMMIT 这个 trigger,则会针对 form 和代码一起提交。 如果 form 上面的数据变动和代码中的数据变动有冲突,最后以界面上的为准。 适用:只是更改了一下代码执行的任先顺序,没有什么实质区别。 4、forms_ddl('commit') 只针对代码中的 update,insert,delete 语句进行提交。如果 form 上面的数据有变动,是不会提交的。 适用:一般不用。在一个 FORM 中调用不同的 WINDOW1、基础概念: ① 一个 FORM 是可以包含多个 WINDOW,一个 WINDOW 可以切换不同的 CANVAS。 ②对于包含有多个 WINDOW 的 FORM,FORM 的“第一个导航块”属性,决定了首先打开的 WINDOW。③另外在 EBS 开发中,template 模板中 FORM-LEVEL 的 PRE-FORM 触发器,会有如下代码: app_standard.event('PRE-FORM');19 Author:JarWang(王重东)Email: QQ:app_window.set_window_position('MAIN_W', 'FIRST_WINDOW'); 上述代码也会决定,加载 FORM 时首先要打开的 WINDOW 2、FORM 调用 WINDOW 的例子: 对于包含有多个 WINDOW 的 FORM,在已打开的 WINDOW 上,通过按钮打开另一个 WINDOW。 BEGIN SHOW_WINDOW('Test_W',2,2); SET_WINDOW_PROPERTY('Test_W',TITLE,'标题'); END; Effect:3.错误: 关闭窗口时出现以下提示解决:在该画布上必须要有一个可以导航的 item。该 ITEM 必须满足以下其中一个条件: 1.该 item 是可用的,并且该 ITEM 所属的块必须是数据块。 2.该 item 是失效的,即 enabed 为 property_false。Form 假死锁问题之初步解决1、错误提示:2、原理知识: 2.1 当我们在 Forms 中,试图更改 block 中数据的时候,Forms 先发出一个对该行数据的 select ... for update nowait 查询,希望锁定该行(该锁是 ORACLE 行级 X 锁) 。如果不能锁定,Forms 提示 Could not reserve records (2 trys). Keep trying?。 如果用户选择 No, Forms 报告 FRM-40510 错误: ORACLE error: unable to reserve record for update or delete。 2.2 block 加锁的模式。20 Author:JarWang(王重东)Email: QQ:block 的锁定模式如果为 automatic 或 immediate,会在修改记录时 Forms 会立即锁定数据库记录;如 果设为 delayed,在保存时 Forms 才尝试锁定记录。也就是说这个属性不管如何设置,都不会影响锁的 模式,有影响的只是什么时候加锁而已。 2.4 上面已经说过了,Forms 在更数据行时,会先对该数据行加行级 X 锁。这个是 Oracle 写死在 Forms 中的, 我们无法手工修改。 你想不加锁也不行! Oracle 够野蛮吧! ^_^。 不要拿 Oracle 推荐的 transaction 来压我,要明白这个世界上,不是全部的业务应用都需要严格的 transaction。 2.5 即使前面的查询锁定步骤成功,Forms 还要比较查询结果和当前行的值是否一致。如果两者不完全 相同,Forms 抛出 FRM-40654(记录已经被另一个用户更新,重新查询以查看修改)错误。这么做主 要是为了防止 lost update 的情形,不让用户根据过时的数据来做出修改。这一点请认真理解哦? 3、解决方法: 3.1 避免在 TRIGGER 中直接使用 UPDATE 语句,这样会造成 Forms 上的数据与 Oracle 数据库的数据不 一致,从而造成 FRM-40654 的错误。 3.2 要是问题都是由方法 3.1 造成的,那么它就不是问题了。 3.2.1 下面细讲造成这次造成 Form 假死锁的根本原因。被锁的记录-订单编号为 :3.2.2 注意认真查看这条记录,我们注意到 3967.8 这个字段。^_^,至于为什么会注意到这个字段。我 折腾了一周多,并且在 ITPUB 上反复认真学习 FORM 底层数据操作的原理,再加 N*N 次方 TEST, 最后才锁定这个字段。3967.8 是“供方承担”的金额字段。经查数据字典又得知数据库字段名为 “supply_pay” 3.2.3 我们直接从数据库 SELECT 这个记录出来看看。select hm.oe_head_number,hm.supply_pay from hek_ods_th_fee_m hm where hm.oe_head_number=''看清楚了吗?supply_pay 数据库的值为 ,而 FORM 界面上的值却为 3967.8。也就是说 FORM 自动帮我们四舍五入了。这样我们在 FORMS 上 MODIFY 这条记录时,FORM 就会判断 3967.8 &&,从而报 FRM-40654 的错误。而我们呢?却被误导一直在数据库锁方面找问题。21 Author:JarWang(王重东)Email: QQ:于是,我们总结出,可恶的 ORACLE 自作聪明,帮我们四舍五入了。可是我们真需要四舍五入吗? 就算是要,自已加个 ROUND 不就得了吗?这不能不说是 FORMS 一个 BUG!这也再次提醒我们不能 对 ORACLE 太崇拜了哦?FORM 死锁解决关于在 Form 死锁的产生的原因,有很多种。但主要的是主外键导致,如:允许修改主键的值,外键 未加索引等。例如:在 Form 修改任何一笔记录,即使只修改了一列。Form 也会生成诸如 update t set c =:x1,c2=x2….这样的语句,也就是说,只要修改了一列,但 Form 就会提交修改全部的列,即使其他列并 未修改。 下面这个属性可以设置只更新修改列。这个属性很好用,但很多开发人员并不知道。FORM6i 引入 JAVA 类看到 FORM 中有一个导入 JAVA 类的菜单,就特亲切。^_^,至少不会让我学的 JAVA 知识白费。事实 上 ORACLE 很多产品都是要么是用 JAVA 开发,要么提供了 JAVA 编程接口。所以 JAVA 程序员转到 ORACLE 阵容,还是比较容易的。 1. 安装 JDK,FORM6i 最好安装 1.4 的版本,太高版本怕支持不了,比如泛型类。 2. 设置环境变量。 2.1 首先设置 JAVA 基本环境变量。 JAVA_HOME:C:\j2sdk1.4.2_17 Classpath:C:\j2sdk1.4.2_17\lib\tools. Path:C:\j2sdk1.4.2_17\ 2.2 设置 FORM 有关 JAVA 的环境变量。 Classpath: .; C:\orant\TOOLS\COMMON60\JAVA\IMPORTER.JAR;C:\orant\TOOLS\COMMON60\JAVA Path::C:\Program Files\Java\j2re1.4.2_17\C:\j2sdk1.4.2_17\jre\bin\client22 Author:JarWang(王重东)Email: QQ:3.引入 JAVA 类。 3.1 首先,写一个 Test 的 JAVA 类。然后将这个类的目录加入 Classpath 环境变量中。 Classpath:D:\JAVA_FORM\Socket\ 3.2 导入类。导入成功后,FORMS 会将 JAVA 类转成 PL/SQL 包。 3.3 调用 Test 类。declare obj ORA_JAVA.JOBJECT;a varchar2(50); begin obj := Test.new(); a:=TEST.GETTEST(obj); message(a);FORMS 之列表项动态赋值1.将数据块 d_test 的 l_test 项 ITEM TYPE 修改为 LIST、Data Type 修改为 Char。 2.在 when-new-form-instance 触发器中加入。 2.1 实现 LIST 的值来源为固定的值declare list_id I begin list_id := Find_Item(' d_test.l_test '); Clear_List(list_id); Add_List_Element(list_id,1,'批',0); Add_List_Element(list_id,2,'固定计划单',11);2.2 实现 LIST 的值来源为数据表23 Author:JarWang(王重东)Email: QQ:declare rg_name_test varchar2(40) :='test_name'; v_sql_test varchar2(300); rg_id_ v_ begin clear_list('d_test.l_test'); rg_id_test := find_group(rg_name_test); if id_null(rg_id_test) then --记录组要求有两个为varchar2的列 v_sql_test := ' select hname,hmark from hek_test_headers'; rg_id_test := create_group_from_query(rg_name_test,v_sql_test); v_status := populate_group(rg_id_test); populate_list(' d_test.l_test ', rg_id_test);如果报错:FRM-41337 错误。可能是 LIST 的数据类型与查询记录组的类别不同。FORMS 之 LOV 动态赋给记录组1.在数据块 d_test,增加一文本项 l_test、LOV 项 lov_test、两个记录组 Rec_test1、Rec_test2。 2.分别给给记录组 Rec_test1、Rec_test2 赋 SQL 语句,并将项 Lov_test 的记录组设成 Rec_test1。 3.在 WHEN-BUTTON-PRESS 触发器中加入Declare Lov_id LOV; Begin Lov_id := Find_Lov('lov_test'); if Get_Lov_Property(Lov_id,Group_Name)=' Rec_test1' then Set_Lov_Property(kpi_lov_xsbb,Group_Name,' Rec_test2'); E24 Author:JarWang(王重东)Email: QQ:屏蔽 FORM 系统提示信息1.1 直接将 SYSTEM.MESSAGE_LEVEL 设成 25,这样大于 25 的信息提示就不会提示了。Declare t_l number := :SYSTEM.MESSAGE_LEVEL; Begin :SYSTEM.MESSAGE_LEVEL :=25; :SYSTEM.MESSAGE_LEVEL := t_l; E1.2 上述方法只适用于小于 25 的信息提示,无法屏蔽错误提示屏蔽错误提示可以 FORM 的 ON-ERROR 或 ON-MESSAGE 中加入拦截代码(不提倡屏蔽错误提示。)。declare t varchar2(10) := error_ begin if (error_code=40202 or error_code=40401) or t='FRM' then NULL;FORM 之间的调用ORACLE FORM 提供多种方法来实现不同 FORM 之间的调用。 1.CALL_FORM 或 OPEN_FORM 这种方法比较直观,但此种方法需要给出 FORM 的详细路径。如: call_form('/data/deve/deveappl/au/11.5.0/forms/ZHS/HEK_DISCOUNT_PERIOD_NEW.fmx'); 其中:call_form 与 open_form 的区别:open_form 可以保留原表单。 2. APP_NAVIGATE.EXECUTE 或 FND_FUNCTION.EXECUTE 例:APP_NAVIGATE.EXECUTE('HEK_DISCOUNT_PERIOD_NEW', 'Y', 'Y', null); 其中 APP_NAVIGATE.EXECUTE 与 FND_FUNCTION.EXECUTE 的区别: APP_NAVIGATE.EXECUTE 只打一个 FORM,而 FND_FUNCTION.EXECUTE 调用多少次,就打开多少 个。Tree-层次树之使用25 Author:JarWang(王重东)Email: QQ:遍历数据块go_block('BLOCKNAME'); first_ IF :SYSTEM.block_status && 'NEW ' THEN Loop if :system.last_record = 'TRUE' else next_LOV 动态确保从块记录唯一所谓的动态确保从块记录唯一,就是指在从块记录表实现类似 unique key 的作用。那么为什么不直接 使用 unique key。这是因为 unique key 只能实现整张表的唯一性,而我们在这要实现的功能是从块与主块 关联时,该字段才是唯一的。如:一张采购单可以有多个 ITEM,但一张采购单不允许出现相同的 ITEM。 下边只大概说明一下程序的思路。FORM 的主从关系开发就省略了吧。 1.创建一个 Oracle 临时表,用来 FORM 尚未 COMMIT 时的临时 ITEM。 注:这边最好 Oracle 临时表,这样没有并发处理的压力,也不会造成死锁。 create GLOBAL temporary table HEK_TEMP( item_id int ) ON COMMIT DELETE ROWS 2.修改 LOV 记录组的 SQL 语句: 修改前:select ITEM_NO, ITEM_DESC1, ITEM_UM, iim.ITEM_IDfrom apps.IC_ITEM_MST_VL iim修改后:select ITEM_NO, ITEM_DESC1, ITEM_UM, iim.ITEM_ID from apps.IC_ITEM_MST_VL iim where not exists (select lt.item_id from HEK_DISCOUNT_ITEM_LINES_TEMP lt where lt.item_id =iim.item_id)3.在 FORM 的从块中添加两个触发器。 WHEN-VALIDATE-RECORD 加入: if :block2.item_id is not null then insert into HEK_TEMP (item_id)values(:block2.item_id); WHEN-REMOVE-RECORD 加入: if :block2.item_id is not null then delete from HEK_TEMP t where t.item_id =:block2.item_id:26 Author:JarWang(王重东)Email: QQ: 5.实现效果:说明:尽管尚未 commit,但
仍不能输入两次。Form 实现复制上条记录此功能就是要实现,同时按下 shift+F6 自动复制上条记录。在数据块的 KEY-DUPREC 触发器中加入begin duplicate_效果如下:控制删除条件的触发器在相应数据块的 KEY_DELREC 加入条件控制参数。if :parameter.P_APPROVE_FLAG = 'Y' then fnd_message.debug('您不能删除此记录,只能由录入员删除。'); raise form_trigger_ end IF;实现进度条Declare27 Author:JarWang(王重东)Email: QQ:V_all_count number :=10000; V_current_count number:=0 Begin For v_current_count in 1..10000 Loop APP_WINDOW.PROGRESS(V_current_count /v_all_count); E E效果如下:Form 实现唯一性检查本文所谓的唯一性检查指:组合主键或组合唯一键的检查。当然,如果是新建的表,我们可以通过添加唯 一索引来实现。 例:针对表 TABLE1 的 c1、c2、c3 列建唯一索引键。alter table TABLE1 add constraint HEK_UNIUE unique(C1,C2,C3)但上述方法对于已存在的表,并且 C1、C2、C3 列已经存在冗余数据,就无能为力啦。事实在 FORM 中解 决此问题,也是很简单。只有些开发人员偏要将简单的问题复杂化。 解决方法: 在 post-insert、post-update 的 trigger 加入判断代码:declare l_28 Author:JarWang(王重东)Email: QQ:begin select count(*) into l_cou if l_cou & 1 then fnd_message.debug('此数据存在冗余'||:hek_ods_th_price_m_v.price_name); raise form_trigger_ from TABLE1 where c1=:block.c1 and c2= :block.c2 and c3=:block.c3Oracle Report 基础前言 Oracle 的东西总是要“标新立异” ,report 也不列外,非得搞个什么循环框、固定框之类专有概念。外 面大多数报表工具,如 crystal report、Java Birt、VB ActiveReport 等报表工具,其基本概念是一致的。而 Oracle Report 就不一样了。什么循环框、固定框,不就是几 group 么?好像换个概念,技术含量就比较高 似得?还有 Report 的撤销重做功能,居然只能有一次。Faint!Report 页面设置数据模型、固定框、循环框1.0 数据模型与循环框的层次29 Author:JarWang(王重东)Email: QQ:1.1 布局原则 一般布局方法是先画固定框,然后在其内套入:1.表头固定框,2.表数据源循环框。最外层的固定框属性设置:注:最外层固定框的“打印对象在”必须设置为“第一页” 。 表头固定框属性设置:注:表头的“打印对象在”必须设置为“全部页” 。 表数据源属性设置:30 Author:JarWang(王重东)Email: QQ:1.2 实现自动分页。 当记录总数不只一页时,要实现自动分页,必须将最外层的固定框或循环框“打印对象在”设置为“第 一页” 。实现记录汇总行动态伸缩查询视图无数据如果确认 SQL 语句确有数据,则有可能是 OU 的设置的问题。 在报表的 Before Parameter Form 触发器加入初始化条件。 function BeforePForm return boolean is begin APPS.FND_GLOBAL.apps_initialize( user_id =&APPS.FND_GLOBAL.user_id, resp_id =&APPS.FND_GLOBAL.resp_id, resp_appl_id =&APPS.FND_GLOBAL.resp_appl_id ); return (TRUE);31 Author:JarWang(王重东)Email: QQ:Report 数据域Oracle Report 引用数据模型的数据源,有二种方式。 1.较常规的做法。直接使用工具栏上的“域”标签,然后设置相应数据源 2.使用“文本”标签,然后用“&”进行引用。 3.在 PL/SQL 中引用报表域文本的值,只需在 PL/SQL 直接引用域对应源字段名称即可(无须加组名) 。Report 汇总项Report 的汇总项比较灵活,在不同的组其汇总规则是可以多变的。这也会隐藏一些不易发现的问题。 比如,下面这个数据源分为三个组。这个数据源大量使用了汇总项,但汇总项的默认汇总规则是基于整个数据源的,也是就说汇总项是基于整 个 REPORT 的。如图所示:这也是会造成错误的原因,因为我们在使用汇总项,会自以认为 REPROT 会帮我们处理好这个汇总规则。 可事实却相反。这个汇总项的“重设于”属性就是汇总规则。显然处于分组的汇总“重设于”应该基于相 应的组。32 Author:JarWang(王重东)Email: QQ:Report 动态条件查询如果一条 SQL 的查询条件是动态的,SQL 语句本身是无法做到这个功能。在 JAVA 中常见的做法进行这字 符串拼接来达到这一功能。在 Report 也差不多,在触发器事件中进行字符串拼接。 1、 增加一个报表用户参数 p_batch_id_char 、p_batch_id_temp 2、 在报表 After Parameter Form 触发器,加入字符串拼接条件 function AfterPForm return boolean is begin if nvl(:p_batch_id_char,'A')='A' then C通过条件,来进行字符串拼接。 :p_batch_id_temp := 'and 1=1' ; else :p_batch_id_temp := 'and to_char(m.fee_batch_id) in ('|| :p_batch_id_char ||')' ; return (TRUE); 3、 在数据模型的 SQL 语句中加入刚才拼接的字符串。 Select * from table_name where &p_batch_id_temp 注:是用“&” ,不是 PL/SQL 中的“||” 。矩阵报表矩阵报表,不要被 Oracle 的概念给忽悠了。其实就是 crystalreport 中是交叉报表。Report 编译出错在本机上可以执行成功,但上传在 EBS 服务器时,执行报错。 错误提示:Spawned Process 15601 REP-0736: 此处存在未编译的程序单元. REP-1247: 报表包含未编译的 PL/SQL. 原因分析:很有可能是程序包、视图、表等对象,没有授权或是失效了。33 Author:JarWang(王重东)Email: QQ:Oracle 数据库基础常用函数 substr 函数Example:SELECT substr('teach',0,3) FROM DUAL Effect: tea Example: SELECT substr('teach',3,3) FROM DUAL Effect: achLpad/Rpad 函数Example: SELECT LPAD('TEACH',4) FROM Effect: teac Example: SELECT LPAD('TEACH',10,'5') Effect: 55555TEACHDUALFROM DUAL日期函数Oracle 的日期函数比较丰富,不象 SQL SERVER 只有 dateadd、datediff 之类。 1.系统时间 SQL:select getdate() value Oracle:select sysdate value from dual 2.前后几日 都支持直接与整数相加减 3.求日期 SQL:select convert(char(10),getdate(),20) value Oracle:select trunc(sysdate) value from dual select to_char(sysdate,'yyyy-mm-dd') value from dual 4.求时间 SQL:select convert(char(8),getdate(),108) value Oracle:select to_char(sysdate,'hh24:mm:ss') value from dual 5.取日期时间的其他部分 SQL:DATEPART 和 DATENAME 函数 (第一个参数决定) Oracle:to_char 函数 第二个参数决定 下表补充说明 SQL 与 ORACLE 在取参数时的区别 年度:year、yy、y、yyyy 季度:quarter 、qq、q 月度:month、mon、mm、m (m 参数 Oracle 无效) 星期:dayofyear (dayofyear 参数 Oracle 无效) 、dy, 日:day、 dd34 Author:JarWang(王重东)Email: QQ:一年中的第几周:week(week 参数 Oracle 无效)、wk(wk 参数 Oracle 无效)、 ww 一周中的第几天:weekday(此参数 Oracle 无效) 、dw(dw 参数 Oracle 无效)、d 时:Hour hh,hh12,hh24 (hh12,hh24 参数 SQL 无效) 分:minute mi, n (n 参数 Oracle 无效) second ss, s (s 参数 Oracle 无效) millisecond ms (ms 参数 Oracle 无效) 6.当月最后一天 SQL:比较烦琐,先求当月的第一天,然后求得下月的第一天,最后减一得到当月最后一天。 Oracle:select LAST_DAY(sysdate) value from dual 7.本星期的某一天(比如星期日) SQL:week 函数 Oracle:SELECT Next_day(sysdate,7) vaule FROM DUAL; 8.字符串转时间 SQL:可以直接转或者 select cast(''as datetime) value O:SELECT To_date(' 22:09:38','yyyy-mm-dd hh24-mi-ss') vaule FROM DUAL; 9.求两日期某一部分的差(比如秒) SQL:select datediff(ss,getdate(),getdate()+12.3) value Oracle:直接用两个日期相减(比如 d1-d2=12.3) SELECT (d1-d2)*24*60*60 vaule FROM DUAL; 10.根据差值求新的日期(比如分钟) SQL:select dateadd(mi,8,getdate()) value Oracle:SELECT sysdate+8/60/24 vaule FROM DUAL; 11.当月第一天 SQL:select dateadd(getdate,-day) O: select trunc(sysdate,'mm')随机取前 10 条不同的记录Oracle 有提供一个函数来实现取随机数:DBMS_RANDOM SELECT DBMS_RANDOM.VALUE FROM DUAL; 返回 0--1 之间的随机数,因为 DBMS_RANDOM 是默认使用时钟作为种子,来实现取随机数的。select * from(select * from hek_test_tb order by dbms_random.value(1,10)) where rownum&10TRUNC 函数Oracle 与 SQL SERVER 在日期比较方面有重大区别。 例:含有日期+时间的字段 BEGINDATE 与仅含有日期的字段在比较时 ENDDATE。 SQL SERVER:BEGINDATE&=ENDDATE ORACLE:TRUNC(BEGINDATE,’DD’)&=ENDDATE ORACLE 必须先截断时间,然后再进行比较。如果没有这样做,这将会是一个巨大的 BUG。35 Author:JarWang(王重东)Email: QQ:修改表的一些常用语法添加列:alter table hek_test_headers add col_ 修改列:alter table hek_test_lines modify litem varchar(40) 删除列:alter table hek_test_lines drop columns col_ 重命名列:alter table hek_test_lines rename column col_test to col_test2; 添加主键:alter table HEK_TEST_LINES add constraint pk_test primary key (LINEID); 添 加 外 键 : alter table hek_test_lines add constraint fk_test foreign key(hid)hek_test_headers(hid)references失效主键:alter 失效外键:alter 删除主键:alter 删除外键:altertable hek_test_lines disable constraint pk_ table hek_test_lines disable constraint fk_ table hek_test_lines drop constraint pk_ table HEK_TEST_LINES drop constraint fk_舍入函数三个舍入函数:round()、floor()、ceil() Round():实现四舍五入,允许设置保留的位数,这个也最常用的四舍五入函数。 Floor():实现取整。一般的程序语言是整数除以整数,返回的仍是整数。PL/SQL 想得比较多。 Ceil():实现近似值。Ceil 会直接近似取整,如果想保留小数,就要自己动手写个函数了。select 9/4 select CEIL(9/4)select round(9/4,0)实现类似 BREAK 语句在没有 LOOP…END LOOP 时,是不能使用 EXIT 的。但可以通过 GOTO 语句实现。 begin t:=&t; DBMS_OUTPUT.PUT_LINE('T='||t); if t=1 then DBMS_OUTPUT.PUT_LINE('Goto!'); goto GOTOS; else DBMS_OUTPUT.PUT_LINE('NO Goto!'); goto NoG &&GOTOS&& for i in 1..10 loop DBMS_OUTPUT.put_line('i='||i); &&NoGoto&&36 Author:JarWang(王重东)NULL;Email: QQ:Oracle 定时器ORACLE 9i 及 其 以 前 版 本 , 都 是 使 用 DBMS_JOB 来 实 现 任 务 调 度 。 10g 官 方 推 荐 使 用 DBMS_SCHEDULER。 1.1 JOB 创建 1.1.1 先创建一个存储过程 create or replace procedure usp_test_pr is BEGIN update t_test set tname='test' where tid =110; END; 1.1.2 在 pl/sql developer 中创建 job declare v_ begin sys.dbms_job.submit(job=&v_job, what =& 'usp_test_', next_date =& to_date('22-12-2008', 'dd-mm-yyyy'), interval =& 'sysdate+1/1440'); --每隔一分钟执行一次 1.2 删除 JOB exec DBMS_JOB.remove(JOB=&&job_number);--输入 job_ 1.3 查询所有的 JOB select * from dba_jobs j order by j.JOB descOver 分析查询Over 函数,其实也可以转换成嵌套查询来实现。 准备测试数据 create table t_test( tid int, tname varchar2(20), tsalary number(8,2), tdeptno int, primary key(tid) ); begin insert into t_test values(1,'小王',); insert into t_test values(2,'小张',4200,3);37 Author:JarWang(王重东)Email: QQ:insert into t_test values(3,'小 K',3000,3); insert into t_test values(4,'小 Q',); insert into t_test values(5,'小 T',); insert into t_test values(6,'小丁',3000,5); insert into t_test values(7,'小李',3000,5); insert into t_test values(8,'小 KK',3000,5); SELECT * FROM T_TEST; ----------------------------------------------------------------------------------------------1 1 小王
--求员工工资占该部门总工资额的比率 select tname, tsalary,tsalary/sum(tsalary)over(partition by tdeptno order by tdeptno) per from t_test --partition by 实现记录分组,order by 实现组内排序后连接求和 ------------------------------------------------------------------------------------------1 小王 .03 2 小张 .483 3 小K .488 4 小Q .684 5 小T .316 6 小丁 .333 7 小李 .333 8 小 KK .333 --当然也可以不使用 over,实现同样的效果 select a.tname,a.tsalary,a.tsalary/b.ttl per,a.tdeptno from t_test a,(select tdeptno,sum(tsalary) ttl from t_test group by tdeptno) b where a.tdeptno=b.tdeptno ------------------------------------------------------------------------------------------------------1 小王 .03 3 2 小张 .483 3 3 小K .488 3 4 小Q .684 4 5 小T .316 4 6 小丁 .333 5 7 小李 .333 5 8 小 KK .333 5 --求工资排名 SELECT ROWNUM ser ,TNAME,TSALARY,TDEPTNO38 Author:JarWang(王重东)Email: QQ:FROM(SELECT * FROM t_test order by tsalary desc) --注意这样求出的排名,有点问题。就是工资一样的没有处于第一排名,这是由 rownum 的性质决定。 ---------------------------------------------------------------------------------------------------1 小Q
--要实现真正的排名,应该使用 rank 或者 dense_rank -- rank()和 dense_rank()的区别是: --rank()是跳跃排序,有两个第二名时接下来就是第四名 --dense_rank()l 是连续排序,有两个第二名时仍然跟着第三名 select dense_rank()over(order by tsalary desc) ser,tname,tsalary,tdeptno from t_test -----------------------------------------------------------------------1 2 3 4 4 4 4 5 小Q 小王 小张 小K 小 KK 小李 小丁 小T 0.21 0.00 0.00 0.50 4 3 3 3 5 5 5 4--上面是工资在全体部门的排名,如果要求部门排名的话。 select tname,tsalary,tdeptno,dense_rank()over(partition by tdeptno order by tsalary desc ) ser from t_test -----------------------------------------------------------------------1 小王
1 --直接实现行汇总 select tname,tsalary,tdeptno,sum(tsalary)over(partition by null) ttl from t_test 如下: 1 小王
30721.2139 Author:JarWang(王重东)Email: QQ:4 5 6 7 8小Q 小T 小丁 小李 小 KK0.50 0.00 3000.004 4 5 5 521.21 21.21 30721.21Oracle 层次树查询Oracle 层次树是通过 Connect by &Prior& [条件] Start with [条件] 来实现。这一功能非常好用,比如 ERP 中 的 BOM、HR 中的组织架构,就算是这类的典型应用了。不过,Oracle EBS11i 中好象没实现,BOM 也没 有使用树这种组件。 下面就做一个简单的 MRP 试算过程,来说明层次树的应用。 1.1 建一个简单 BOM 表。 create table hek_bom( master_id varchar2(20), master_name varchar2(50), sub_id varchar(20), sub_name varchar(20) ) 1.2 放入测试数据。 begin insert into hek_bom values('0001','V1 卡车','10001','V1 发动机'); insert into hek_bom values('0001','V1 卡车','10002','V1 车架'); insert into hek_bom values('0001','V1 卡车','10003','V1 车轮'); insert into hek_bom values('0002','V2 卡车','10001','V1 发动机'); insert into hek_bom values('0002','V2 卡车','10002','V1 车轮'); insert into hek_bom values('0002','V2 卡车','10004','V2 车架'); insert into hek_bom values('0003','V3 卡车','10004','V1 发动机'); insert into hek_bom values('0004','V4 卡车','10005','V2 发动机'); insert into hek_bom values('10001','V1 发动机','10006','V1 活塞'); insert into hek_bom values('10001','V1 发动机','10007','V1 火花器'); insert into hek_bom values('10007','V1 活塞','10008','V1 橡胶片'); insert into hek_bom values('10007','V1 活塞','10009','V1 螺丝'); 1.3 查询一下明细: select t.* from hek_bom t for update ------------------------ 1 0001 V1 卡车 10001 V1 发动机 2 0001 V1 卡车 10002 V1 车架 3 0001 V1 卡车 10003 V1 车轮 4 0002 V2 卡车 10001 V1 发动机 5 0002 V2 卡车 10002 V1 车轮 6 0002 V2 卡车 10004 V2 车架40 Author:JarWang(王重东)Email: QQ:7 8 9 10 11 120003 V3 卡车 10004 V1 发动机 0004 V4 卡车 10005 V2 发动机 10001 V1 发动机 10006 V1 活塞 10001 V1 发动机 10007 V1 火花器 10006 V1 活塞 10008 V1 橡胶片 10006 V1 活塞 10009 V1 螺丝1.4 问题:求 V1 螺丝料品有哪几层产品用到。 select level,t.* from hek_bom t connect by prior t.master_id=t.sub_id start with t.sub_id='10009' --注意这条 SQL 语名的语法,connect by prior t.master_id=t.sub_id 表示优先从子节点到父节点。 --start with t.sub_id='10009'相当于 where t.sub_id='10009' --------------------------------------------- 1 10006 V1 活塞 10009 V1 螺丝 2 10001 V1 发动机 10006 V1 活塞 3 0001 V1 卡车 10001 V1 发动机 4 0002 V2 卡车 10001 V1 发动机 1.5 问题:求:V1 卡车的 BOM 结构: select level,t.* from hek_bom t connect by prior t.sub_id=t.master_id start with t.master_name='V1 卡车' --connect by prior t.sub_id=t.master_id 表示优先从父节点查询到子节点。 --------------------------------------------------------------------------------------------1 0001 V1 卡车 10001 V1 发动机 2 10001 V1 发动机 10006 V1 活塞 3 10006 V1 活塞 10008 V1 橡胶片 4 10006 V1 活塞 10009 V1 螺丝 5 10001 V1 发动机 10007 V1 火花器 6 0001 V1 卡车 10002 V1 车架 7 0001 V1 卡车 10003 V1 车轮 DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD 通过这两个例子,已经可以很形象地说明 connect by 的典型应用了。Merge into 应用Merge into 适用于数据量非常大的表,做 insert\update 动作。比起 insert into select 效率上要更高些。当然 merge into 也提供了 when matched then 的条件规范。 基本语法:Truncate table1.Truncate table 与 delete * from table 作用是一样,都是删除表中全部数据。但 Delete 是与事务关联的,所 以 Truncate table 会快很多。另外 Oracle 书上说,truncate 会把 highwatermark 回归至 0 ,当下一次再插 入新资料时就会快一些。 需要注意的是 Truncate table 不是 PL/SQL 直接使用,必须使用动态 SQL 来执行,并且 truncate table 是无须 commit 语句的。begin41 Author:JarWang(王重东)Email: QQ:execute immediate 'truncate table hek_table';2.Truncate Table 的权限:必须是表的所有者,或具 drop any table 权限的用户。绑定变量与非绑定变量之比较1、以 insert 20 条记录为测试用例。数据库:Oracle9iR2、Oracle10gR2。操作系统:Linux。 表结构:heap 表,建有主键create table hek_heap ( col1 int , col2 char(30) )绑定变量:declare v_name varchar(10) :='测试数据'; v_ v_num1 v_num2 begin execute immediate 'truncate table hek_index'; dbms_output.put_line('绑定变量测试用例'); v_num1 :=dbms_utility.get_time(); dbms_output.put_line('开始时间:'||to_char(sysdate,'yyyy-mm-dd hh:mm:ss')); for i in 1..200000 loop execut v_num2 :=dbms_utility.get_time(); dbms_output.put_line('结束时间:'||to_char(sysdate,'yyyy-mm-dd hh:mm:ss')); v_num := v_num2-v_num1; dbms_output.put_line('用时:'||v_num||' 毫秒'); 'insert into hek_index values(:x,:y )' using i,v_结果:绑定变量测试用例 开始时间: 11:06:54 结束时间: 11:06:07 用时:1322 毫秒非绑定变量:declare v_name varchar(10) :='测试数据'; v_ v_num1 v_num2 begin42 Author:JarWang(王重东)Email: QQ:execute immediate 'truncate table hek_index'; dbms_output.put_line('非绑定变量测试用例'); v_num1 :=dbms_utility.get_time(); dbms_output.put_line('开始时间:'||to_char(sysdate,'yyyy-mm-dd hh:mm:ss')); for i in 1..200000 loop execut v_num2 :=dbms_utility.get_time(); dbms_output.put_line('结束时间:'||to_char(sysdate,'yyyy-mm-dd hh:mm:ss')); v_num := v_num2-v_num1; dbms_output.put_line('用时:'||v_num||' 毫秒'); 'insert into hek_index values('||i||',''||v_name||'')';结果:非绑定变量测试用例 开始时间: 11:06:19 结束时间: 11:06:39 用时:7917 毫秒静态SQL语句declare v_name varchar(10) :='测试数据'; v_ v_num1 v_num2 begin execute immediate 'truncate table hek_index'; dbms_output.put_line('静态SQL用例'); v_num1 :=dbms_utility.get_time(); dbms_output.put_line('开始时间:'||to_char(sysdate,'yyyy-mm-dd hh:mm:ss')); for i in 1..200000 loop insert into hek_index values(i,v_name); v_num2 :=dbms_utility.get_time(); dbms_output.put_line('结束时间:'||to_char(sysdate,'yyyy-mm-dd hh:mm:ss')); v_num := v_num2-v_num1; dbms_output.put_line('用时:'||v_num||' 毫秒'); 直接书写SQL语句用例 开始时间: 11:06:46 结束时间: 11:06:57 用时:1094 毫秒结论:绑定与不绑定变量在动态SQL时,用时差别非常大。但静态SQL与绑定变量SQL,由于动态SQL的 执行时编译,所以会占有一些编译时间,用时也略大于静态SQL。43 Author:JarWang(王重东)Email: QQ:取不重复的记录行表结构:table ID NAME 110 AA 120 AA 125 BB 126 BB 129 CC 取得如下记录: 110 AA 125 BB 129 CC 如果是 MySQL 实现这个比较简单。因为 MySQL Group By 支持多字段。 Select ID,NAME from TABLE group by NAME 但 Oracle 不支持此用法。 可以做到的,目前只有 Select NAME,MAX(ID) FROM TABLE GROUP BY NAME查询具有相同薪水的职工表结构:create table emp(emp_id int,dept_id int,commission number);测试数据:insert into emp values(1,2,11.22); insert into emp values(2,3,12.22); insert into emp values(3,4,12.22); insert into emp values(4,5,13.22);查询薪水相同的职工:select e.* from emp e, emp m where e.emp_id && m.emp_id mission = m.commission统计 EBS 表数量及 Oracle 概念转到 Oracle ERP 有段时间了,突然被一个问题问倒。Oracle ERP 有多少张表?统计表的数量首先想到数据 字典,可是 select 了半天,发现对一些概念有点乱。特总结如下: 首先,要明白几个 Oracle 核心概念。这些概念 2 年前在读《Oracle8i 初学者指南》中明白了一些,无耐后 来转做 JAVA 开发,这些东西又还给作者了^_^。44 Author:JarWang(王重东)Email: QQ:“解释数据库、表空间、数据文件、表、数据的最好办法是想象一个装满东西的柜子。数据库就是柜子, 柜中的抽屉是表空间,抽屉中的文件夹是数据文件,文件夹中的纸是表,写在纸上的信息就是数据”。 这 是《Oracle8i 初学者指南》关于这些概念的理解。这样理解并没有错,但事实远非如此简单。 1.核心概念:数据库(Scheme)、数据文件、表空间(Tablespace)、表(table)、用户(user)。 1.1 数据库是数据文件、控制文件、日志文件等组成的。属于物理文件的范畴。一个 Scheme 可以多个 Tablespace。对于不同的应用,Oracle 也推荐创建不同的表空间,以提高性能。例:DBA 备份时可以按 表空间进行备份。 1.2 表空间是逻辑文件的范畴,Scheme 是通过 Tablespace 进行管理的。这也是 Oracle 与 SQL SERVER 在设 计理念上的最大区别。一个表空间一般只对应一个数据文件,但也可以有多个数据文件。例:给表空 间增容。 1.3 表也是逻辑文件的范畴。一个表空间可以多张表,一张表一般只能属于一个表空间。当然 Oracle 也有 提供分区表,来实现一张表存放在多个表空间中。 1.4 一张表只能属于一个用户。即用户与表是 1 对多的关系。Oracle 是通过 synonym 来实现不同用户创建 的表进行互访的。 1.5 一个用户通过配额(Quota)可以拥有多个表空间,但只能有一个默认的表空间。 引申一下数据字典的概念,数据字典就是存放 Oracle 数据对象的表。一般是通过数据字典视图来查询,有 三种视图:user_、all_、dba_。 2.查看全部表的数量 select count(*) from dba_tables -C因为有做过大量的二次开发,所以直接这样得到的数量是不准确 的。 3.查看当前用户所有表的数量 select count(*) from all_tables 4.查看当前用户创建表的数量 select count(*) from user_tables 5.ebs11i 对应的表空间是 APPS_TS_TX_DATA,通过对表空间进行表的统计,算是比较准确的。select count(*) from dba_tables dt where dt.tablespace_name='APPS_TS_TX_DATA'得到 EBS 表的数量为“15997” 。Oracle 死锁之解决方法1. 解决 ORA-04021 错误,查看 EBS 死锁的进程。SELECT c.owner ,c.object_name ,c.object_type ,fu.user_name locking_fnd_user_name ,fl.start_time locking_fnd_user_login_time ,vs.module ,vs.machine ,vs.osuser ,vlocked.oracle_username ,vs.SID ,vp.pid45 Author:JarWang(王重东)Email: QQ:,vp.spid AS os_process ,vs.serial# ,vs.status ,vs.saddr ,vs.audsid ,vs.process FROM fnd_logins fl,fnd_user fu,v$locked_object vlocked,v$process vp ,v$session vs,dba_objects c WHERE vs.SID = vlocked.session_id AND vlocked.object_id = c.object_id AND vs.paddr = vp.addr AND vp.spid = fl.process_spid(+) AND vp.pid = fl.pid(+) AND fl.user_id = fu.user_id(+) --AND c.object_name LIKE '%' || UPPER('&tab_name_leaveblank4all') || '%' AND NVL(vs.status ,'XX') != 'KILLED';或者:select b.sid,b.serial#,b.machine,b.terminal,b.program,b.process,b.status from v$lock a , v$session b where a.SID = b.SID2.Kill 掉进行程 alter system kill session 'SID,serial#'; ―SID、serial# 这两个参数,可以从上面的查询结果中找到。PL/SQL 过程调用表示法PL/SQL 过程调用支持两种参数表示方式,一种是位置表示法,如 C、JAVA 都是使用这种方式。第二 种是名称表示法,这个恐怕只有 PL/SQL 使用,当然 PL/SQL 也是从 Ada 那边学来的。 名称表示法示例(注:仅限于过程,名称表示法不适用于函数。切记!):创建存储过程: create or replace procedure test_proc(i_temp number,j_temp number,c_temp varchar) is t varchar(30); begin t := i_temp || '' || j_temp || c_ dbms_output.put_line(t); 调用: begin test_proc(j_temp=&10,i_temp =& 60,c_temp =& 'test');PL/SQL 调用 Java 类作为 JAVA 程序员,对 ORACLE 的 javasource 一直是想找个机会下手的。呵呵!风高月夜,此时正下 手之机。 Oracle 有提供一个叫“外部例程” 来实现与其他编程语言的访问, ORACLE 特别集成了 JAVA。 但 例如:可以将业务逻辑写在 JAVA 类中,通 PL SQL 进行调用,从而实现了业务逻辑层与数据库分离。 1.HelloWorld 例子46 Author:JarWang(王重东)Email: QQ:1.0 创建 java source create or replace and compile java source named JTest as public class JTest { public static String entry(String s,int i) { return &First &+i+& hello&+s; } } 1.1 创建调用 function create or replace function read_string (t in varchar2,i number) return varchar2 is language java name ' JTest.entry(java.lang.String,int) return t'; --注:function 的形参应与调用的 JAVA 类中方法的形参相同 1.2 调用测试 SELECT read_string(' world',10) from dual 注意:在 ORACLE 中,JAVA SOURCE 可以拥有非 static 方法,但 PLSQ/包调用的方法必须是 static 的。 2.再来一个实用一点的例子(JDBC) 2.1 创建 JAVA 类 create or replace and compile java source named testjdbc as import java.io.IOE import java.sql.C import java.sql.DriverM import java.sql.PreparedS import java.sql.ResultS import java.sql.SQLE /** * @author jarwang * @since
* @version xx1.0 */ public class TestJDBC{ public static String queryTable(){ String temp=&&; Connection conn = PreparedStatement pstmt = ResultSet rs = try{ conn = getConn(); pstmt = conn.prepareStatement(&select hname from test &); rs = pstmt.executeQuery(); while(rs.next()){ temp += rs.getString(&hname&);47 Author:JarWang(王重东)Email: QQ:} }catch(Exception ioex){ System.out.println(&failure: &+ioex); }finally{ closeConn(conn,pstmt,rs); } } public static void insertTable(String s){ Connection conn = PreparedStatement pstmt = ResultSet rs = String sql = &insert into test (hname)values('&+s+&')&; try{ conn = getConn(); pstmt = conn.prepareStatement(sql); pstmt.execute(); mit(); }catch(Exception oex){ System.out.println(& has failure: &+oex); try{ conn.rollback(); }catch(Exception ex){ ex.printStackTrace(); } }finally{ try{ pstmt.close(); conn.close(); }catch(Exception ex){ ex.printStackTrace(); } } } public static Connection getConn(){ Connection conn = String user = &&; String pwd = &&; String url = &jdbc:oracle:thin:@ip:sid&; try{ Class.forName(&oracle.jdbc.driver.OracleDriver&); conn = DriverManager.getConnection(url,user,pwd); conn.setAutoCommit(false); System.out.println(& OPEN DATABASE SUCCESS &); }catch(SQLException ex){ System.out.println(& OPEN DATABASE FAILURE: &+ex);48 Author:JarWang(王重东)Email: QQ:}catch(Exception e){ System.out.println(&JDBC CLASS LOADE FAILURE: &+e); } } public static void closeConn(Connection conn,PreparedStatement pstmt,ResultSet rs){ try{ rs.close(); pstmt.close(); conn.close(); }catch(Exception e){ e.printStackTrace(); } } } 2.2 创建 PL/SQL 包 create or replace package TestJDBC is -- Author : JARWANG -- Created :
10:24:51 -- Purpose : TestJDBC procedure insert_table(t varchar2); function query_table return varchar2; end TestJDBC; create or replace package body TestJDBC is procedure insert_table(t varchar2) is language java name 'TestJDBC.insertTable(java.lang.String)'; function query_table return varchar2 is language java name 'TestJDBC.queryTable() return String'; end TestJDBC; 2.3 测试调用 declare t varchar2(3000); begin TestJDBC.insert_table('JDBC 例子'); t := TestJDBC.query_table(); dbms_output.put_line('t='||t); 3.调用含有外部的 jar 的 JAVA 类 3.1 在 ORACLE 中加载 JAR 包。 3.1.1 上传 JAVA 类 上传 jar 包至 ORACLE 服务器。例:/data/test/test.jar 3.1.2 注册 JAVA 类49 Author:JarWang(王重东)Email: QQ:CALL DBMS_JAVA.loadjava('/data/test/test.jar'); 3.1.3 查询是否注册成功 Select OBJECT_NAME, OBJECT_TYPE, STATUS, SYS.DBMS_JAVA.LONGNAME(OBJECT_NAME) LONGNAME, LAST_DDL_TIME, OBJECT_ID, uo.created from sys.user_objects uo where object_type in ('JAVA CLASS', 'JAVA SOURCE', 'JAVA RESOURCE', 'JAVA DATA') order by uo.created desc3.1.4 删 除 注 册 的 JAVA 类CALL dbmPL/SQL 操作 EXCELPL/SQL 操作 EXCEL 有多种方法,但都不理想。比较了一下,还是通过 JAVA 的方法比较适用。 1. 使用 UTL_FILE 包 declare l_file utl_file.file_ BEGIN l_file :=utl_file.fopen('U_FIEL','test1.xls','w'); utl_file.put_line(l_file,'jobs 表导出数据'); utl_file.fflush(l_file); 说明:此方法操作文本尚可,对于 EXCEL 这种 COM 文件并不可行。网络大多数所谓的 PL/SQL 操作 EXCEL, 也是使用 cvs 这种简单的格式。如果要读入稍微复杂点的 EXCLE 模板文件,utl_file 就挂掉了。 2. 使用 OLE2 declare application OLE2.OBJ_TYPE; workbooks OLE2.Obj_T workbook OLE2.Obj_T worksheets OLE2.Obj_T worksheet OLE2.Obj_T args OLE2.List_T cell OLE2.Obj_T begin application:=OLE2.CREATE_OBJ('Excel.Application'); OLE2.Set_Property(application,'Visible','True'); workbooks := OLE2.GET_OBJ_PROPERTY(application,'Workbooks');50 Author:JarWang(王重东)Email: QQ:workbook:=OLE2.INVOKE_OBJ(workbooks,'Add'); worksheets := OLE2.

我要回帖

更多关于 共用媳妇辣文 的文章

 

随机推荐