1)绝对是的,除非您提供唯一的主键的不同方式,否则 id 应该自动递增。mysql_insert_id()
您可以直接使用 mysql或从 mysql获取插入的 id LAST_INSERT_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)");
(复制消息等,仅接收者更改)
或者
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 列表并再次用逗号包装(稍后我将详细说明原因)。
因此,您必须再次将接收者的 ID 收集到一个数组中,例如 $recepients=array(2,3,5) 并修改您的插入:
"INSERT INTO table (sent_at,title,content,sender,recepients) VALUES(NOW(),'$title','$content',$sender_id,',".implode(',', $recepients).",')"
你得到的表格行像
......发件人| 收件人
... 1 | ,2, //单个用户消息
... 1 | ,3,5, //多用户消息
为您使用的 ID 为 $user_id=2 的用户选择所有消息
SELECT * FROM table WHERE sender=$user_id OR INSTR(recepients, ',$user_id,')
以前我们包装了接收者的内爆列表,例如'5,2,3'变成',5,2,3',并且这里的INSTR告诉',2'是否包含在某个地方作为子字符串 - 因为只寻找'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}
这导致:
... 发件人 | 收件人| 读者
... 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
从结果中收集消息 ID 并一次性更新“收件人”字段
"UPDATE table SET readers=CONCAT(',',TRIM(TRAILING ',' FROM readers),',$user_id,') WHERE id IN (".implode(',' ,$received_msg_ids).")"