2010-12-08 75 views
1

我試圖添加一個約束(在Oracle中),這限制了用戶在一個字段中存在'smth','smth else'或'one more thing'的條目。基本上,這就是我將如何寫它:檢查SQL語句中的嵌套查詢

ALTER TABLE sometable 
ADD CONSTRAINT sometable_text_chk 
CHECK (
    caption IN ( 
     SELECT caption 
     FROM sometable 
     WHERE text NOT IN ('smth', 'smth else', 'one more thing') 
    ) 
) 

不幸的是,它似乎不被允許巢這個場合的查詢。有沒有解決方法。

+0

這不太清楚 - 字段'text`和`caption`之間的關係是什麼?當你說'限制用戶創建條目時,你是什麼意思......在一個領域已經存在'? (你是否想要在字段`caption`中有獨特的值????) – Unreason 2010-12-08 15:47:56

回答

2

基本上,您正試圖基於另一個表中的數據對一個表中的數據的有效性進行某種常規檢查(注意:實際上可能不是,等待OP澄清他的問題)。

解決方法可以是:

  • 一般情況下 - 你可以做相當多的內部觸發複雜的數據驗證的條款(包括將你的數據庫停頓,即使是最簡單的更新查詢的,所以在使用小心點)
  • 對於一個更具體的情況,你試圖完成一些動態驗證(一個更有代表性的例子會有用) - 你可以動態地維護CHECK約束和驗證的'快照'向下保留檢查語句中引用的表的副本,所以它非常難看)
  • 也許你可以做一個外鍵檢查。這不是你通常設計數據庫的方式,但是如果你從語義上看它 - 你聲稱(用你的CHECK)這個表和其他實體之間有關係。那麼,如果這個實體不是作爲單獨的表格實現的,也許它應該是? (這類問題有有時指標設計不好)
0

不能添加這樣的CHECK約束,則需要從字面上提供可能值的整個列表:

CHECK (caption IN (Word1, Word2, Word3 ...)) 

但是您可以在其他的方式做:

CHECK (Caption <> 'smth' and caption <> 'smth else' and caption <> 'one more thing') 

但是你從丟失支票sometable。

1
ALTER TABLE sometable 
ADD CONSTRAINT sometable_text_chk 
CHECK (text not in ('smth', 'smth else', 'one more thing')) 
/

Regards, Rob。

+0

這就是我最初的想法,但要求更復雜一些......你需要在查找表中找到值,而不是關鍵本身 – 2010-12-08 15:17:50

0

我承認這可能是矯枉過正。如果你可以創建一個快速刷新,刷新上提交物化視圖與定義,也要算壞值的數量在你的表,(可能像下圖):

select count(*) as rows_with_errors 
    from data_table a 
    join lookup_table b on(a.caption = b.caption); 

查詢應返回計數爲零,因爲data_table中的值可能不包含lookup_table中的值。然後你在物化視圖本身上創建一個檢查約束,CHECK(rows_with_errors = 0)。

無論何時將更新或插入提交到data_table,實例化視圖都會刷新。但是(並且這是事物),如果你在lookup_table中存在的data_table中輸入了一個值,count(*)將返回一個非零值,這將導致物化視圖上的檢查約束失敗,因此整個插入/更新語句將失敗/回滾。瞧!