带有自动值的oracle PL / SQL

时间:2014-06-18 02:27:25

标签: oracle plsql

嗨大家好我有关于计算oracle中一列中的值的问题。

所以我有这张桌子

NAME     PROCESS1    PROCESS2    WEIGHT    TOTAL_WEIGHT
ITEM1    0           0           10
ITEM2    1           1           10
ITEM3    1           1           15

所以我在这里尝试做的是基于PL / SQL中的process1和process2生成total_weight中的值。因为稍后我需要在PHP页面中显示总权重的总和。因此,对于第2项,总重量应为20,而对于第3项,则应为30.我是否应使用程序生成总重量值?我想在用户更改Process1或process2中的值时更新该值。请帮助我,我在这里有点新手。

4 个答案:

答案 0 :(得分:4)

select name, process1, process2, weight, (process1+process2)*weight total_weight
from table

除非我误解了要求,否则我认为没有理由认为PL / SQL必须在这方面发挥作用。

答案 1 :(得分:1)

据我所知,只要进程1或进程2中的值发生更改,就希望更新字段TOTAL_WEIGHT。因此,理想情况下,您必须使用 TRIGGERS

TRIGGERS 用于根据初始事件触发操作。

因此,对于您的情况,初始事件是" Value change of process1 or process2" 预期的行动是" automatic update of total weight field based on changed value。"

但是,根据您的要求,触发器是不必要的, 完全不必要的开销 。因此,不要在表中添加额外的字段,而是使用如下的选择查询,它将在运行时计算值并显示实时值。

SELECT NAME, 
       PROCESS1,
       PROCESS2,
       WEIGHT ,
       (WEIGHT * (PROCESS1 + PROCESS2)) AS TOTAL_WEIGHT
FROM MY_TABLE

输出将是:

NAME   |  PROCESS1  |  PROCESS2  |  WEIGHT   | TOTAL_WEIGHT
------------------------------------------------------------
ITEM1  |  0         |  0         |  10       |  0
ITEM2  |  1         |  1         |  10       |  20
ITEM3  |  1         |  1         |  15       |  30

您可以使用resultSet.getLong("TOTAL_WEIGHT");

之类的内容来使用此TOTAL_WEIGHT

或者,如果您非常擅长使用该字段,则可以修改更新查询以包含

UPDATE MY_TABLE  SET FIELD1=VALUE1, FIELD2=VALUE2, ... ,
TOTAL_WEIGHT = (WEIGHT * (PROCESS1 + PROCESS2))
WHERE SOME_CONDITION;

答案 2 :(得分:1)

如果您使用11g或更高版本,最安全的方法是将TOTAL_WEIGHT设为计算列。然后CREATE TABLE语句将变为类似

CREATE TABLE MY_TABLE
 (PROCESS1      NUMBER,
  PROCESS2      NUMBER,
  WEIGHT        NUMBER,
  TOTAL_WEIGHT  NUMBER GENERATED ALWAYS AS (NVL((PROCESS1+PROCESS2)*WEIGHT, 0)));

通过这种方式,应用程序不需要知道如何计算TOTAL_WEIGHT - 它始终正确完成。

SQLFiddle here

分享并享受。

答案 3 :(得分:1)

在Oracle Table Design中声明VIRTUAL(计算)列

我同意迄今为止所说的大部分内容,并进行了一些额外的阐述。我的起始表设计看起来很相似,但对于某些用例来说也是不准确的,如下所述。

    CREATE TABLE "PROCESSED_PRODUCT_WEIGHT" (
       "PRODUCT_NAME"  VARCHAR2(40) NOT NULL,
       "PROCESS1"      NUMBER,
       "PROCESS2"      NUMBER,
       "WEIGHT"        NUMBER,
       "TOTAL_WEIGHT"  NUMBER GENERATED ALWAYS AS 
                       ((PROCESS1 + PROCESS2)*WEIGHT) VIRTUAL,
       "RECORDED_DATE" DATE,
       CONSTRAINT  "PROCESSED_PRODUCT_WEIGHT_PK" 
          PRIMARY KEY ("PRODUCT_NAME", "RECORDED_DATE")
       )
       /  

以前的建议和假设

表绑定属性属性 @Bob Jarvis使用的表格结构也称为VIRTUAL COLUMN。它运行良好,因为TOTAL_WEIGHT的定义完全取决于同一个表中包含的其他值。

SQL查询关联计算: 另一方面,@Nishanthi Grashia@OldProgrammer都建议修改针对每个执行的SQL查询中的值数据库中。

BOTH 假设产品的每单位质量在生产周期的生命周期内没有变化,情况可能有效。

  

这种假设不灵活的一个例子是产品是否由每单位体积不同质量的单位组成。

     
      
  • 由于OP中未提及,请考虑这种可能性:
  •   
  • 产品ITEM1,ITEM2和ITEM3每单位可变权重。
  •   
  • 它们都是在咖啡包装厂生产的。
  •   
  • 每个项目都可以是一种咖啡豆及其来源。
  •   
  • "流程"可能是bean"治疗"如脱咖啡因,烘烤类型或调味剂。
  •   

"单位"可以是不同尺寸的包装。这意味着包装量会对每个产品单位的质量(称为“#34;重量"”)产生直接影响。

用于识别更改单位尺寸影响的测试用例

每个测试用例都显示虚拟列如何不满足每个产品的单位大小和质量随时间变化的可能性。

Initial Table Population

测试案例一:

Test Case One:  Change Process Quantites for Two Different Item Types

对于2/14/2015的生产观察

测试案例二:

Test Case Two:  No Process Quantities Counted/Incremented

2014年3月14日处理的每单位质量仅增加,因为先前生成的项目数量通过虚拟列定义乘以更大的值而产生的总质量偏差。

测试案例三:

Test Case Three:  Process Quantity and Mass per Unit Changes

数据输出和结果

Result Snapshots for each production period

以上是与所有三个测试用例相关的测试结果。结果值对于创建的用例不正确。他们证明,对于不断变化的权重值,虚拟/计算列公式和方法会得出不正确的结果。

关于替代解决方案的讨论

  1. 触发器方法可用于维护TOTAL_WEIGHT的计算值。当每个组件变化时,增量更改(更新)将附加到当前现有值。

  2. 强制所有DML通过CRUD包中包含的单个DML操作。定义嵌入式SQL语句以强制执行要求的问题是,其他进程及其开发人员需要熟悉您的应用程序中隔离的PHP表单/页面所执行的操作,以便为自己的操作复制它。

  3. 如果担心主表的开销或可能锁定,请考虑引入复合密钥:PRODUCT_NAME + WEIGHT。这涵盖了问题,以便相同产品名称的数量乘以正确的重量,即使重量乘数被修改,已经计算的值也保持不变。

  4.   

    SOMETIMESALWAYSNEVER ...在开发人员的项目圈中都有流行的假设。这种情况发生的可能性有多大?这取决于......如果你是一个咖啡豆包装装,我说这很有可能。

    冠!