我的项目中有一个单元,用于在用户之间进行消息交换。为此,我使用了两个MySQL表:
CREATE TABLE `tmessages` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`header` varchar(100) DEFAULT NULL,
`body` text,
...
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
那是主人。它包含有关发件人,标题,邮件正文等信息和
CREATE TABLE `tmessage_recipients` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`idmessage` int(10) unsigned NOT NULL DEFAULT '0',
`idstuff_recipient` int(10) unsigned NOT NULL DEFAULT '0',
...,
PRIMARY KEY (`id`,`idmessage`,`idstuff_recipient`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
作为发送消息的用户的信息,打开消息的日期/时间等的详细信息(其余信息由触发器设置)以下代码正常工作并发送消息。
var
s: string;
idmessage: longword;
i: Word;
...
s := 'INSERT INTO `tmessages` SET ' + '`header`=' + QuotedStr(Edit12.Text) +
', ' + '`body`=' + QuotedStr(Memo3.Text);
Hdm1.FDConnection1.ExecSQL(s);
idmessage := Hdm1.FDConnection1.ExecSQLScalar('SELECT `id` FROM `tmessages` '
+ 'WHERE `header`=' + QuotedStr(Edit12.Text) + 'AND `body`=' +
QuotedStr(Memo3.Text) + ' ORDER BY `id` DESC LIMIT 1');
for i := 0 to ListBox3.Count - 1 do
begin
s := 'INSERT INTO `tmessage_recipients` SET ' + '`idmessage`=' +
inttostr(idmessage) + ', ' + '`idstuff_recipient`=' +
inttostr(ListBox3.ItemByIndex(i).Tag);
Hdm1.FDConnection1.ExecSQL(s);
end;
但我认为它不是最佳的,因为我必须首先获取idmessage。如何优化程序并使其更可靠?可以在Hdm1.FDConnection1.ExecSQL()
的一次通话中插入吗?
修改
使用@Alex Tartan和@whosrdaddy的评论,我发现了这样的事情。这是最佳方式吗?或者我需要改变什么?
s:= 'INSERT INTO `tmessages` (`header`,`body`) VALUES(:p1, :p2);'#13#10 +
'SET @last_id := (SELECT LAST_INSERT_ID());';
for i := 0 to ListBox3.Count - 1 do
s := s + #13#10'INSERT INTO `tmessage_recipients` (`idmessage`,`idstuff_recipient`)'
+ ' VALUES(@last_id,' + inttostr(ListBox3.ItemByIndex(i).Tag) + ');';
Hdm1.FDConnection1.ExecSQL(s, [Edit12.Text, Memo3.Text]);
修改2
根据@kobik的提议,我来到了以下地方:
s:= 'INSERT INTO `tmessages` (`header`,`body`) VALUES(:p1, :p2);'#13#10 +
'SET @last_id := (SELECT LAST_INSERT_ID());';
for i := 0 to ListBox3.Count - 1 do
s := s + #13#10'INSERT INTO `tmessage_recipients` (`idmessage`,`idstuff_recipient`)'
+ ' VALUES(@last_id,' + inttostr(ListBox3.ItemByIndex(i).Tag) + ');';
HDM1.FDQViaFDTransaction.Transaction.StartTransaction;
try
HDM1.FDQViaFDTransaction.ExecSQL(s, [Edit12.Text, Memo3.Text]);
HDM1.FDQViaFDTransaction.Transaction.Commit;
except
HDM1.FDQViaFDTransaction.Transaction.Rollback;
end;
编辑3
根据@ Rick-James的重要建议,代码转换为以下内容......
s := 'INSERT INTO `tmessages` (`header`,`body`) VALUES(:p1, :p2);'#13#10 +
'SET @last_id := (SELECT LAST_INSERT_ID());';
s := s + #13#10'INSERT INTO `tmessage_recipients` ' +
'(`idmessage`,`idstuff_recipient`)'#13#10'VALUES';
for i := 0 to ListBox3.Count - 1 do
s := s + #13#10'(@last_id,' + inttostr(ListBox3.ItemByIndex(i).Tag) + '),';
s[High(s)] := ';';
Hdm1.FDQViaFDTransaction.Transaction.StartTransaction;
try
Hdm1.FDQViaFDTransaction.ExecSQL(s, [Edit12.Text, Memo3.Text]);
Hdm1.FDQViaFDTransaction.Transaction.Commit;
ShowMessage('Message sent.');
Button10Click(self);
except
Hdm1.FDQViaFDTransaction.Transaction.Rollback;
end;
答案 0 :(得分:3)
为了提高效率,请使用多行INSERT:
INSERT INTO table2
(id, x)
VALUES
(@last_id,"newVal_1"),
(@last_id,"newVal_2"),
(@last_id,"newVal_3");
答案 1 :(得分:2)
使用mysql变量:
INSERT INTO table1 (id,value) VALUES(1,'test');
SET @last_id := (SELECT LAST_INSERT_ID());
INSERT INTO table2 (id,colName) VALUES(@last_id,"newVal_1");
...
INSERT INTO table2 (id,colName) VALUES(@last_id,"newVal_n");
这样您只需要一次调用服务器