嘗試建立包含 FROM 子句子查詢的視圖時,MySQL 拋出錯誤:
ERROR 1349 (HY000): View's SELECT contains a subquery in the FROM clause
這是 MySQL 的已知限制(參考 Bug #16757),視圖定義中不允許在 FROM 子句使用子查詢(衍生表)。
CREATE OR REPLACE VIEW BLOG_V_ADMIN
(ID, NICKNAME, SEX, EMAIL, PHONE, QQ, MSN, HTTP, REGISTER_TIME,
IP, LAST_LOGIN_IP, LOGIN_TIME)
AS
SELECT
A.ID, A.NICKNAME, A.SEX, A.EMAIL, A.PHONE, A.QQ, A.MSN, A.HTTP, A.REGISTER_TIME,
B.IP AS LAST_LOGIN_IP, B.LOGIN_TIME AS LAST_LOGIN_TIME
FROM
BLOG_ADMIN A
LEFT JOIN BLOG_ADMIN_LOGIN_TRACK B ON B.ADMIN = A.ID
LEFT JOIN (
SELECT ADMIN, MAX(LOGIN_TIME) AS LOGIN_TIME
FROM BLOG_ADMIN_LOGIN_TRACK
GROUP BY ADMIN
) C ON B.ADMIN = C.ADMIN;
將 FROM 子查詢移至 SELECT 清單,改為相關標量子查詢,每欄位單獨取得最新登入時間與 IP。
CREATE OR REPLACE VIEW BLOG_V_ADMIN
(ID, NICKNAME, SEX, EMAIL, PHONE, QQ, MSN, HTTP, REGISTER_TIME,
LOGIN_TIME, LAST_LOGIN_IP)
AS
SELECT
A.ID, A.NICKNAME, A.SEX, A.EMAIL, A.PHONE, A.QQ, A.MSN, A.HTTP, A.REGISTER_TIME,
(SELECT LOGIN_TIME
FROM BLOG_ADMIN_LOGIN_TRACK
WHERE ADMIN = A.ID
ORDER BY LOGIN_TIME DESC LIMIT 1) AS LAST_LOGIN_TIME,
(SELECT INET_NTOA(IP)
FROM BLOG_ADMIN_LOGIN_TRACK
WHERE ADMIN = A.ID
ORDER BY LOGIN_TIME DESC LIMIT 1) AS LAST_LOGIN_IP
FROM BLOG_ADMIN A;
INET_NTOA() 將儲存為整數的 IP 轉換為點分十進位格式。ORDER BY ... DESC LIMIT 1 取得最新一筆登入記錄。| 方案 | 優點 | 缺點 |
|---|---|---|
| 標量子查詢(本文採用) | 語法簡單、無需額外物件 | 大量資料時效能較差 |
| 建立中繼表/暫存表 | 查詢效能佳 | 需維護同步機制 |
| 升級至 MySQL 8.0+ 使用 CTE | 語意清晰、可讀性高 | 需升級資料庫版本 |