1)Definetely是,ID的应该是自动自动递增,除非你提供一个主键的不同手段这是独一无二的。你得到的插入或者与从MySQL直接mysql_insert_id()
或LAST_INSERT_ID()
的ID,所以要张贴一些连接的信息,你可以做任何
mysql_query("INSERT INTO table1 ...")
$foreign_key=mysql_insert_id(); //this gives you the last auto-increment for YOUR connection
或者,但只有当你绝对肯定没有其他人写入表在平均时间或有过交易的控制,插入后做:
$foreign_key=mysql_query("SELECT LAST_INSERT_ID()")
INSERT INTO table2 message_id=$foreign_key
,或者不拉FK到PHP,都在同一个交易(我也建议包裹SQL作为交易太)的东西如:
"INSERT INTO table1...; INSERT INTO table2 (message_id,...) VALUES(LAST_INSERT_ID(),...)"
根据您的语言和mysql库,您可能无法发出多重查询方法,因此您最好使用第一种方法。
2)这可以有很多方法,取决于你是否也需要回复所有接收者(例如会议),以线程/类似论坛的方式答复,客户端是否可以存储上次检索消息/ ID(例如,在cookie中;也影响你是否真的需要“读”字段)。
“私人聊天”方法是最简单的方法,那么您可能更好的方法是将消息存储在一个表中,并将来自到的关系存储到另一个表中(或使用JOIN),或者只是重新填充在一个表中的消息(因为现在存储便宜)。因此,简单的模型是一个表:
table: message_body,from,to
$recepients=array(1,2,3..);
foreach($recepients as $recepient)
mysql_query("INSERT INTO table (...,message_body,from,to) VALUES(...,$from,$recepient)");
(复制消息等,只有recepient变化)
或
message_table: id,when,message_body
to-from-table: id,msg_id,from,to
$recepients=array(1,2,3,...);
mysql_insert("INSERT INTO message_table (when,message_body) VALUES(NOW(),$body)");
$msg_id=mysql_insert_id();
foreach($recepients as $recepient)
mysql_query("INSERT INTO to-from-table (msg_id,from,to) VALUES($msg_id,$from,$recepient)");
(消息中插入一次,存储关系和FK对于所有收信人)
然后每个客户端存储他/她接收到的最后一个message_id(默认为0),并且假设所有先前的消息已经被读取):
"SELECT * FROM message WHERE from=$user_id OR to=$user_id WHERE $msg_id>$last_msg_id"
,或者我们只需要注意最后的输入时间从用户和然后查询任何新的消息:
"SELECT * FROM message WHERE from=$user_id OR to=$user_id WHERE when>='".date('Y-m-d H:i:s',$last_input_time)."' "
如果你需要一个更会议室套装或论坛胎面类似的方法,并且需要跟踪谁读取或不读取消息,您可能需要跟踪所有涉及的用户。
假设在一个“多用户会议”中不会有数百人参加会议,我会用一张桌子来发送消息,并使用“逗号分隔和包裹列表”技巧,我用它来存储标签。
id autoincrement (again, no need for a separate message id)
your usual: sent_at, title (if you need one), content
sender (int)
recepients (I'd go with varchar or shorter versions of TEXT; whereas TEXT or BLOB gives you unlimited number of users but may have impact on performance)
readers (same as above)
为受助/读者场的秘诀是填充它们以逗号分隔的ID列表,再敷在逗号(我会dulge到为什么后来)。
因此,您必须再次将收件人的id收集到数组中,例如, $受助=阵列(2,3,5)和修改插入:
"INSERT INTO table (sent_at,title,content,sender,recepients) VALUES(NOW(),'$title','$content',$sender_id,',".implode(',', $recepients).",')"
你表中的行状
...发件人| recepients
... 1 | ,2,//单用户消息
... 1 | ,3,5,//多用户消息
选择具有的$ USER_ID = 2你去
SELECT * FROM table WHERE sender=$user_id OR INSTR(recepients, ',$user_id,')
以前我们包裹受助的内爆列表中的ID,例如用户的所有邮件'5,2,3'变成',5,2,3',并且INSTR在这里告诉'2,'是否作为子字符串被包含在某处 - 自从寻求'2','2'或'2' '可能会给你错误的肯定例如' 34,56','1 **,2 34','9,45 2,** 89'相应地 - 这就是为什么我们必须首先包装清单。
当用户读取/接收他/她的消息,则其ID添加到读者列表,如:
UPDATE table SET readers=CONCAT(',',TRIM(TRAILING ',' FROM readers),',$user_id,') WHERE id=${initial message_id here}
导致:
...发件人| recepients |读者
... 1 | ,2, | ,2,
... 1 | ,3,5, | ,3,5,2,
或者我们现在可以修改初始查询添加一列“is_read”陈述用户是否事先阅读信息,或不:
SELECT * FROM table WHERE INSTR(recepients, ',$user_id,'),INSTR(readers, ',$user_id,') AS is_read
收集信息的IDS结果并一次性更新“recepients”字段
"UPDATE table SET readers=CONCAT(',',TRIM(TRAILING ',' FROM readers),',$user_id,') WHERE id IN (".implode(',' ,$received_msg_ids).")"
感谢您的答复,我还挺喜欢‘包装清单’的把戏,不过,我有一个问题:使用这种方法,我怎样才能跟踪邮件实际被读取的时间戳,换句话说,除了跟踪“is_read”,我还想跟踪每个收件人的“when_read”。 – Dodinas 2009-07-29 21:54:08