將 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 對上下文的“記憶”只能維持少數回合,再繼續問下去也沒有含義了。面試結束。)