The Will Will Web

記載著 Will 在網路世界的學習心得與技術分享

開發SQL相關應用程式時要注意登入帳號的預設結構描述

上週我經手一個案子,客戶原本將網站架設在自己公司,且運作正常好一段時間了,但最近將網站與資料庫搬遷到戰國策之後卻發現有部分程式無法執行了。因為這已經是結案的案子,所以客戶原本想自行解決這個問題,但在嘗試了一整天之後才請我幫他找問題。

首先,這個網站在我的電腦與公司的測試主機都可以正常執行,但當我將資料庫連線切換到戰國策提供的 SQL Server 主機之後就會出現異常,錯誤訊息如下:

System.Data.ConstraintException: 
  無法啟用條件約束。一或多個資料列的值違反非 Null、唯一或外部索引鍵條件約束。

又是這種「萬用錯誤訊息」,這種 Exception 錯誤訊息應該是 ASP.NET 初學者最怕的吧,完全不知道該從何下手解決問題。

因為是 Typed DataSet 在取得資料時出現的問題,且程式「曾經」跑過一段時間都沒問題,是在切換到不同資料庫時才發生問題的,所以我直覺的研判程式部分應該沒問題,所以我就打算直接從資料庫著手調查原因。

經過十幾分鐘的奮戰,我發現原來是戰國策所開給我們客戶的 SQL Server 登入帳號所對應到資料庫中的使用者,被指派了一個跟帳號同名預設結構描述(Default Schema),但我查了一下我們寫的程式,在 Typed DataSet 中的 TableAdapter 中的查詢設定,並沒有特別在 T-SQL 中指令結構描述(Schema),所以我們預期所有表格都應該使用 dbo 這個預設的結構描述才對。

例如以下語法:

SELECT * FROM members WHERE enabled=1

在 SQL Server 中預設會轉成這樣子來執行:

SELECT * FROM dbo.members WHERE enabled=1

不過客戶從轉移主機之後,該資料庫裡的使用者卻被指定了與帳號同名的預設結構描述(例如:user1),而這樣的設定值導致我們的程式中的 T-SQL 被轉成以下:

SELECT * FROM user1.members WHERE enabled=1

所以才會找不到表格,或找到不同結構描述但表格名稱相同的表格而出現錯誤。

所以這告訴我兩個實務經驗:

  1. 在開發與 SQL Server 相關的應用程式時,所下的任何 T-SQL 語法都應該加上適當的「結構描述」(Schema),以免相同的問題再度發生。
  2. 資料庫在轉移或重建的時候,要特別注意資料庫使用者的相關設定是否跟原來的一樣,尤其是「預設結構描述」的部分最有可能影響應用程式的運作!

修改預設結構描述的方式如下:

修改預設結構描述的方式 

查看目前使用者的「預設結構描述」設定:

資料庫使用者 - test

最後將預設結構描述修改為 dbo 即可。