1

首先,我的基本结构如下。

friends表,添加了一些示例关系:

-------------------------------
|user1 | user2 | util1 | util2|
-------------------------------
| 123  |  456  |  123  |  456 |
| 789  |  012  |  012  |  789 |
| 345  |  678  |  345  |  678 |

(这些util列是与我拥有的触发器关联的辅助列 - 如果说(user1,user2) = (123,456)存在,那么我不希望(456,123)能够被创建。触发器插入(util1,util2)(least,greatest); 然后有一个唯一索引。这很好,只是想我会解释一下。)

friendReq待处理的好友请求表:

----------------
|initBy| reqTo |
----------------
| 901  |  234  |
| 567  |  890  |
| 234  |  567  |

什么有效:例如,如果 id 901requests的用户,234如果该请求不存在,则将其添加到好友请求表中;我在 上有一个唯一索引(initBy,reqTo),因此如果向它901重新发送请求,234则不会插入额外的行。凉爽的。

我需要什么:如果234随后向 发送请求901,我不想(initBy,reqTo) = (234, 901)被插入(请注意,我已经设置了当901请求234234收到通知;这工作正常。在这里我只是假设234忽略请求和决定尝试901通过我的简单文本字段+添加朋友按钮手动添加)。相反,我希望它自动接受好友请求——也就是说,(901,234)从. 这里没有个人资料页面——没有 Facebook 风格的“回复好友请求”选项。这是一个简单的基于追随者的应用程序,只需输入他们的用户名并单击添加即可请求友谊。friendReqfriends

我的功能 SQL 用于简单地添加好友请求而不检查我刚刚描述的内容:

INSERT INTO friendReq ( initBy, reqTo)
    VALUES ($userid, (SELECT id FROM users WHERE username = '$addFriend') );

$addFriend从给定用户发送好友请求时输入的用户名获取;请不要评论防止 SQL 注入,这只是我的简化示例。)

伪代码,假设234发送请求到901

IF (234, 901) DOES NOT EXIST
    INSERT INTO friendReq ( initBy, reqTo)
        VALUES ( 234, 901 )
IF (901, 234) EXISTS
    INSERT INTO friends (901, 234),
    DELETE FROM friendReq (901, 234);

如果我的解释不是很清楚,我很抱歉。有什么建议么?


解决方案:我不确定这是否是这里的 SOP,但对于其他人来说,下面是我最终做的并且它有效。我确信有一些效率改进要做(例如,从其他字符串构建各种查询字符串,而不是重新键入它的许多部分,以及使用 multi_query),但是对于一个简单的解决方案,希望有人能找到这个利用:

$query = "SELECT * FROM friendReq
          WHERE initBy = (SELECT id FROM users WHERE username = '$addFriend')
          AND reqTo = $userid";
if ( mysqli_num_rows(mysqli_query($conn, $query) ) == 1 ) {
    $query = "DELETE FROM friendReq
              WHERE initBy = (SELECT id FROM users WHERE username = '$addFriend')
              AND reqTo = $userid";
    mysqli_query($conn, $query);
    $query = "INSERT INTO friends (user1, user2)
              VALUES ($userid, (SELECT id FROM users WHERE username = '$addFriend') )";
    mysqli_query($conn, $query);
    die();
} else {
    $query = "INSERT INTO friendReq (initBy, reqTo)
              VALUES ($userid, (SELECT id FROM users WHERE username = '$addFriend') )";
    mysqli_query($conn, $query);
    die();
}
4

2 回答 2

1

我会在没有实际代码的情况下回答这个问题,因为我很着急。你已经有了这个主要的设置,我喜欢你的布局。

尝试插入friendReq并获取插入的行数。如果插入一行则完成,如果插入0行,则删除相反的好友请求并插入好友。

此解决方案不是 100% mysql,但也将采用 php。

于 2013-07-19T22:27:46.220 回答
1

我认为您会找到INSERT IGNOREDELETE IGNORE容易使用的语法。

给定: CREATE TABLEfriendReq ( initByint(11), reqToint(11), UNIQUE KEY urel( initBy, reqTo) );

这允许您编写插入语句而不会弄乱 withEXISTS子句:

INSERT IGNORE INTO friendReq (initBy, reqTo) VALUES ( 234, 901 );
INSERT IGNORE INTO friends (901, 234);
DELETE IGNORE FROM friendReq WHERE initBy=901 AND reqTo=234;

如果您done向friendReq 表添加一列,您可以利用[on duplicate key update][1 语法。然后你更新一个标志列并且不必为删除而锁定。您可以推迟删除操作,直到它们由 cron 进程处理,从而减少表上的读写争用:

INSERT INTO friendReq( initBy, reqTo, done) VALUES(234, 901, 0)
    ON DUPLICATE KEY UPDATE done=1;
于 2013-07-19T23:54:48.473 回答