最近越來越多 ASP.NET Core 企業內訓需求,有客戶提到希望能在上課的時候展示 Entity Framework Core 與 Oracle 資料庫的整合能力,我第一時間就想到要在本機安裝 Oracle 資料庫容器起來,快速建立可開發測試的環境。不過,雖然建立 Oracle 資料庫容器相當簡單方便,但不太熟悉 Oracle 資料庫特性的我,卻連第一步「建立使用者」都沒辦法成功,錯誤訊息也相當難以理解,花了一些時間才找到解決之道。
這篇文章已經過時,請移駕 如何在 Windows 快速啟動一個 Oracle Database 23c Free 資料庫容器 觀看最新版文章。
執行 Oracle Database Server 12c R2 容器
要在本機執行 Docker 容器之前,請先參考 Install Docker Desktop on Windows 文件進行 Docker 安裝。
由於 Oracle 官方提供的 Oracle Database Server 12c R2 image 放在 Docker Hub 上面,而且必須先登入 Docker Store 才能下載,所以在執行容器之前,必須先用 docker 命令進行登入:
docker login
只要登入完成,就可以進行 docker pull
下載 Oracle 授權的容器映像 (Container images),目前官方提供兩個版本:
- Oracle Database Server 12.2.0.1 Enterprise Edition (完整版)
- Oracle Database Server 12.2.0.1 Enterprise Edition Slim Variant (精簡版)
docker pull store/oracle/database-enterprise:12.2.0.1
docker pull store/oracle/database-enterprise:12.2.0.1-slim
如果你只想測試簡單的資料庫功能,建議安裝 Slim Variant 版本即可,不但 image 體積小,啟動速度也較快。
接著就直接執行容器,大約 1 ~ 2 分鐘才會啟動完畢:
docker run -d -it --name oracle -p 1521:1521 -p 5500:5500 store/oracle/database-enterprise:12.2.0.1-slim
如果你希望保留本次容器執行所建立的資料庫,可以透過 docker volume mapping 做到:
docker volume create OracleDBData
docker run -d -it --name oracle -p 1521:1521 -p 5500:5500 -v OracleDBData:/ORCL store/oracle/database-enterprise:12.2.0.1-slim
官方容器的預設帳號密碼如下:
- SID:
ORCLCDB
- 帳號:
SYS
- 密碼:
Oradoc_db1
如果不從外部連線的話,可以直接透過 docker exec
命令從 Oracle 容器中執行 sqlplus
工具:
docker exec -it oracle bash -c "source /home/oracle/.bashrc; sqlplus /nolog"
接著可以透過以下 SQL 命令登入 SYS
為 SYSDBA
角色:
CONNECT SYS/Oradoc_db1 AS SYSDBA;
或是直接在執行 sqlplus
時就直接登入:
docker exec -it oracle bash -c "source /home/oracle/.bashrc; sqlplus sys/Oradoc_db1@ORCLCDB as sysdba"
建議第一次登入就先修改 SYS
預設密碼,請參考以下命令進行修改:ALTER USER SYS IDENTIFIED BY <new-password>;
登入後,可以透過以下 SQL 命令,查詢目前資料庫的服務名稱(ORCLCDB.localdomain
):
SELECT VALUE FROM V$PARAMETER WHERE NAME='service_names';
如果要透過 Oracle SQL Developer 登入,可以參考以下截圖進行設定:
建立使用者
當 Oracle 容器完全啟動之後,悲劇也就開始發生了,因為我連一個使用者都無法建立!
因為 Oracle 資料庫跑在容器中,有著不同的安全性架構,從 Oracle 12cR1 開始,因為新增了多租戶架構(multitenant architecture),可以讓你在一個資料庫容器中執行多個租戶資料庫(tenant databases),所以建立使用者的 SQL 命令稍微有點不一樣,而這個問題對一個不常使用 Oracle 的開發者來說也太困難了。
如果你用傳統的 SQL 命令建立一個新用戶,就會得到這個錯誤:ORA-65096: invalid common user or role name
SQL> CREATE USER WILL IDENTIFIED BY yourpassword;
CREATE USER WILL IDENTIFIED BY yourpassword
*
ERROR at line 1:
ORA-65096: invalid common user or role name
而正確建立使用者的方法,應該用以下 SQL 命令:
ALTER SESSION SET "_ORACLE_SCRIPT"=TRUE;
CREATE USER will IDENTIFIED BY yourpassword;
GRANT CONNECT, RESOURCE, DBA TO WILL;
ALTER SESSION SET "_ORACLE_SCRIPT"=FALSE;
接著就可以用新帳號登入連線:
CONNECT WILL/yourpassword AS SYSDBA;
刪除使用者
基本上,只要跟「使用者」相關的操作,在 Oracle 容器中都會遇到問題,所以若要刪除上一節所建立的 WILL
帳號的話,必須使用以下 SQL 命令:
ALTER SESSION SET "_ORACLE_SCRIPT"=TRUE;
DROP USER WILL CASCADE;
ALTER SESSION SET "_ORACLE_SCRIPT"=FALSE;
建立範例資料庫
我從 Getting Started with Oracle Database 找到一個 Oracle Sample Database 非常適合用來學習與測試 Oracle 資料庫連線,以下我將用這個範例進行解說。
下載範例資料庫之後,你將會看到四個檔案:
-
ot_create_user.sql
你首先要解決的困難就是將 ot_create_user.sql
稍微修改一下,前後都加上 ALTER SESSION
命令:
ALTER SESSION SET "_ORACLE_SCRIPT"=TRUE;
-- create new user
CREATE USER OT IDENTIFIED BY yourpassword;
-- grant priviledges
GRANT CONNECT, RESOURCE, DBA TO OT;
ALTER SESSION SET "_ORACLE_SCRIPT"=FALSE;
-
ot_schema.sql
建立 Schema 時並不會發生問題。
建立好之後,可以透過 SELECT table_name FROM user_tables;
密令列出所有建立的表格。(參考)
-
ot_data.sql
匯入資料時,你會遇到 ORA-01843: 不是有效的月份
錯誤,那是因為這個範例資料的 SQL 語法,使用的是美國的日期表示法,你必須在匯入資料前,先執行以下 SQL 才可以成功匯入所有資料:
ALTER SESSION SET NLS_DATE_LANGUAGE='american';
-
ot_drop.sql
等測試完成後,就可以執行這個 SQL 檔案,刪除所有表格。
如果想刪除 OT
使用者,請記得手動刪除。
dotnet add package Oracle.EntityFrameworkCore
dotnet ef dbcontext scaffold "Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=ORCLCDB.localdomain)));User Id=OT;Password=yourpassword;" Oracle.EntityFrameworkCore -o Models
上述 Oracle 連接字串的 Data Source 部分,可以透過 docker logs oracle
查詢相對應的提示訊息
相關連結