初學 Oracle 時最令人抓狂的莫過於:明明在 Navicat 建好表,SELECT * FROM user; 卻查無資料,加上雙引號 SELECT * FROM "user"; 反而能查出來。這背後是 Oracle 識別符大小寫敏感機制與工具預設行為的雙重「坑」。本文深度解析根因、實測對比,並給出避坑指南。
使用 Navicat 可視化介面建立表 user,執行:
SELECT * FROM user; -- 無結果、不報錯
SELECT * FROM "user"; -- 正常返回資料
為何會如此?關鍵在於 Oracle 如何解析識別符。
| 寫法 | Oracle 內部儲存 | 查詢時需否雙引號 | 大小寫敏感 |
|---|---|---|---|
CREATE TABLE user ... | USER(全大寫) | 否 | 否(自動轉大寫匹配) |
CREATE TABLE "user" ... | user(保持原樣) | 是 | 是(精確匹配) |
CREATE TABLE "User" ... | User(大小寫混合) | 是 | 是 |
鐵律:
匯出 Navicat 建表 SQL 可見:
DROP TABLE "ROOT"."user";
CREATE TABLE "ROOT"."user" (
"userid" NUMBER(2) NOT NULL
);
Navicat 為了「保留使用者輸入的大小寫」,**預設對所有識別符加雙引號**。這導致:
user 而非 USERUSER,自然找不到"userid" 查詢時必須 SELECT "userid" FROM "user"CREATE TABLE personal_user_table (
personal_id NUMBER(10) NOT NULL,
login_name VARCHAR2(20) NOT NULL,
login_password VARCHAR2(20) NOT NULL,
register_time DATE NOT NULL,
...
);
結果:表名儲存為 PERSONAL_USER_TABLE,欄位全大寫。查詢 SELECT * FROM personal_user_table 正常運作,**完全不區分大小寫**,體驗與 MySQL/PostgreSQL 一致。
CREATE TABLE "personal_user_table" (
"personal_id" NUMBER(10) NOT NULL,
"login_name" VARCHAR2(20) NOT NULL,
...
);
結果:表名儲存為 personal_user_table,查詢**必須** SELECT "personal_id" FROM "personal_user_table",大小寫稍有差錯即報 ORA-00904。
-- 建表
CREATE TABLE EMPLOYEE (
EMP_ID NUMBER(10) PRIMARY KEY,
EMP_NAME VARCHAR2(50) NOT NULL,
DEPT_ID NUMBER(6),
HIRE_DATE DATE DEFAULT SYSDATE
);
-- 查詢(任意大小寫均可)
SELECT emp_name FROM employee WHERE dept_id = 10;
select EMP_NAME from EMPLOYEE where DEPT_ID = 10;
優勢:
CREATE VIEW v_user AS SELECT "userid" AS user_id FROM "user";Tools → Options → Code Completion → Quote identifiers 取消勾選Preferences → Editors → SQL → Quote identifiers 設為 NeverTools → Preferences → Database → SQL Formatter → Identifiers → Upper Case若表名/欄位名**必須**使用保留字(如 USER、ORDER、GROUP),**唯一解法是加雙引號**並接受大小寫敏感後果:
CREATE TABLE "ORDER" ("ID" NUMBER PRIMARY KEY); -- 不得不為之
SELECT "ID" FROM "ORDER";
此時建議在應用層封裝視圖或同義詞隔離複雜度。