我目前正在开发令牌读取器(RFID)服务,以获取我自己的乐趣和知识,无论您相信与否。我说法语比英语说得好,所以请大家保持警惕。 Google翻译是我的朋友,但是...
我的项目非常简单:
在我的表上执行SELECT的Ajax查询t_rfids代码以检索附加的用户
如果the_users_id不为NULL,则插入t_accesslogs条目。
这是表结构:
CREATE TABLE test_punch.t_accesslogs (
id_tokenaccesslog bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
punchtime timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
id_ref_user bigint(20) UNSIGNED NOT NULL,
PRIMARY KEY (id_tokenaccesslog)
)
ENGINE = INNODB,
CHARACTER SET latin1,
COLLATE latin1_swedish_ci;
因此,通过简单的INSERT INTO t_accesslogs(id_ref_user)值(3);我得到了CURRENT_TIMESTAMP的条目。
一切正常,但我尝试将访问日志优化为带有日期,time_start,time_end的时间卡条目。表结构:
CREATE TABLE test_punch.t_timecards (
id_timecard bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
id_ref_user bigint(20) UNSIGNED NOT NULL,
day_date date NOT NULL,
time_begin time NOT NULL,
time_end time DEFAULT NULL,
PRIMARY KEY (id_timecard)
)
ENGINE = INNODB,
CHARACTER SET latin1,
COLLATE latin1_swedish_ci;
我尝试找出无需使用外部代码即可填充此表的最佳方法,因此我尝试了一下触发器。有触发代码:
CREATE
DEFINER = 'root'@'localhost'
TRIGGER test_punch.add_timecard_entry
AFTER INSERT
ON test_punch.t_accesslogs
FOR EACH ROW
BEGIN
DECLARE bint_IdTimeCard BIGINT;
DECLARE dt_Punch DATE;
DECLARE time_Start TIME;
DECLARE time_End TIME;
SELECT t_timecards.id_timecard INTO bint_IdTimeCard
FROM t_timecards
WHERE t_timecards.id_ref_user = NEW.id_ref_user
AND day_date = CAST(NEW.punchtime as DATE)
AND time_begin IS NOT NULL
AND time_end IS NULL;
IF (bint_IdTimeCard IS NOT NULL) THEN
UPDATE t_timecards
SET t_timecards.time_end = CAST(NEW.punchtime AS TIME)
WHERE t_timecards.id_timecard=bint_IdTimeCard
AND t_timecards.id_ref_user=NEW.id_ref_user;
ELSE
INSERT INTO t_timecards (id_ref_user,day_date,time_begin)
VALUES (NEW.id_ref_user,
CAST(NEW.punchtime AS DATE),
CAST(NEW.punchtime AS TIME));
END IF;
END
我不确定的第一件事是SELECT值为Null时返回的值。它是一个真正的NULL还是Empty?如前所述,即使使用dbForge Studio也很难调试(请参见Debugging MySQL Triggers)
实际上,代码行为似乎无法正确处理IF语句。关于我在做什么错的任何想法吗?
任何帮助将不胜感激。
谢谢
马丁
答案 0 :(得分:0)
如果可以的话,不要。请勿对此类情况使用触发器。使用触发器仅出于一个原因:维护引用完整性。最好不要使用它们,除非您必须这样做。而是依靠DRI。
插入时无需以此方式调整数据。这样做会使您的应用程序更加复杂且可靠性降低。
我推荐一个视图。编写一个表示您要使用的表的视图。看看是否适合您的目的。
如果视图执行不佳,则可能有助于保留其他表示形式。如果是这样,请使用存储过程执行要在表中插入级别高于的操作,并要求应用程序使用该存储过程。您可能会发现使用第二张表保存派生的信息很方便。
答案 1 :(得分:0)
感谢您的评论。我发现使用触发器代替存储过程更容易,但是我将尝试一下存储过程。事实是我的表t_accesslogs将是并且仍然是我的“真”表。在我的方法中,我不打算仅在t_timecards表中添加/删除该表中的任何条目。也许我的逻辑必须加以审查。
我尝试编写一个视图,并且它可以杀死异常,就像一个人错误地两次“推动”一样,它运行良好。
这是我的查看代码:
SELECT
`t_accesslogs`.`id_ref_user` AS `id_user`,
`t_accesslogs`.`dt_scan` AS `dt_scan`,
MIN(`t_accesslogs`.`dt_scan`) AS `dt_scan_min`,
MAX(`t_accesslogs`.`dt_scan`) AS `dt_scan_max`
FROM `t_accesslogs`
GROUP BY CAST(`t_accesslogs`.`dt_scan` AS DATE)
就像我说的那样,这是可行的,但是我尝试自动使开始和结束时间戳记自动化。我将尝试一个存储过程,并让您知道。
谢谢
编辑:
嗯,很奇怪。使用有关调试的文章,我发现问题出在SELECT上。我从以下位置更改了我的WHERE条件:
WHERE t_timecards.id_ref_user = NEW.id_ref_user
AND day_date = CAST(NEW.punchtime AS DATE)
AND time_begin IS NOT NULL
AND time_end IS NULL;
通过
WHERE t_timecards.id_ref_user = NEW.id_ref_user
AND day_date = CAST(NEW.punchtime AS DATE)
AND (time_begin IS NOT NULL AND time_end IS NULL);
,并且可以解决此问题。我想我必须阅读更多。
感谢您的帮助,我将把触发器转换为存储过程。您是对的,更容易调试。