PostgreSQL中使用CLSQL自动生成主键

4

我正在尝试使用Common Lisp ORM创建一个简单的数据库。我使用PostgreSQL和CLSQL。我可以创建类并生成表格,但是当我想要插入一个没有主键以获得生成值的值时,它不起作用。似乎在mysql数据库中可以工作。在PostgreSQL中是否可能实现这一点?

我将主键定义为:

(id :db-kind :key
    :db-type "serial" 
    :db-constraints (:not-null :unique)
    :type integer
    :initarg :id)

并且我收到了这个错误:
While accessing database #<POSTGRESQL-DATABASE localhost/cl_ormex/postgres OPEN {1004FCC403}>
  with expression "SELECT currval ('NIL')":
   Error 42P01 / relation "nil" does not exist
   LINE 1: SELECT currval ('NIL')
                           ^  
 has occurred.
   [Condition of type SQL-DATABASE-DATA-ERROR]

我使用PostgreSQL 9.5.2和SBCL 1.3.1。 编辑 这里有一个示例:
(require 'clsql)
(defpackage :orm-ex (:use :cl :clsql))
(in-package :orm-ex)
(file-enable-sql-reader-syntax)
(enable-sql-reader-syntax)
(setf *default-caching* nil)
(connect '("localhost" "examp" "postgres" "postgres")
     :database-type :postgresql)

(def-view-class person ()
  ((id :db-kind :key
       :db-type "serial"
       :db-constraints (:not-null :unique)
       :type integer
       :initarg :id
       :accessor person-id)
   (name :type (varchar 30)
     :initarg :name
     :accessor person-name)))

(defparameter person1
  (make-instance 'person
         :name "Matt"))

(dolist (c '(person)) (create-view-from-class c))
(update-records-from-instance person1)

我不太明白这个错误,但是该行似乎已经插入到数据库中了。


一个完整的、最小化的示例会很有帮助,同时也需要堆栈跟踪信息。 - Svante
好的。我添加了一个例子... - andrei-n
实际上,我注意到所有字段都被插入了(包括id),但是对象中的id槽仍然未定义... - andrei-n
2个回答

3

从Mark Watson的《Loving Lisp》中得知,db-constraints需要用:auto-increment进行定义。
注意 - 截至今天(2019年10月25日)的书籍版本不正确,但下载的代码是正确的。

(clsql:def-view-class article ()
  ((id
    :db-kind :key
    :db-constraints (:auto-increment :not-null :unique)
    :type integer
    :initarg :id)
   (uri
    :accessor uri
    :type (string 60)
    :initarg :uri)
   (title
    :accessor title
    :type (string 90)
    :initarg :title)
   (text
    :accessor text
    :type (string 500)
    :nulls-ok t
    :initarg :text)))

我还应该指出,如果您创建了没有上述约束条件的表格,则需要更新其属性。在我的情况下,其中没有数据,因此我将其删除并使用新的类详细信息从lisp重新创建它。 - paulj

1

看起来这样做行不通。它有一个待办事项文件,上面写着:

  • 测试“:db-kind:key”是否为该键添加了索引。这很复杂,因为不同的后端以不同的方式显示自动生成的主键。

所以也许它与Postgres不兼容。我相信你有很多选择。

使用其他更新一些的框架,例如cl-dbi,在这里查看:

cl-dbi提供了一个统一的接口,用于连接各种数据库服务器特定的库(如cl-postgres、cl-mysql等)。SxQL提供了一种DSL来构建安全的、自动参数化的SQL查询。

目前有两个相当完整的ORM:Crane和Integral,分别由我和cl-dbi的作者开发。

整合:
不鼓励使用除cl-dbi以外的任何东西。

未来工作:

存在其他数据库系统(例如Oracle)的绑定。编写cl-dbi的驱动程序将是最好的行动方向,并有助于整合。

我发现使用时间戳可以轻松生成按创建时间升序或降序排序的ID,也可以使用生成器或考虑插入的最后一个数字。但这样做就可以了,使用通用时间并添加一个随机数,以便同时创建多个实体并具有较低的冲突率。
(format nil "~12,'0d-~6,'0d" (get-universal-time) (random 1000000))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接