2015-05-05 29 views
2

我想使用Database.Persistant爲Scotty應用程序創建數據庫,並且我無法弄清楚在表之間添加外鍵約束的語法。例如,我有一個User表和Post表,並且我希望Post表的屬性爲authorId,其參考User中的UserId。這可以很容易地在原始SQL中完成,但是我希望能夠通過haskell訪問數據而不訴諸原始的sql命令。此外,約束將覆蓋數據庫遷移。這是我目前所面對的定義數據庫:Yesod/Persistent中的外鍵約束?

share [mkPersist sqlSettings, mkMigrate "migrateAll"] 
[persistLowerCase| 
    User 
    name String 
    email String 
    username String 
    Primary username 
    deriving Show 
    Post 
    title String 
    content T.Text 
    author String 
    deriving Show 
|] 

這是好的,但沒有主要制約因素,它可以是一個非常糟糕的事情。 如果我嘗試添加外鍵約束如the wiki on github說,通過將Foreign User authorfk author行添加到Post塊,它編譯得很好,但沒有任何反應;不會發生遷移,也不會引入外鍵約束。

我在做什麼錯?任何援助或建議將不勝感激。

要清楚,我想要的是Post中的作者屬性以引用User中的現有用戶名。

回答

7

Persistent使用Haskell類型系統來生成外鍵。這就是爲什麼沒有特定的字段類型來指示一個字段引用另一個表中的記錄。

您應該使用Persistent自動創建的密鑰類型來指示密鑰。

說我有UserArticle表。 Persistent會爲您生成UserIdArticleId。然後,您將使用它們來表示就像這個例子引用:

User 
    username Text 
    password Text 
    email  Text 
    description Text Maybe 
    active  Bool 

    UniqueUser username 
    UniqueEmail email 

    deriving Typeable 

Article 
    artname  Text 
    title  Text 
    keywords Text Maybe 
    description Text Maybe 
    body  Markdown 
    parent  ArticleId Maybe -- optional Foreign Key 
    user  UserId   -- required Foreign Key 
    lastUpdate UTCTime 
    weight  Int 
    public  Bool 

    UniqueArt artname 

    deriving Typeable 

這個模型說:

  • Article可以就此與ArticleId Maybe類型的parent字段的引用到另一個Article
  • Article必須對Useruser字段UserId的字段具有參考。

這個例子將產生如下表article PostgreSQL中:

   Table "public.article" 
    Column |   Type   | Modifiers 
-------------+--------------------------+---------------- 
id   | integer     | not null (...) 
artname  | character varying  | not null 
title  | character varying  | not null 
body  | character varying  | not null 
parent  | bigint     | 
user  | bigint     | not null 
last_update | timestamp with time zone | not null 
weight  | bigint     | not null 
public  | boolean     | not null 
keywords | character varying  | 
description | character varying  | 

Indexes: 
    "article_pkey" PRIMARY KEY, btree (id) 
    "unique_art" UNIQUE CONSTRAINT, btree (artname) 
Foreign-key constraints: 
    "article_parent_fkey" FOREIGN KEY (parent) 
          REFERENCES article(id) 
    "article_user_fkey" FOREIGN KEY ("user") 
         REFERENCES "user"(id) 
Referenced by: 
    TABLE "article" CONSTRAINT "article_parent_fkey" 
        FOREIGN KEY (parent) 
        REFERENCES article(id) 

注:如果您使用SQLite,你必須確保外鍵的支持已啓用。請參閱→SQLite Foreign Key Support: Enabling Foreign Key Support

+0

謝謝,這很有道理。至於sqlite不尊重外鍵約束,這很煩人,但我會研究它。可能不得不切換到postgres或mysql。 – asg0451

+0

還有一個頁面在GitHub上的SQLite中討論外鍵https://github.com/yesodweb/yesod/wiki/Activate-foreign-key-checking-in-Sqlite – zigazou