如果count永远不为null,则为mysql存储过程

时间:2016-01-20 20:29:23

标签: mysql stored-procedures

我有一个表,每隔5分钟由一个脚本调用更新,由http请求触发。该表看起来像这样

MariaDB > select host_id, ping_eu, disk_usage,insert_time from sequencial_host;
+---------+---------+-------------+---------------------+
| host_id | ping    | disk_usage  | insert_time         |
+---------+---------+-------------+---------------------+
|       1 |   35.60 | 10329416704 | 2016-01-20 20:47:51 |
|       2 |   36.57 |  2902848512 | 2016-01-20 20:48:06 |
+---------+---------+-------------+---------------------+

我想通过调用存储过程来防止乱码,以防脚本运行或任何恶意,如果最后一次insert_time至少是4,5分钟前允许插入。 (30秒脚本内置超时,所以更不准确)。 我建立了这个程序:

CREATE PROCEDURE `update_table`(
IN host_id_a int(11),
IN insert_time timestamp,
IN disk_usage bigint(20) ,
IN ping decimal(10,2)
BEGIN
DECLARE count INT;
SELECT count(insert_time) INTO count FROM db.sequencial_host WHERE insert_time > (NOW() - INTERVAL 270 SECOND) AND host_id = host_id_a ORDER BY insert_time DESC LIMIT 1;

IF count < 1 THEN 
    INSERT INTO db.sequencial_host ( `host_id`,`insert_time`,`disk_usage`,`ping`) 
    VALUES( host_id_a, CURRENT_TIMESTAMP, disk_usage, ping);
END IF;
END

如果我省略了If子句,那么插入语句通过调用过程来工作,如果在shell中执行,则Select Query也适用于它自己。 我使用的是MariaDB 5.5.46-1ubuntu0.14.04.2。

我几乎尝试了IF count = 0,IF count IS NULL,IF(SELECT ..)IS NULL的任意组合。

有人可以看一下吗? 亲切的问候Joey

修改

MariaDB [tempdb]> SELECT count(*) FROM tempdb.sequencial_host WHERE insert_time > (NOW() - INTERVAL 270 SECOND) AND host_id = 1 ORDER BY insert_time DESC LIMIT 1;
+--------------------+
| count(insert_time) |
+--------------------+
|                  0 |
+--------------------+
1 row in set (0.01 sec)

MariaDB [tempdb]> SELECT count(*) FROM tempdb.sequencial_host WHERE insert_time > (NOW() - INTERVAL 2 HOUR) AND host_id = 1 ORDER BY insert_time DESC LIMIT 1;
+--------------------+
| count(insert_time) |
+--------------------+
|                  1 |
+--------------------+

编辑2: 包含所有相关数据库信息的Pastebin完整。 pastebin.com/99eEDLy4

编辑3: 如果我将其更改为cnt = 1,我可以垃圾邮件查询并填充所有内容,但前提是表中有数据。对于刚刚截断的一个,我需要将其设置为0以获取值。

3 个答案:

答案 0 :(得分:0)

从来没有&lt; 0。 count是每次0到n之间的正数。所以

IF count < 0 THEN 

永不运作

将其更改为

 IF count > 0 THEN 

答案 1 :(得分:0)

指望一个或者为null的列,只返回那些非null的值的计数。如果所有列值都为null,则返回null。

在这种情况下,你的where子句确保没有记录返回,因此insert_Time的所有列值都将为null;因此返回null。但是,如果您有多个没有空insert_time的记录;那么计数就代表那些没有空insert_time的记录。

我认为您希望count(*)代替count(insert_time),以确保在找不到记录时返回0。

CREATE PROCEDURE `update_table`(
IN host_id_a int(11),
IN insert_time timestamp,
IN disk_usage bigint(20) ,
IN ping decimal(10,2))
BEGIN
DECLARE count INT;
SELECT count(*) INTO count FROM db.sequencial_host WHERE insert_time > (NOW() - INTERVAL 270 SECOND) AND host_id = host_id_a ORDER BY insert_time DESC LIMIT 1;

IF count < 1 THEN 
    INSERT INTO db.sequencial_host ( `host_id`,`insert_time`,`disk_usage`,`ping`) 
    VALUES( host_id_a, CURRENT_TIMESTAMP, disk_usage, ping);
END IF;
END

答案 2 :(得分:0)

这不是一个错误,它是一个功能。

存储过程内部选择Exists在表中有数据时返回1,如果没有则返回null,当查询写成时(没有在where子句中设置特定表) : SELECT EXISTS (SELECT * INTO count FROM db.sequencial_host WHERE insert_time > (NOW() - INTERVAL 270 SECOND) AND host_id = host_id_a ORDER BY insert_time DESC LIMIT 1);

如果将表附加到主机ID,它将按预期工作。偶数也会返回预期值。 SELECT EXISTS (SELECT * INTO count FROM db.sequencial_host WHERE insert_time > (NOW() - INTERVAL 270 SECOND) AND sequencial_host.host_id = host_id_a ORDER BY insert_time DESC LIMIT 1);