如何通过主键从表排序中进行选择
Posted
技术标签:
【中文标题】如何通过主键从表排序中进行选择【英文标题】:How to select from table ordering by primary key 【发布时间】:2014-11-24 10:26:44 【问题描述】:我有这个 SQLite 持久模式:
share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
Entry
class EntryClass
|]
这映射到以下CREATE TABLE
语句:
CREATE TABLE "entry"
( "id" INTEGER PRIMARY KEY AUTOINCREMENT
, "class" INTEGER NOT NULL);"
我手动添加了AUTOINCREMENT
关键字,以确保标识符始终单调递增。现在我想从数据库中挑选最旧的条目 - 那是标识符最低的条目。
如果我要编写 SQL,我会这样说:
SELECT id, class FROM entry ORDER BY id ASC LIMIT 1
但我在将此查询转换为持久查询时遇到问题。它应该看起来像
nextEntry <- selectFirst [] [Asc EntryId, LimitTo 1]
但这给了我一个语法错误,抱怨没有数据构造函数EntryId
。实际上EntryId
是Database.Persist.Class.PersistEntity.Key Entry
的类型同义词,因此它不能在Asc
数据构造函数中使用,它的类型为forall typ . Asc (EntityField record typ)
。
所以问题是我怎样才能通过表的主键对查询结果进行持久排序?
【问题讨论】:
【参考方案1】:这应该确实有效; EntryId
既是类型又是数据构造函数。例如,下面的代码(刚刚从persistent chapter of the Yesod book 的概要中调整)编译得很好:
-# 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 Database.Persist
import Database.Persist.Sqlite
import Database.Persist.TH
share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
Person
name String
age Int Maybe
deriving Show
|]
main :: IO ()
main = runSqlite ":memory:" $ do
runMigration migrateAll
johnId <- insert $ Person "John Doe" $ Just 35
janeId <- insert $ Person "Jane Doe" Nothing
selectList [] [Asc PersonId] >>= liftIO . mapM_ print
【讨论】:
糟糕,我似乎忘记从实体模块导出数据构造函数EntryId
。在进行适当的导出后,结果证明我的代码编译得很好。我也被生成的模板 haskell 拼接误导了,并没有注意到实际上存在一个只看到类型同义词的 EntryId 数据构造函数。很抱歉:(以上是关于如何通过主键从表排序中进行选择的主要内容,如果未能解决你的问题,请参考以下文章