2015-05-05 3 views
2

Я пытаюсь использовать Database.Persistant для создания базы данных для приложения Scotty, и я не могу понять синтаксис для добавления ограничения внешнего ключа между таблицами. Например, у меня есть таблица User и таблица Post, и я хочу, чтобы таблица Post имела атрибут authorId, который ссылается на UserId в User. Это можно сделать довольно легко в необработанном SQL, но я хочу иметь доступ к данным через haskell, не прибегая к необработанным командам sql. Кроме того, ограничения будут перезаписываться при миграции базы данных. Это то, что у меня есть на данный момент, чтобы определить базу данных:Внешние ограничения ключа в Yesod/Persistent?

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, он компилируется в порядке, но ничего не происходит; миграция не происходит, и никаких ограничений внешнего ключа не вводится.

Что я делаю неправильно? Любая помощь или рекомендации были бы весьма признательны.

Чтобы быть ясным, я хочу, чтобы атрибут author в Post ссылался на существующее имя пользователя в User.

ответ

7

Persistent использует систему типа Haskell для генерации внешних ключей. Вот почему нет определенного типа поля, чтобы указать, что поле ссылается на запись в другой таблице.

Вы должны использовать тип ключа, который Persistent создан автоматически для указания ключа.

Скажем, у меня есть User и Article столов. 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.

Этот пример будет генерировать следующий article таблицы в PostgreSQL:

   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

+0

Спасибо, это имеет смысл. Что касается того, что sqlite не соблюдает ограничения внешнего ключа, это раздражает, но я буду изучать его. Может потребоваться перейти к postgres или mysql. – asg0451

+0

Существует также страница, рассказывающая о внешних ключах в SQLite на GitHub https://github.com/yesodweb/yesod/wiki/Activate-foreign-key-checking-in-Sqlite – zigazou