Yesod / Persistent中的外键约束?

Posted

技术标签:

【中文标题】Yesod / Persistent中的外键约束?【英文标题】:Foreign key constraints in Yesod/Persistent? 【发布时间】:2015-05-05 20:30:56 【问题描述】:

我正在尝试使用 Database.Persistant 为 Scotty 应用程序创建数据库,但我无法弄清楚在表之间添加外键约束的语法。例如,我有一个User 表和一个Post 表,我希望Post 表有一个属性authorId,它在User 中引用UserId。这可以在原始 SQL 中很容易地完成,但我希望能够通过 haskell 访问数据,而无需使用原始 sql 命令。此外,约束将在数据库迁移时被覆盖。这是我目前定义数据库的内容:

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 中的 author 属性来引用 User 中的现有用户名。

【问题讨论】:

【参考方案1】:

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 可以使用 parent 类型为 ArticleId Maybe 的字段引用另一个 ArticleArticle 必须持有对 User 的引用,其中 user 字段类型为 UserId

本示例将在 PostgreSQL 中生成以下 article 表:

                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

【讨论】:

谢谢,这很有意义。至于 sqlite 不遵守外键约束,这很烦人,但我会调查一下。可能必须切换到 postgres 或 mysql GitHubgithub.com/yesodweb/yesod/wiki/…上还有一个关于SQLite外键的页面@

以上是关于Yesod / Persistent中的外键约束?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Persistent Haskell 来自现有数据库的外键

创建外键时,phpmyadmin 中的外键约束失败

此表中的外键约束有啥问题?

Laravel-7 迁移中的外键约束形成错误

基本表设计中的外键约束异常

MySQL 中的外键约束错误 1452 - Magento 导入