haskell-persistent:如何在第二个表中使用外键作为主键
Posted
技术标签:
【中文标题】haskell-persistent:如何在第二个表中使用外键作为主键【英文标题】:haskell-persistent: how to use a foreign key as primary key in a second table 【发布时间】:2016-12-23 10:38:34 【问题描述】:更新 - 找到了错误的根本原因 - 但不知道如何解决它
我刚刚发现这种行为的根源不是使用sql=…
引起的,而是我使用第一个表的主键作为外部和主键。
Post
topic String
deriving Show Eq
PostContent
Id PostId
content String
deriving Show Eq
所以问题仍然存在:
我可以以某种方式持久地表示主键是外键吗? - 从 SQL 的角度来看,这是有道理的(至少我是这么认为的)?
原创
我正在将 simon marlow Fun With HAXL pt1 的 haxl 示例移植到 oracle/docker - 以进行概念验证。
我正在使用现有的 sql 脚本来生成数据库(在现实世界的情况下,我没有数据库表) - 我有以下数据库布局
表发布信息
| POSTID NUMBER | POSTDATE DATE | POSTTOPIC VARCHAR2(512 CHAR) |
表后内容
| POSTID NUMBER | CONTENT CLOB |
表后视图
| POSTID NUMBER | VIEWS INT |
当然我想在对应的haskell持久化QuasiQuoter
中表达POSTID
是postcontent
和postview
中的外键和唯一键的关系。在维基链接的yesod-book、wiki 和test cases 之后。
我创建了以下模板 haskell 拼接:
share [ mkPersist sqlSettings mpsGeneric = False , mkMigrate "compositeMigrate" , mkDeleteCascade sqlSettings mpsGeneric = False] [persistUpperCase|
Post sql=POSTINFO
Id Int sql=POSTID
date UTCTime sql=POSTDATE
topic Text sql=POSTTOPIC
deriving Show Eq
PostContent sql=POSTCONTENT
Id PostId sql=POSTID
content Text sql=CONTENT
deriving Show Eq
PostViews sql=POSTVIEWS
Id PostId sql=POSTID
views Int sql=VIEWS
deriving Show Eq
|]
编译出错
error:
• Not in scope: type constructor or class ‘PostId’
• In the quasi-quotation:
[persistUpperCase|
Post sql=POSTINFO
Id Int sql=POSTID
date UTCTime sql=POSTDATE
topic Text sql=POSTTOPIC
deriving Show Eq
PostContent
Id PostId sql=POSTID
content Text sql=CONTENT
deriving Show Eq
PostViews
Id PostId sql=POSTID
views Int sql=VIEWS
deriving Show Eq
|]
要注意以下测试用例准引用器 - 有效,
Citizen
name String
age Int Maybe
deriving Eq Show
Address
address String
country String
deriving Eq Show
CitizenAddress
citizen CitizenId
address AddressId
Primary citizen address
deriving Eq Show
这是一个最小的示例,它重现了错误和一些刚刚运行的工作版本(并相应地更改 #define
行
> stack runhaskell --package persistent-template minimal.hs
minimal.hs
-# LANGUAGE FlexibleInstances #-
-# LANGUAGE GADTs #-
-# LANGUAGE GeneralizedNewtypeDeriving #-
-# LANGUAGE MultiParamTypeClasses #-
-# LANGUAGE QuasiQuotes #-
-# LANGUAGE TemplateHaskell #-
-# LANGUAGE TypeFamilies #-
-# LANGUAGE CPP #-
module Minimal where
import Database.Persist.TH
#define FAILS
main :: IO ()
main = putStrLn "It works"
#ifdef WORKS
share [ mkPersist sqlSettings mpsGeneric = False , mkMigrate "compositeMigrate" , mkDeleteCascade sqlSettings mpsGeneric = False] [persistUpperCase|
Post sql=POSTINFO
Id Int sql=POSTID
topic String sql=POSTTOPIC
deriving Show Eq
|]
#endif
#ifdef ALSOWORKS
share [ mkPersist sqlSettings mpsGeneric = False , mkMigrate "compositeMigrate" , mkDeleteCascade sqlSettings mpsGeneric = False] [persistUpperCase|
Post sql=POSTINFO
Id Int sql=POSTID
topic String sql=POSTTOPIC
deriving Show Eq
PostContent sql=POSTCONTENT
post PostId sql=POSTID
content String sql=POSTCONTENT
deriving Show Eq
|]
#endif
#ifdef FAILS
share [ mkPersist sqlSettings mpsGeneric = False , mkMigrate "compositeMigrate" , mkDeleteCascade sqlSettings mpsGeneric = False] [persistUpperCase|
Post sql=POSTINFO
Id Int sql=POSTID
topic String sql=POSTTOPIC
deriving Show Eq
PostContent sql=POSTCONTENT
Id PostId sql=POSTID
content String sql=POSTCONTENT
deriving Show Eq
|]
#endif
-- UPDATE
#ifdef FAILSTOO
share [ mkPersist sqlSettings mpsGeneric = False , mkMigrate "compositeMigrate" , mkDeleteCascade sqlSettings mpsGeneric = False] [persistUpperCase|
Post
topic String
deriving Show Eq
PostContent
Id PostId
content String
deriving Show Eq
|]
#endif
【问题讨论】:
我认为您应该将其作为单独的答案发布,而不是编辑您的问题。 我认为我找到了原因-但我不知道如何解决-绝对是用词错误 啊,好的。一个明显的问题:您知道 Oracle 没有持久绑定吗? 嗯 - 我已经开始使用 persistent-odbc - 我花了一段时间,但我设法将查询从 Haskell 发送到 Oracle 数据库。 【参考方案1】:我可以以某种方式持久地表示主键是外键吗?
是的。假设 Sqlite 作为数据库的示例代码示例:
#!/usr/bin/env stack
- stack
--resolver lts-7.14
--install-ghc
runghc
--package yesod
--package yesod-core
--package blaze-html
--package text
--package persistent
--package persistent-template
--package persistent-sqlite
--package shakespeare
--package aeson
-
-# LANGUAGE EmptyDataDecls #-
-# LANGUAGE FlexibleContexts #-
-# LANGUAGE GADTs #-
-# LANGUAGE GeneralizedNewtypeDeriving #-
-# LANGUAGE MultiParamTypeClasses #-
-# LANGUAGE OverloadedStrings #-
-# LANGUAGE QuasiQuotes #-
-# LANGUAGE TemplateHaskell #-
-# LANGUAGE TypeFamilies #-
import Control.Monad.IO.Class (liftIO)
import Control.Monad.Logger (runStderrLoggingT)
import Database.Persist
import Database.Persist.Sqlite
import Database.Persist.TH
share
[mkPersist sqlSettings, mkMigrate "migrateAll"]
[persistLowerCase|
Post
topic String
deriving Show
PostContent
pid PostId
Primary pid
deriving Show
|]
main :: IO ()
main = mockMigration migrateAll
在执行时,你会得到这个:
CREATE TABLE "post"("id" INTEGER PRIMARY KEY,"topic" VARCHAR NOT NULL)
CREATE TABLE "post_content"("pid" INTEGER NOT NULL REFERENCES "post", PRIMARY KEY ("pid"))
在上面的例子中可以看到post_content
表中的pid
列既是主键也是外键。
【讨论】:
以上是关于haskell-persistent:如何在第二个表中使用外键作为主键的主要内容,如果未能解决你的问题,请参考以下文章
如何在第二个 ViewController 表格视图中使用模型快速显示第一个 ViewController 值
我如何在 android 中显示从 listView 到第二个活动的相同数据,如果我点击 google,它会在第二个活动中显示 google