Oracle XMLType 讓關係資料庫原生支援 XML 存儲與查詢。本文實戰示範:C# 類別 → XML Schema → 註冊 Schema → 建立 XMLType 資料表 → 插入/查詢/Schema 演進 → ASP.NET 顯示,全流程無縫串聯。
public enum PhoneType { [XmlEnum("未知")] Unknown, [XmlEnum("移動")] Mobile, [XmlEnum("固定")] Fixed }
public class Phone { public string Code { get; set; } public PhoneType Type { get; set; } }
[XmlRoot("Phones")] public class Phones : List {
public void Add(string code, PhoneType type) => Add(new Phone { Code = code, Type = type });
}
使用 xsd.exe 或 XmlSchemaExporter 生成 Schema,關鍵片段:
<xs:simpleType name="PhoneType">
<xs:restriction base="xs:string">
<xs:enumeration value="未知"/><xs:enumeration value="移動"/><xs:enumeration value="固定"/>
</xs:restriction>
</xs:simpleType>
BEGIN
DBMS_XMLSCHEMA.registerSchema(
schemaURL => 'https://www.OracleDemo.com/Phones.xsd',
schemaDoc => '<完整XSD字串>',
local => TRUE, genTypes => TRUE, genTables => TRUE);
END;
CREATE TABLE XML_USER_INFO (
NPK integer PRIMARY KEY,
USER_NAME NVARCHAR2(50),
Phones XMLType
) XMLTYPE COLUMN Phones STORE AS OBJECT RELATIONAL
XMLSCHEMA "https://www.OracleDemo.com/Phones.xsd" ELEMENT "Phones"
VARRAY Phones.XMLDATA."Phone" STORE AS TABLE XML_USER_INFO_XMLNT01;
-- 加主鍵約束防止重複電話
ALTER TABLE XML_USER_INFO_XMLNT01 ADD CONSTRAINT PK_XML_USER_INFO_XMLNT01 PRIMARY KEY (NESTED_TABLE_ID, "Code");
INSERT INTO XML_USER_INFO VALUES (1, '用戶1', XMLType(
'
13940588000移動
024-22222222-1固定
'));
-- 測試枚舉約束:嘗試插入 "小靈通" 會拋 ORA-31038
新增 Phone.Make 欄位、PhoneType 增加「小靈通」:
DECLARE
oldSchema XMLType := XMLType('<舊XSD>');
newSchema XMLType := XMLType('<新XSD>');
diffDoc CLOB;
BEGIN
SELECT xmldiff(oldSchema, newSchema).getClobVal() INTO diffDoc FROM dual;
DBMS_XMLSCHEMA.inPlaceEvolve('https://www.OracleDemo.com/Phones.xsd', XMLType(diffDoc));
END;
Oracle 11g+ inPlaceEvolve 實現無停機 Schema 升級,極大降低維運成本。
// DAL 查詢並反序列化
const string SQL = "SELECT t.NPK, t.USER_NAME, t.PHONES.GETSTRINGVAL() as PHONES FROM XML_USER_INFO t";
using (var reader = cmd.ExecuteReader()) {
while (reader.Read()) {
string xml = reader["PHONES"].ToString();
Phones phones = xml.XMLToObject(); // 擴充方法反序列化
list.Add(new UserInfo { NPK = ..., UserName = ..., Phones = phones });
}
}
// GridView 綁定,Phones 類別重寫 ToString() 格式化顯示
| 優點 | 缺點 |
|---|---|
| 類別驅動 Schema,減少 DDL 設計 | C# 屬性難對應長度、精度等細粒度約束 |
| 子資料內嵌,單次 INSERT/SELECT 替代多表 JOIN | 集合元素無法建立外鍵關聯 |
| Schema 演進支援敏捷開發 | 大量子資料時效能不如平面表 |
| 樹狀/半結構化資料天然契合 | XML 序列化有效能開銷 |
XMLType 適合「主檔+少量明細」且結構常變的場景,如設備屬性、表單資料、設定檔存儲。