2015-05-05 30 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