to developer2002(开发者2002): 实际上,我的开发中没有并行的操作,所以不用考虑 to Lastdrop(空杯): 第一个问题,我现在有一个sql server下的解决方法,添加一个表C,各字段和A一样,对每个字段作instead of insert 触发,表C始终是一行数据,在插入时对每一个字段的插入值与表C的这行数据进行比较如果插入值小于原有值,则将插入值加上原有值作为这个字段的插入值,否则不变,判断完成后, 用新的inserted表中插入值更新这行数据,同时 select * from inserted into 表A 我对oracle不熟,不知道是否有类似的触发以及inserted表?
如果有表C,第一个问题可以解决,不过oracle的语法和SQL SERVER是有差别的。create or replace trigger test before insert on A for each row declare last_a number; last_b number; last_c number; begin SELECT NVL(MAX(a),0),NVL(MAX(b),0),NVL(MAX(c),0) INTO last_a, last_b, last_c FROM c; if :new.a < last_a then :new.a := :new.a + last_a; end if; if :new.b < last_b then :new.b := :new.b + last_b; end if; if :new.c < last_c then :new.c := :new.c + last_c; end if;
update c set a=:new.a, b=:new.b, c=:new.c; end; /如果你用同样类似的方法,创建一个表D保存最近一次0点的记录,那么也可以在触发器中实现。
to Lastdrop(空杯): 这些语句在哪里执行(sql server里有查询分析器),我用的oracle的可视界面创建,逐行触发,旧值与新值该怎么添? oracle易用性好像不太好,错误提示尽是些问号,你能不能帮我在你那里调试一下,看能不能正常触发 你上面的语句末尾再添加: INSERT INTO A SELECT NVL(MAX(a),0),NVL(MAX(b),0),NVL(MAX(c),0) FROM C THANKS!
1. 一般是通过SQL*Plus执行,有可视界面的也有命令行方式的。首先创建触发器,就是把我的那些语句执行一下,触发器中的新值与旧值不用你来填,当执行插入操作是,要插入的就是新值,通过:new.field_name访问,而当进行update操作时,原来的记录就是旧值,而要更新的值为新值,在进行删除时,只有旧值。2.错误提示尽是些问号是字符集问题,显示的是中文错误提示会出现这种问题。3. 我不知道为什么要加上 INSERT INTO A SELECT NVL(MAX(a),0),NVL(MAX(b),0),NVL(MAX(c),0) FROM C 这个语句,应该是这个语句会触发我上面写的那个触发器。
to tuidler(): 请看看楼主的话 “我现在有一个sql server下的解决方法,添加一个表C,各字段和A一样,对每个字段作instead of insert 触发,表C始终是一行数据,在插入时对每一个字段的插入值与表C的这行数据进行比较如果插入值小于原有值” SELECT NVL(MAX(a),0),NVL(MAX(b),0),NVL(MAX(c),0) INTO last_a, last_b, last_c FROM c; 请注意记录是从表C,而非表A中取得,表C中存放的就是最近一次的记录,之所以用MAX是防止表C中没有记录是执行SELECT INTO语句出错。
Lastdrop(空杯)作法也没错啊,C中始终只有一条记录,就是插入前的上一条记录,不过应该不用取最大值也可以吧! to Lastdrop(空杯):哦,原来我是想用C表起一个过滤的作用,我是直接插入到c表,在C表上判断后再插入A表,和你说的是一个道理,主要是考虑第二个问题还要在A表上建立一个插入的触发器,是不是分开会好一点?
to realdreaming() 1. 当你第一次插入A表时,(当然你现在A表和C表中都有记录)此时C表中没有记录,若此时调用select a,b,c into last_a,last_b,last_c from c,就会报错,所以我们的习惯对SELECT INTO语句即使知道可以取到值,也使用min或MAX之类的函数以保证安全。2.第二个问题,你可以为C表建立触发器,判断插入记录为当天0点时,从A表取出前一天的值进行计算后插入到B表中。这样就不需要建立D表作为中间表了。
to Lastdrop(空杯): 1."在表A的触发器中是不能执行对表A的查询的"这句话确实很关键(在sql server里是可以的) 2.触发器的时间比较以及插入B表时的格式转换该怎么处理(我对oracle的时间函数不了解) 谢谢!
“原来我是想用C表起一个过滤的作用,我是直接插入到c表,在C表上判断后再插入A表,和你说的是一个道理,主要是考虑第二个问题还要在A表上建立一个插入的触发器,是不是分开会好一点?”我觉得因为你总是需要以前的一些信息,所以最好不要为表A建立触发器,就按你说每次都是先对C表进行update,在其update触发器中完成对A表和B表的操作。create or replace trigger test after update on C for each row begin if :new.a < :old.a then :new.a := :new.a + :old.a; end if; if :new.b < :old.b then :new.b := :new.b + :old.b; end if; if :new.c < :old.c then :new.c := :new.c + :old.c; end if;
insert into A (time, a, b, c) values(sysdate, :new.a, :new.b, :new.c); -- B if to_char(sysdate,'hh24:mi:ss') = '00:00:00' then -- 不好意思,我还没有找到得到前一天的函数,所以只能.... insert into B .... end if; end; /
不好意思,这个trigger应该是before update而不是after update
B表中存放的是两个相邻0点的差值,所以还得从A表中找到最近的0点值再相减后插入B表 语句该怎么写呢?这样可以吗? IF to_char(time,'hh24:mi:ss') = '00:00:00' then SELECT top 1 INTO last_a,last_b, last_c FROM a WHERE to_char(time,'hh24:mi:ss') = '00:00:00' ORDER BY time desc last_a :=:new.a -last_a last_b :=:new.b -last_b last_c :=:new.c -last_c INSERT INTO B(TIME,last_a,last_b, last_c ) --这里的TIME怎么能取道上一个0点的值,还得是YYYY-MM-DD格式!
实际上,我的开发中没有并行的操作,所以不用考虑
to Lastdrop(空杯):
第一个问题,我现在有一个sql server下的解决方法,添加一个表C,各字段和A一样,对每个字段作instead of insert 触发,表C始终是一行数据,在插入时对每一个字段的插入值与表C的这行数据进行比较如果插入值小于原有值,则将插入值加上原有值作为这个字段的插入值,否则不变,判断完成后,
用新的inserted表中插入值更新这行数据,同时
select *
from inserted into 表A
我对oracle不熟,不知道是否有类似的触发以及inserted表?
before insert on A
for each row
declare
last_a number;
last_b number;
last_c number;
begin
SELECT NVL(MAX(a),0),NVL(MAX(b),0),NVL(MAX(c),0) INTO last_a,
last_b, last_c FROM c;
if :new.a < last_a then
:new.a := :new.a + last_a;
end if;
if :new.b < last_b then
:new.b := :new.b + last_b;
end if;
if :new.c < last_c then
:new.c := :new.c + last_c;
end if;
update c set a=:new.a, b=:new.b, c=:new.c;
end;
/如果你用同样类似的方法,创建一个表D保存最近一次0点的记录,那么也可以在触发器中实现。
这些语句在哪里执行(sql server里有查询分析器),我用的oracle的可视界面创建,逐行触发,旧值与新值该怎么添?
oracle易用性好像不太好,错误提示尽是些问号,你能不能帮我在你那里调试一下,看能不能正常触发
你上面的语句末尾再添加:
INSERT INTO A
SELECT NVL(MAX(a),0),NVL(MAX(b),0),NVL(MAX(c),0)
FROM C
THANKS!
INSERT INTO A
SELECT NVL(MAX(a),0),NVL(MAX(b),0),NVL(MAX(c),0)
FROM C
这个语句,应该是这个语句会触发我上面写的那个触发器。
请看看楼主的话
“我现在有一个sql server下的解决方法,添加一个表C,各字段和A一样,对每个字段作instead of insert 触发,表C始终是一行数据,在插入时对每一个字段的插入值与表C的这行数据进行比较如果插入值小于原有值” SELECT NVL(MAX(a),0),NVL(MAX(b),0),NVL(MAX(c),0) INTO last_a,
last_b, last_c FROM c;
请注意记录是从表C,而非表A中取得,表C中存放的就是最近一次的记录,之所以用MAX是防止表C中没有记录是执行SELECT INTO语句出错。
其实不加这个表也好解决,就是取记录MAX(ROWID)
to Lastdrop(空杯):哦,原来我是想用C表起一个过滤的作用,我是直接插入到c表,在C表上判断后再插入A表,和你说的是一个道理,主要是考虑第二个问题还要在A表上建立一个插入的触发器,是不是分开会好一点?
2.MAX(ROWID)并不一定就是最近的一条记录,当记录不是连续存放时,ROWID也不连续。
能说说用MAX(ROWID)具体的实现方法吗?谢谢!
1. 当你第一次插入A表时,(当然你现在A表和C表中都有记录)此时C表中没有记录,若此时调用select a,b,c into last_a,last_b,last_c from c,就会报错,所以我们的习惯对SELECT INTO语句即使知道可以取到值,也使用min或MAX之类的函数以保证安全。2.第二个问题,你可以为C表建立触发器,判断插入记录为当天0点时,从A表取出前一天的值进行计算后插入到B表中。这样就不需要建立D表作为中间表了。
1."在表A的触发器中是不能执行对表A的查询的"这句话确实很关键(在sql server里是可以的)
2.触发器的时间比较以及插入B表时的格式转换该怎么处理(我对oracle的时间函数不了解)
谢谢!
to_char(date_field,date_format)
date_format有很多,比如'yyyy-mm-dd'等将字符串表示的时间转换成数据库中DATE类型的值
to_date('2003-02-14 00:00:00','yyyy-mm-dd hh24:mi:ss')
但是建不来,受"在表A的触发器中是不能执行对表A的查询的"制约!
触发器?按照上面的讨论应该不需要为表A创建触发器,请先将表A的触发器drop掉。drop trigger trigger_name;
我觉得你说的对阿!
能不能告诉我针对C的触发器语句写法,我实在是对oracle语法不熟阿!
谢谢!
after update on C
for each row
begin
if :new.a < :old.a then
:new.a := :new.a + :old.a;
end if;
if :new.b < :old.b then
:new.b := :new.b + :old.b;
end if;
if :new.c < :old.c then
:new.c := :new.c + :old.c;
end if;
insert into A (time, a, b, c)
values(sysdate, :new.a, :new.b, :new.c);
-- B
if to_char(sysdate,'hh24:mi:ss') = '00:00:00' then
-- 不好意思,我还没有找到得到前一天的函数,所以只能....
insert into B ....
end if;
end;
/
B表中存放的是两个相邻0点的差值,所以还得从A表中找到最近的0点值再相减后插入B表
语句该怎么写呢?这样可以吗?
IF to_char(time,'hh24:mi:ss') = '00:00:00' then
SELECT top 1
INTO last_a,last_b, last_c
FROM a
WHERE to_char(time,'hh24:mi:ss') = '00:00:00'
ORDER BY time desc
last_a :=:new.a -last_a
last_b :=:new.b -last_b
last_c :=:new.c -last_c
INSERT INTO B(TIME,last_a,last_b, last_c ) --这里的TIME怎么能取道上一个0点的值,还得是YYYY-MM-DD格式!