Yesod/Persistent 中的外键约束?
Foreign key constraints in Yesod/Persistent?
我正在尝试使用 Database.Persistant 为 Scotty 应用程序创建数据库,但我无法弄清楚在 table 之间添加外键约束的语法。例如,我有一个 User
table 和一个 Post
table,我希望 Post
table 有一个属性 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 中的作者属性来引用用户中的现有用户名。
Persistent
使用 Haskell 类型系统生成外键。这就是为什么没有特定的字段类型来指示字段引用另一个 table.
中的记录的原因
您应该使用 Persistent
自动创建的密钥类型来指示密钥。
假设我有 User
和 Article
table。 Persistent
将为您生成 UserId
和 ArticleId
。然后,您将使用它们来指示引用,如本例所示:
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
可能持有对另一个 Article
的引用,其 parent
字段类型为 ArticleId Maybe
。
Article
必须持有对 User
的引用,其中 user
字段类型为 UserId
。
此示例将在 PostgreSQL 中生成以下 article
table:
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
我正在尝试使用 Database.Persistant 为 Scotty 应用程序创建数据库,但我无法弄清楚在 table 之间添加外键约束的语法。例如,我有一个 User
table 和一个 Post
table,我希望 Post
table 有一个属性 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 中的作者属性来引用用户中的现有用户名。
Persistent
使用 Haskell 类型系统生成外键。这就是为什么没有特定的字段类型来指示字段引用另一个 table.
您应该使用 Persistent
自动创建的密钥类型来指示密钥。
假设我有 User
和 Article
table。 Persistent
将为您生成 UserId
和 ArticleId
。然后,您将使用它们来指示引用,如本例所示:
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
可能持有对另一个Article
的引用,其parent
字段类型为ArticleId Maybe
。 Article
必须持有对User
的引用,其中user
字段类型为UserId
。
此示例将在 PostgreSQL 中生成以下 article
table:
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