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

Posted

技术标签:

【中文标题】使用 Persistent Haskell 来自现有数据库的外键【英文标题】:Foreign Key from an existing database with Persistent Haskell 【发布时间】:2016-05-12 09:10:06 【问题描述】:

我目前正在使用 Haskell 和 Persistent 开展一个项目,并且遇到了一个小问题。我想编写一个小库来处理一种通用的身份验证方法,每个用户都获得一个“身份”。

此身份使用持久性存储在数据库中。

Identity
  lastSeen       UTCTime
  registration   UTCTime
  karma          Int DEFAULT=0
  banned         UTCTime Maybe

我的想法是我的 lib 的用户可以将他们的帐户数据类型映射到一个身份。我的问题是,当我将类型 IdentityId 赋予我的用户数据类型的字段时,该列是一个整数(这很好)但缺少引用约束。

例如:

User
  email          Text
  identity       IdentityId
  UniqueIdentity identity

我明白了:

Migrating: CREATE TABLE "identity"("id" INTEGER PRIMARY KEY,"last_seen" TIMESTAMP NOT NULL,"registration" TIMESTAMP NOT NULL,"karma" INTEGER NOT NULL,"banned" TIMESTAMP NULL)
Migrating: CREATE TABLE "user"("id" INTEGER PRIMARY KEY,"email" VARCHAR NOT NULL,"identity" INTEGER NOT NULL,CONSTRAINT "unique_identity" UNIQUE ("identity"))

诀窍是:用户的定义是在不同的文件中完成的,我想问题就在这里。

我可以做些什么来强制持久添加引用约束吗?

提前谢谢你!

【问题讨论】:

【参考方案1】:

我假设您正在使用 SQLite。 SQLite 支持外键约束,但默认情况下是不开启的。您必须在迁移前打开它们。

SQLite Foreign Key Support: 2. Enabling Foreign Key Support

这是开启它们的 SQLite 命令:

PRAGMA foreign_keys = ON;

您可以通过 Haskell 和 Persistent 使用以下代码打开此 PRAGMA:

import qualified Database.Sqlite as Sqlite
import Database.Persist.Sqlite (createSqlPool, wrapConnection)

enableForeignKeys :: Sqlite.Connection -> IO ()
enableForeignKeys conn = Sqlite.prepare conn "PRAGMA foreign_keys = ON;" >>= void . Sqlite.step

createSqliteBackend :: Text -> LogFunc -> IO SqlBackend
createSqliteBackend connStr logFunc = do
  conn <- Sqlite.open connStr
  enableForeignKeys conn
  wrapConnection conn logFunc

createSqliteBackend 将返回一个 SqlBackend,在打开 foreign_keys Pragma 的情况下运行持久查询。

Yesod Cookbook: Activate foreign key checking in Sqlite

【讨论】:

以上是关于使用 Persistent Haskell 来自现有数据库的外键的主要内容,如果未能解决你的问题,请参考以下文章

“类型变量不明确”在 Haskell Yesod 中使用 Persistent

Haskell Persistent 加入 Esqueleto

Haskell的Persistent sometmes返回500内部服务器错误

Haskell Persistent:可以按包含指定值的字段选择所有行

使用 Persistent 输入与数据库的关系

Haskell Persistent Library - 如何从我的数据库中获取数据到我的前端?