MySQL在当前会话期间为所有INSERTS设置字段值

时间:2011-08-09 09:36:50

标签: mysql

我正在用C开发一个系统,它将更新提交到MySQL数据库中。客户端并不总是在线,因此当服务器不可访问时,应用程序将保存将执行到* .sql的SQL命令。

我正在考虑将一个名为late_commit的BOOLEAN字段添加到所使用的表中,以便我知道稍后在恢复连接时将这些字段插入到数据库中。

我可以改变程序中的编程逻辑,在插入查询中包含late_commit字段,但我宁愿使用默认值false,并且只有在.sql时才设置为true文件被执行。

我想过使用alter语句插入插入内容,但这看起来有点笨拙并且性能会很差。

我从来没有使用触发器,但是从我在SO question中看到的它们可以起作用。但是,它们似乎不是临时的或本地会话,这会干扰来自其他客户端的并发插入。

你对自己的表现有什么看法吗?不一定是要使用的查询,而是应用最佳的技术/方法。

编辑: 我认为,如果没有其他方法出现,可以创建一个具有相同结构且late_commit默认为true的临时表,将数据插入其中,然后复制到主表中。

注意: 我已经添加了一些我找到的方法的答案。我仍然在寻找永久的解决方案。所以请如果你知道如何做得更好,请发表评论或回答。谢谢!

2 个答案:

答案 0 :(得分:1)

我会为false设置默认late_commit并让所有普通代码忽略它的存在。然后我会将编写SQL文件的代码通过注入late_commit内容的“装饰器”,例如普通的SQL:

insert into table1 (col1, col2) values (val1, val2);

但是当写入档案时:

insert into table1 (late_commit, col1, col2) values (true, val1, val2);

这样只需要知道一段代码。 SQL解析以确定将额外位放在何处非常简单。

答案 1 :(得分:0)

我想我会离开这里,到目前为止我发现的是为了回答这个问题。

正如问题所述,我最好只选择sql方法,避免使用注射器。 准备好的语句不起作用,因为它们需要连接到可能不存在的数据库。


IFNULL()解决方案:

我倾向于使用我提出的使用IFNULL mysql语句的解决方案,通过设置局部变量,我可以在进行实际操作时使用相同的查询配置late_commit列(late_commit = false)或稍后进行(late_commit = true)。

所以使用查询:

INSERT INTO `tmp`.`new_table` (`a`,`b`,`late_commit`)    
VALUES ('abc','def', IFNULL(@LATECOMMIT, FALSE) );

我可以插入late_commit列设置为false的值,使用IFNULL语句:因为未定义会话变量@latecommit,代码会将列配置为false。

另一方面,如果我们实际上正在进行离线提交,我们只需要在所有插入之前加上:

SET @LATECOMMIT = TRUE;

然后继续进行所有必要的插入,在我的例子中包含几个不同的表,但在所有这些表中都有late_commit字段设置为IFNULL(@LATECOMMIT, FALSE)

INSERT INTO `tmp`.`new_table` (`a`,`b`,`latecommit`)
VALUES ('abc','def', IFNULL(@LATECOMMIT, FALSE) );

我喜欢这个解决方案,因为变量只为当前会话设置,并且很容易实现(例如,您只需在SET指令前面添加.sql文件并继续执行)。


TIMEDIFF()或时间戳减法解决方案:

在聊天中讨论这个问题时,@ TehShrike还为我提供了一个仅限sql的解决方案,我利用了首次生成查询的时间和插入时间之间的差异。

这可以完成,因为我的表实际上插入的是clientdate时间戳变量,这是本地的unix时间戳。

所以对于这个解决方案,所需要的只是确定什么被认为是late_commit(例如60秒,1小时......),然后像我这样插入:

INSERT INTO `tmp`.`new_table` (`a`,`b`,`clientdate`,`latecommit`)
VALUES ('abc','def', FROM_UNIXTIME(1313489338),
 IF( CURRENT_TIMESTAMP() - clientdate > 3600, TRUE, FALSE) );

在此插入中,我们认为超过一小时前(3600秒)生成的插入为late_commit

如果您没有使用时间戳,您也可以使用日期时间字段,在这种情况下您可能会使用DATEDIFF()或TIMEDIFF()函数。