8
头图

将 ChatGPT 当作一个求职者来面试它,它的表现如何?下面是要求它做一个数据库设计的例子。

:对一个系统的描述如下:
系统中有大量注册用户,用户可以关注其他用户。用户可以发布消息,消息包含发布者、发布时间和可见性。消息的可见性可以是公开、不公开或仅对关注自己的用户可见。
请设计这个系统的数据库表。

ChatGPT:下面是一种数据库表的设计:

1.用户表 (User)

id: 用户的唯一标识(主键)
username: 用户名
password: 密码
email: 电子邮件地址

2.关注表 (Follow)

id: 关注记录的唯一标识(主键)
user_id: 关注者的用户ID(外键,关联到User表的id字段)
follow_id: 被关注者的用户ID(外键,关联到User表的id字段)

3.消息表 (Message)

id: 消息的唯一标识(主键)
user_id: 消息发布者的用户ID(外键,关联到User表的id字段)
content: 消息内容
visibility: 消息的可见性(公开/不公开/仅对关注自己的用户可见)
created_at: 消息发布的时间戳

请注意,这只是一种可能的数据库表设计,具体的实现可能因为需求的不同而有所变化。


:请给出这些表的建表 SQL 语句。

ChatGPT:以下是用 SQL 创建上述表的语句:

CREATE TABLE User (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(255) NOT NULL,
    password VARCHAR(255) NOT NULL,
    email VARCHAR(255) NOT NULL
);

CREATE TABLE Follow (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT NOT NULL,
    follow_id INT NOT NULL,
    FOREIGN KEY (user_id) REFERENCES User(id),
    FOREIGN KEY (follow_id) REFERENCES User(id)
);

CREATE TABLE Message (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT NOT NULL,
    content TEXT NOT NULL,
    visibility ENUM('public', 'private', 'followers') NOT NULL,
    created_at TIMESTAMP NOT NULL,
    FOREIGN KEY (user_id) REFERENCES User(id)
);

请注意,上述 SQL 语句是在 MySQL 中创建表的语句。如果使用其他数据库系统,可能需要更改语法。


:请给出用MyBatis框架查询User表的Java代码

ChatGPT:下面是一种使用 MyBatis 框架查询 User 表的 Java 代码:

1.首先,需要在 User 实体类中定义属性:

public class User {
    private Integer id;
    private String username;
    private String password;
    private String email;
    // 省略 getters 和 setters
}

2.其次,需要在 MyBatis 的映射文件中编写 SQL 语句:

<select id="getUserById" resultType="User">
    SELECT * FROM User WHERE id = #{id}
</select>

3.最后,在 Java 代码中调用 MyBatis 查询:

SqlSession sqlSession = sqlSessionFactory.openSession();
try {
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    User user = mapper.getUserById(1);
    System.out.println(user);
} finally {
    sqlSession.close();
}

请注意,这仅仅是一个简单的示例,实际的代码可能会有所不同。还需要配置 MyBatis,创建 SqlSessionFactory 对象等。


接下来提升难度。

:现在需求改了,要求用户发消息可以指定接收人,此时数据库设计要如何改?

ChatGPT:现在需要考虑用户发消息可以指定接收人,因此可以创建一个新的表,存储消息和接收人之间的关系。

1.首先,创建一个新表 MessageReceiver:

CREATE TABLE MessageReceiver (
    id INT AUTO_INCREMENT PRIMARY KEY,
    message_id INT NOT NULL,
    receiver_id INT NOT NULL,
    FOREIGN KEY (message_id) REFERENCES Message(id),
    FOREIGN KEY (receiver_id) REFERENCES User(id)
);

2.然后,将 Message 表的 visibility 字段删除:

ALTER TABLE Message DROP COLUMN visibility;

3.最后,可以使用两种方式之一在 MyBatis 中查询消息:

查询所有与特定用户相关的消息:
<select id="getMessagesByReceiverId" resultType="Message">
    SELECT m.* FROM Message m
    INNER JOIN MessageReceiver mr ON m.id = mr.message_id
    WHERE mr.receiver_id = #{receiverId}
</select>
查询特定用户发送的所有消息:
<select id="getMessagesBySenderId" resultType="Message">
    SELECT * FROM Message WHERE user_id = #{senderId}
</select>

这样,您就可以根据消息的发送者和接收者的不同需求,选择不同的查询方法了。


(注意上面的回答存在问题,删除 visibility 字段的操作是我没想到的,于是我接着问)

:但是 visibility 字段删除后,如何表达一个消息是公开的呢?

ChatGPT:如果删除了 visibility 字段,可以通过在 MessageReceiver 表中为所有用户添加一条记录来表示消息是公开的。

1.首先,创建一个新的角色 PUBLIC:

CREATE TABLE Role (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255) NOT NULL
);

INSERT INTO Role (name) VALUES ('PUBLIC');

2.然后,创建一个新的表 UserRole,用于存储用户和角色之间的关系:

CREATE TABLE UserRole (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT NOT NULL,
    role_id INT NOT NULL,
    FOREIGN KEY (user_id) REFERENCES User(id),
    FOREIGN KEY (role_id) REFERENCES Role(id)
);

3.最后,为所有用户添加一条记录,表示他们是公共用户:

INSERT INTO UserRole (user_id, role_id)
SELECT id, (SELECT id FROM Role WHERE name = 'PUBLIC')
FROM User;

现在,您可以使用以下查询语句查询公开消息:

<select id="getPublicMessages" resultType="Message">
    SELECT m.* FROM Message m
    INNER JOIN MessageReceiver mr ON m.id = mr.message_id
    INNER JOIN UserRole ur ON mr.receiver_id = ur.user_id
    WHERE ur.role_id = (SELECT id FROM Role WHERE name = 'PUBLIC')
</select>

这样,您就可以使用相同的数据库表来表示公开消息了。


(不错不错,虽然这个回答还是有问题,但基本上还是可以说让它给圆回去了。正确的回答是创建一个用户用来表示“公开接收者”即可。现在我换个表达的角度提问,看它能不能充分理解)

:按照需求,如果一条消息是公开的,那么它就不应该再有其它的接收人。请给出查询违反这条规则的消息记录的SQL语句。

ChatGPT:您可以使用以下 SQL 语句查询违反这条规则的消息记录:

SELECT m.*
FROM Message m
INNER JOIN MessageReceiver mr ON m.id = mr.message_id
INNER JOIN UserRole ur ON mr.receiver_id = ur.user_id
WHERE ur.role_id != (SELECT id FROM Role WHERE name = 'PUBLIC')
GROUP BY m.id
HAVING COUNT(ur.id) > 1;

此查询语句查询所有具有不止一个接收人的消息,并且这些接收人中必须至少有一个不是公共用户。如果一条消息同时具有公共用户和其他接收人,则该消息是违反规则的。


(上面的回答是有问题的,它在后面准确的描述了 SQL 的逻辑,但 SQL 本身存在问题,于是我希望它能纠正这个问题)

:发给多个接收人的非公开消息同样会被这个SQL查询出来,但是这样的消息没有违反规则。

ChatGPT:您对我的回答是正确的。我错误地认为发给多个接收人的消息是违反规则的。以下是修正后的 SQL 语句:

SELECT m.*
FROM Message m
INNER JOIN MessageReceiver mr ON m.id = mr.message_id
INNER JOIN UserRole ur ON mr.receiver_id = ur.user_id
WHERE m.visibility = (SELECT id FROM Visibility WHERE name = 'PUBLIC') AND
      COUNT(ur.id) > 1;

此语句只查询 visibility 字段为“公开”的消息,但有多个接收人的记录。


(这个回答问题更严重了,因为 visibility 字段在需求变更后已经没了。我怀疑我没表达清楚,于是继续追加条件)

:visibility字段不是被删了吗,怎么SQL里面又出现了?请按照需求变更后的表设计来生成SQL语句。

ChatGPT:对不起,我错误地在 SQL 语句中提到了 visibility 字段。根据需求变更后的表设计,可以使用以下 SQL 语句来查询具有多个接收人的非公开消息:

SELECT m.*
FROM Message m
INNER JOIN MessageReceiver mr ON m.id = mr.message_id
GROUP BY m.id
HAVING COUNT(mr.receiver_id) > 1;

这条语句将查询出所有具有多个接收人的非公开消息。

(这个回答问题更严重了,它似乎忘掉了我之前规则中的公开消息条件,而且 SQL 内容与后面的描述都不一致了。至此我推测 ChatGPT 对上下文的“记忆”只能维持少数回合,再继续问下去也没有含义了。面试结束。)

捏造的信仰
2.8k 声望272 粉丝

Java 开发人员