處理資料庫錯誤
Adobe AIR 1.0 以及更新的版本
大致上,處理資料庫錯誤就像處理其它執行階段錯誤一樣。您應該撰寫程式碼,為可能發生的錯誤做好準備,並回應錯誤而不是留待執行階段來決定處理方式。在一般情形下,可能的資料庫錯誤可以分成三大類:連線錯誤、SQL 語法錯誤,以及限制錯誤。
連線錯誤
大部分資料庫錯誤都是連線錯誤,而可能會在任何作業期間發生。雖然有策略可以防止連線錯誤,如果資料庫是應用程式的重要部分,卻很少有簡單的方式,能夠妥善處理而從連線錯誤中恢復。
大部分連線錯誤與執行階段跟作業系統、檔案系統和資料庫檔案之間互動的方式有關。例如,如果使用者沒有權限可以在檔案系統上的特定位置中建立資料庫,就會發生連線錯誤。下列策略可以協助防止連線錯誤:
- 使用使用者特定的資料庫檔案
- 請給予每個使用者自己的資料庫檔案,而不是讓所有在單一電腦上使用應用程式的使用者使用單一資料庫檔案。檔案應該位於與使用者帳戶關聯的目錄中。例如,它可以位於應用程式的儲存目錄、使用者的文件資料夾、使用者的桌面等等之中。
- 考量不同的使用者類型
- 請使用不同類型的使用者帳戶,在不同的作業系統上測試您的應用程式。請不要假設使用者在電腦上具有系統管理員權限。同時,也不要假設安裝應用程式的個人必定是執行應用程式的使用者。
- 考慮各種不同的檔案位置
- 如果您允許使用者指定儲存資料庫檔案的位置或選取要開啟檔案的位置,請考慮使用者會使用的檔案的可能位置。此外,請考慮定義有關使用者可以儲存 (或可從中開啟) 資料庫檔案之位置的限制。例如,您可以只讓使用者開啟在其使用者帳戶之儲存位置內的檔案。
如果發生連線錯誤,最可能發生在初次嘗試建立或開啟資料庫時。這表示,使用者無法在應用程式中執行任何資料庫相關作業。對於特定類型的錯誤,例如唯讀或權限錯誤,其中一個可能的復原技巧是將資料庫檔案複製至不同的位置。應用程式可以將資料庫檔案複製至使用者確實具有權限的不同位置,以建立及寫入至檔案,並改用該位置。
語法錯誤
SQL 陳述式格式不正確,而應用程式卻嘗試執行該陳述式時,便會發生語法錯誤。由於本機資料庫 SQL 陳述式會建立為字串,因此無法進行編譯階段 SQL 語法檢查。原因在於,所有 SQL 陳述式都必須先被執行,才能檢查其語法。您可以使用下列策略來防止 SQL 語法錯誤:
- 徹底測試所有 SQL 陳述式
- 可能的話,請先在開發應用程式時另行測試 SQL 陳述式,再將陳述式編寫為應用程式程式碼的陳述式文字。此外,您也能使用程式碼測試手法 (例如單位測試),建立一組測試,執行程式碼中每一項可能的選項和變化。
- 使用陳述式參數並避免組合 (以動態方式產生的) SQL
- 請使用參數並避免以動態方式建立 SQL 陳述式,也就是,在每次執行陳述式時使用相同的 SQL 陳述式文字。這能讓您輕鬆測試您的陳述式,並限制可能的變化。如果您必須以動態方式產生 SQL 陳述式,請將陳述式的動態部分維持在最低限度。同時,請仔細驗證任何使用者輸入,以確保不會造成語法錯誤。
若要從語法錯誤中復原,應用程式需要複雜的邏輯,才能夠檢查 SQL 陳述式並修正其語法。若能遵循上述有關防止語法錯誤的準則,您的程式碼便能識別 SQL 語法錯誤 (例如使用者輸入用於陳述式中) 的在執行階段的任何潛在來源。若要從語法錯誤復原,請為使用者提供準則。請指出應該修正哪些錯誤,才能讓陳述式正常執行。
限制錯誤
INSERT 或 UPDATE 陳述式嘗試將資料加入至欄時,便會發生限制錯誤。如果新資料違反為資料表或欄定義的其中一項限制,就會發生錯誤。可能的限制組合包括:
- 唯一限制
- 指出資料表的所有列中,一個欄不可以有重複的值。或者,在唯一限制中,當多個欄結合時,這些欄的值組合不可以重複。換句話說,就指定的一個或多個唯一欄而言,每個列都必須不同。
- 主索引鍵限制
- 就限制允許與不允許的資料而言,主索引鍵限制與唯一限制完全相同。
- 非 null 限制
- 指定單一欄無法儲存 NULL 值,因此在每個列中,該欄都必須有值。
- 檢查限制
- 讓您可在一個或多個資料表上指定任意限制。其中一種常見的檢查限制為定義該欄的值必須在特定範圍之內的規則 (例如,數值欄的值必須大於 0)。另一種常見檢查限制會指定欄值之間的關係 (例如,欄的值必須與相同列中其它欄的值不同)。
- 資料類型 (欄相似性) 限制
- 執行階段會強制套用欄值的資料類型,如果嘗試在欄中儲存不正確類型的值,就會發生錯誤。但是,在許多情況下,值會進行轉換,以便與欄的宣告資料類型相符。如需詳細資訊,請參閱使用資料庫資料類型。
執行階段不會在外部索引鍵值上強制套用限制。換句話說,外部索引鍵值不需要與現有主索引鍵值相符。
除了預先定義的限制類型以外,執行階段 SQL 引擎也支援使用觸發程序。觸發程序與事件處理常式類似。它是預先定義的一組指示,會在發生特定動作時執行。例如,可以定義觸發程序,在資料插入特定資料表或從中刪除時執行。觸發程序的其中一個可能用法,就是檢查資料變更,而且如果未符合指定的條件,就會發生錯誤。因此,觸發程序可以與限制達到相同的目的,防止限制錯誤並從錯誤中復原的策略也適用於觸發程序產生的錯誤。但是,觸發程序所產生錯誤的錯誤 ID 與限制錯誤的錯誤 ID 不同。
適用於特定資料表的這組限制會在您設計應用程式的階段決定。仔細地設計限制,有助於簡化應用程式的設計,也能預防限制錯誤並從限制錯誤中復原。但是,限制錯誤很難以系統化的方式加以預測及避免。難以預測的原因在於,限制錯誤在加入應用程式資料之前不會出現。限制錯誤會與建立資料庫之後加入的資料一起發生。這些錯誤往往是新資料與資料庫中現有資料之間建立關聯所造成的結果。下列策略可以協助您避免許多限制錯誤:
- 仔細規劃資料庫結構與限制
- 限制的目的是強制套用應用程式規則,並協助保護資料庫資料的完整性。當您規劃應用程式時,請考慮如何建立您的資料庫結構以支援您的應用程式。該程序的其中一部分是找出資料的規則,例如是否需要特定值、值是否為預設值、是否允許重複的值等等。這些規則可以引導您定義資料庫限制。
- 明確指定欄名稱
- 您可以撰寫 INSERT 陳述式且不明確指定要插入欄中的值,但是這種做法會產生不必要的風險。透過明確命名要插入值的欄,您可以允許自動產生值、使用預設值的欄,以及允許 NULL 值的欄。此外,這麼做的話,您就可以確保所有 NOT NULL 欄都已插入明確的值。
- 使用預設值
- 當您為欄指定 NOT NULL 限制時,如果可以的話,請在欄定義中指定預設值。應用程式程式碼也可以提供預設值。例如,您的程式碼可以檢查 String 變數是否為 null,並為它指定值,再將它用來設定陳述式參數值。
- 驗證使用者輸入的資料
- 請事先檢查使用者輸入的資料,以確保它遵守由限制所指定的限制,尤其是在 NOT NULL 和 CHECK 限制的情況下。當然,UNIQUE 限制較難檢查,因為進行檢查時需要執行 SELECT 查詢,以判斷資料是否為唯一。
- 使用觸發程序
- 您可以撰寫驗證 (而且可能取代) 插入資料的觸發程序,或採取其它行動來修正無效的資料。這項驗證和修正可以防止限制錯誤發生。
在很多方面,限制錯誤會比其它類型錯誤更難預防。幸運的是,許多策略可以用來從限制錯誤中復原,而且不會造成應用程式不穩定或無法使用:
- 使用衝突演算法
- 當您在欄上定義限制,以及當您建立 INSERT 或 UPDATE 陳述式時,您可以選擇指定衝突演算法。衝突演算法會在發生違反限制的情況時,定義資料庫所採取的行動。資料庫引擎可以採取多項可能的行動。資料庫引擎可以結束單一陳述式或整個交易。它可以忽略錯誤。它甚至可以移除舊資料,然後用程式碼嘗試要儲存的資料取代。
如需詳細資訊,請參閱本機資料庫內的 SQL 支援中的「ON CONFLICT (衝突演算法)」小節。
- 提供正確的回應
- 可能會影響特定 SQL 命令的一組限制是可以事先識別的。因此,您可以預期陳述式可能會造成的限制錯誤。瞭解這點之後,您可以建立應用程式邏輯來回應限制錯誤。例如,假設應用程式包含供輸入新產品的資料輸入表單。如果資料庫中的產品名稱欄是使用 UNIQUE 限制來定義,則將新產品列插入資料庫的動作可能會產生限制錯誤。因此,應用程式會設計用來預期限制錯誤。當錯誤發生時,應用程式會警告使用者,指出指定的產品名稱已經在使用中,並請使用者選擇不同的名稱。另一個可能的回應,則是允許使用者檢視其它名稱相同產品的相關資訊。