2017-07-25 122 views
1

我想创建mysql触发器,它应该从一个表(raw_us)中取出新插入的数字,将它与最后一条记录进行比较(是比上一条记录更新的新值,或者低于最后一个),将它们按范围索引为值-10到10并放入另一个表(indexed_us)。我的数据库表:MySQL触发器更新设置为空值而不是预期的数字

CREATE TABLE raw_us(rdate DATE,pmi DECIMAL(3,2)); 
CREATE TABLE indexed_us(idate DATE, ipmi DECIMAL (2,2)); 
INSERT INTO raw_us(rdate,pmi) VALUES(20000101, 50); 
INSERT INTO indexed_us(idate,ipmi) VALUES(20000101, 5); 

我写的触发器代码进行梳理新的原始数据(插入到表raw_us列PMI) - 是新的“PMI的价值比去年一个大或变小,然后检查什么范围新的原始数据属于,然后根据特定的范围将特定的数字插入到indexed_us表impi列中。这里是我的触发代码:

DELIMITER // 
CREATE TRIGGER ipmiUS BEFORE INSERT ON raw_us 
FOR EACH ROW 
BEGIN 
DECLARE @old_pmi int; 
SET @old_pmi = (select pmi from raw_us where rdate = MAX(rdate)); 
IF (@old_pmi < NEW.pmi) THEN 
    IF (50 < NEW.pmi) AND (NEW.pmi < 60) 
    THEN INSERT INTO indexed_us(idate,ipmi) VALUES (new.date,6); 
    ELSEIF (60 < NEW.pmi) AND (NEW.pmi < 70) 
    THEN INSERT INTO indexed_us(idate,ipmi) VALUES (new.date,7); 
    END IF; 
ELSEIF (@old_pmi > NEW.pmi) THEN 
    IF (50 > NEW.pmi) AND (NEW.pmi > 60) 
    THEN INSERT INTO indexed_us(idate,ipmi) VALUES (new.date,5); 
    ELSEIF (40 > NEW.pmi) AND (NEW.pmi > 50) 
    THEN INSERT INTO indexed_us(idate,ipmi) VALUES (new.date,4); 
    END IF; 
END IF; 
END; // 
DELIMITER ; 

而问题是,更新触发 'BEFORE INSERT' 和范围内固定后IF语句“IF(编号> NEW.pmi)AND(NEW.pmi>号) '我刚刚得到错误: 您的SQL语法错误;检查对应于你的MySQL服务器版本使用附近的“DELIMITER // CREATE TRIGGER ipmiUS BEFORE INSERT对每个ROW raw_us”在行正确的语法手册1

+0

我不能完全肯定我理解正确你,但是当你做一个'insert'的'后update'触发不执行。它在你执行'update'时执行。你可能正在寻找一个'插入'触发器?我也不完全确定你为什么使用2个触发器,你可以简单地在插入触发器后插入你的完整行(但是再次,我们不知道你的第一个触发器是什么)。 – Solarflare

+0

谢谢Solarflare。我认为你是对的,那就是它设置NULL值的原因。但如果我使用'AFTER INSERT'触发器,我无法比较'最后'和'新'记录。这意味着我必须撰写所有新的触发器? –

+0

对于插入,没有'旧'。目前还不完全清楚你想要将一个全新的行与之比较。如果你需要你的逻辑来插入和更新,你必须编写一个插入触发器和一个更新触发器。你可能应该添加你的其他触发器,但我们知道你在做什么。我假设你可以使用一个触发器来执行插入操作,插入行时执行所有操作(包括设置值4到6),另一个触发器用于执行'update'所需的'update'。你也应该修正joanolos答案中提到的比较。 – Solarflare

回答

0

你极有可能不得不与IF表达式问题。您正在以不产生预期结果的方式编写“范围内”(30 < NEW.pmi < 40)

要清楚,只是试试这个:

SELECT 
    30 < 1 < 40 ; 

你得到的回应:

 
| 30 < 1 < 40 | 
| ----------: | 
|   1 | 

这是因为MySQL是实际计算:

SELECT 
    (30 < 1) < 40 ; 

结果的(30 < 1)false,并且由MySQL表示为0,那么(0 < 40)true,并表示为1

你需要重写你的情况是这样的:

IF (30 < NEW.pmi) AND (NEW.pmi < 40) THEN 
    -- whatever 
... 

此外,考虑到你有一些角落情况下被考虑在内。例如,当40 = NEW.pmi时,您可能想要发生某种事情。当检查的范围,这是一个很好的做法,喜欢攀比:

`(lower_bound <= value) AND (value < upper_bound)` 

(注<=<)。

还要注意,你可以写(注都< =和< =

(lower_bound <= value) AND (value <= upper_bound)

与等价形式

value BETWEEN lower_bound AND upper_bound 

这仅仅是当你处理一个很好的做法与INTEGER s或DECIMAL s,但不是如果您使用FLOAT s。


看到整个例如在dbfiddle here

+1

谢谢Joanolo。我现在没有注意到“范围内”的说法是错误的。我会解决这个问题。触发器的目的是从插入到原始表中的原始数据生成索引编号,并将这些编号写入索引表中。基本上我有范围和特定的值应根据原始数据的特定范围写入索引表。我只需要再一个条件,即将原始数据中的最新记录与原始数据中的新记录进行比较,以识别新数字是增加还是减少。我希望我的英语弱点有帮助。谢谢你的病人阅读我的回复。 –