我遇到了这个触发器的问题,我不明白为什么它不起作用。我的数据库中有两个表,我想在修改表“mensajes”时创建一个触发器来更新表“mensajes_info”
CREATE TABLE ESC.MENSAJES (CODIGO NUMBER(20) PRIMARY KEY,
TEXTO VARCHAR2(200),
TIPO VARCHAR2(30)) ;
CREATE TABLE MENSAJES_INFO ( TIPO VARCHAR2(30) NOT NULL,
CUANTOS_MENSAJES NUMBER(2),
ULTIMO VARCHAR2(200),
CONSTRAINT MENSAJES_INFO_PK PRIMARY KEY (TIPO ) ENABLE );
create or replace TRIGGER ACTUALIZA_TB_MENS_INFO
AFTER DELETE OR INSERT OR UPDATE ON ESC.MENSAJES
FOR EACH ROW
BEGIN
IF INSERTING THEN
UPDATE MENSAJES_INFO SET(ULTIMO) SELECT :NEW.TEXT0 FROM ESC.MENSAJES;
ELSIF DELETING THEN
UPDATE MENSAJES_INFO SET(CUANTOS_MENSAJES, ULTIMO)
((CUANTOS_MENSAJES)-1, NULL) WHERE :OLD.tipo = tipo;
ELSIF UPDATING THEN
IF(:OLD.tipo != :NEW.tipo) THEN
UPDATE MENSAJES_INFO SET(CUANTOS_MENSAJES, ULTIMO)
(select(CUANTOS_MENSAJES)-1, NULL) WHERE :OLD.tipo != :NEW.tipo;
ELSE
UPDATE MENSAJES_INFO SET (CUANTOS_MENSAJES, ULTIMO)
VALUES(select(CUANTOS_MENSAJES)+1, :NEW.TEXT0) WHERE :new.tipo = tipo ;
END IF;
END IF;
END;
我收到编译错误:
TRIGGER的错误MY_SCHEMA.ACTUALIZA_TB_MENS_INFO:
LINE/COL ERROR
-------- ------------------------------------------------------
3/5 PL/SQL: SQL Statement ignored
3/38 PL/SQL: ORA-00927: missing equal sign
3/45 PLS-00049: bad bind variable 'NEW.TEXT0'
5/5 PL/SQL: SQL Statement ignored
6/5 PL/SQL: ORA-00927: missing equal sign
9/7 PL/SQL: SQL Statement ignored
10/7 PL/SQL: ORA-00927: missing equal sign
12/7 PL/SQL: SQL Statement ignored
13/7 PL/SQL: ORA-00927: missing equal sign
13/42 PLS-00049: bad bind variable 'NEW.TEXT0'
我做错了什么?
答案 0 :(得分:1)
您的代码中有几个问题。最紧迫的是,您的更新语句格式不正确,如 from django.db import models
from django.conf import settings
from django.db.models.signals import post_save
# Create your models here.
class Question(models.Model):
text = models.TextField()
active = models.BooleanField(default = True)
draft = models.BooleanField(default = False)
timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
#answers = models.ManyToManyField('Answer')
def __unicode__(self):
return self.text[:10]
class Answer(models.Model):
question = models.ForeignKey(Question)
text = models.CharField(max_length=120)
active = models.BooleanField(default=True)
draft = models.BooleanField(default=False)
timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
def __unicode__(self): #def __str__(self):
return self.text[:10]
LEVELS = (
('Mandatory', 'Mandatory'),
('Very Important', 'Very Important'),
('Somewhat Important', 'Somewhat Important'),
('Not Important', 'Not Important'),
)
class UserAnswer(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL)
question = models.ForeignKey(Question)
my_answer = models.ForeignKey(Answer, related_name = 'user_answer')
my_answer_importance = models.CharField(max_length=50, choices= LEVELS)
my_points = models.IntegerField(default=-1)
their_answer = models.ForeignKey(Answer, null=True, blank=True, related_name = 'match_answer')
their_importance = models.CharField(max_length=50, choices= LEVELS)
their_points = models.IntegerField(default=-1)
timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
def __unicode__(self):
return self.my_answer.text[:10]
def score_importance(importance_level):
if importance_level == "Mandatory":
points = 300
elif importance_level == "Very Important":
points = 200
elif importance_level == "Somewhat Important":
points = 50
elif importance_level == "Not Important":
points = 0
else:
points = 0
return points
def update_user_answer_score(sender, instance, created, *args, **kwargs):
#print sender
print instance
#print created
if instance.my_points == -1:
my_points = score_importance(instance.my_answer_importance)
instance.my_points = my_points
print my_points
instance.save()
if instance.their_points == -1:
their_points = score_importance(instance.their_importance)
instance.their_points = their_points
print my_points
instance.save()
post_save.connect(update_user_answer_score, sender=UserAnswer)
消息所示。
ORA-00927: missing equal sign
无效;首先,你需要一个等号作为the update-set clause的一部分;其次,你没有从原始表中选择新的/旧的伪记录值,你只需直接引用UPDATE MENSAJES_INFO SET(ULTIMO) SELECT :NEW.TEXT0 FROM ESC.MENSAJES;
:第三,你的表定义说列名是:new.<column>
而不是texto
。
text0
同样在第二次更新中,您错过了一个等号,并且您只能在子括号中使用子查询设置多个值:
UPDATE MENSAJES_INFO SET ULTIMO = :NEW.TEXTO;
您的第三次和第四次更新可能是为了更新两种类型的消息计数,并且有类似的其他问题;第三个也是goign更新表中的所有行,这不是你想要的,所以你可能想要这样的东西:
UPDATE MENSAJES_INFO SET CUANTOS_MENSAJES = CUANTOS_MENSAJES - 1, ULTIMO = NULL
所以,更像是:
IF(:OLD.tipo != :NEW.tipo) THEN
UPDATE MENSAJES_INFO SET CUANTOS_MENSAJES = CUANTOS_MENSAJES - 1, ULTIMO = NULL
WHERE :OLD.tipo = tipo;
END IF;
UPDATE MENSAJES_INFO SET CUANTOS_MENSAJES = CUANTOS_MENSAJES + 1, UNLTIMO = :NEW.TEXT0
WHERE :NEW.tipo = tipo;
我还删除了不必要的括号。详细了解the update statement,triggers和pseudorecords。
尝试通过触发器维护计数和其他聚合信息会让您感到头疼,因为针对CREATE OR REPLACE TRIGGER ACTUALIZA_TB_MENS_INFO
AFTER DELETE OR INSERT OR UPDATE ON MENSAJES
FOR EACH ROW
BEGIN
IF INSERTING THEN
UPDATE MENSAJES_INFO SET ULTIMO = :NEW.TEXTO;
ELSIF DELETING THEN
UPDATE MENSAJES_INFO SET CUANTOS_MENSAJES = CUANTOS_MENSAJES - 1, ULTIMO = NULL
WHERE :OLD.tipo = tipo;
ELSIF UPDATING THEN
IF(:OLD.tipo != :NEW.tipo) THEN
UPDATE MENSAJES_INFO SET CUANTOS_MENSAJES = CUANTOS_MENSAJES - 1, ULTIMO = NULL
WHERE :OLD.tipo = tipo;
END IF;
UPDATE MENSAJES_INFO SET CUANTOS_MENSAJES = CUANTOS_MENSAJES + 1, ULTIMO = :NEW.TEXTO
WHERE :NEW.tipo = tipo;
END IF;
END;
/
的同时操作可能会使MENSAJES
表处于您不期望的状态,除非访问权限是序列化。对于计数,基表的视图会更简单:
MENSAJES_INFO
...但这对CREATE VIEW MENSAJES_INFO AS
SELECT TIPO, COUNT(*) AS CUANTOS_MENSAJES
FROM MENSAJES
GROUP BY TIPO;
...
答案 1 :(得分:1)
我怀疑在单独的表中存储每种类型的消息数是个好主意,您总是可以选择这样的数据。但如果你坚持请尝试这样的事情:
create or replace trigger actualiza_tb_mens_info
after delete or insert or update on mensajes
for each row
begin
if inserting then
merge into mensajes_info mi
using (select :new.tipo tipo, :new.texto texto from dual) m
on (mi.tipo = m.tipo)
when matched then update set
cuantos_mensajes = cuantos_mensajes + 1, ultimo = m.texto
when not matched then
insert (tipo, cuantos_mensajes, ultimo) values (m.tipo, 1, m.texto);
elsif deleting then
update mensajes_info set
cuantos_mensajes = cuantos_mensajes - 1, ultimo = null
where tipo = :old.tipo;
elsif updating then
if :old.tipo != :new.tipo then
update mensajes_info set
cuantos_mensajes = cuantos_mensajes - 1, ultimo = null
where tipo = :old.tipo;
merge into mensajes_info mi
using (select :new.tipo tipo, :new.texto texto from dual) m
on (mi.tipo = m.tipo)
when matched then update set
cuantos_mensajes = cuantos_mensajes + 1, ultimo = m.texto
when not matched then
insert (tipo, cuantos_mensajes, ultimo) values (m.tipo, 1, m.texto);
else
update mensajes_info set ultimo = :new.texto
where tipo = :new.tipo;
end if;
end if;
end;
在插入使用merge
语句时,删除正确的update
时,更新时 - 取决于邮件类型是否发生变化。
测试:
insert into mensajes (codigo, texto, tipo) values (1, 'Text 1', 'Type 1');
insert into mensajes (codigo, texto, tipo) values (2, 'Text 11', 'Type 1');
insert into mensajes (codigo, texto, tipo) values (3, 'Text 12', 'Type 1');
insert into mensajes (codigo, texto, tipo) values (4, 'Text 21', 'Type 2');
delete from mensajes where codigo = 2;
update mensajes set tipo = 'Type 2' where codigo = 3;
select * from mensajes_info;
TIPO CUANTOS_MENSAJES ULTIMO
------ ---------------- --------------------
Type 1 1
Type 2 2 Text 12