Search code examples
common-lispclsql

How to insert multiple records at once using the clsql provided FDML


Is there a way of using the given FDML interface to insert multiple records at once?

The given insert-record statement can only handle one value tuple at once and the idea of calling this function uncountable times, instead of once is bugging me quite a bit, and I guess (without actually having done any profiling) that this would not be the fastest approach either.


Solution

  • How about something like this?

    ; SLIME 2013-04-02
    CL-USER> (ql:quickload "clsql")
    To load "clsql":
      Load 1 ASDF system:
        uffi
      Install 1 Quicklisp release:
        clsql
    ; Fetching #<URL "http://beta.quicklisp.org/archive/clsql/2013-04-20/clsql-20130420-git.tgz">
    ; 900.99KB
    ==================================================
    922,610 bytes in 1.92 seconds (468.78KB/sec)
    ; Loading "clsql"
    [package uffi]....................................
    [package cmucl-compat]............................
    [package clsql-sys]...............................
    [package clsql]...................................
    [package clsql-user]..............................
    ..................................................
    [package ansi-loop]..............................
    ("clsql")
    CL-USER> (ql:quickload "clsql-sqlite3")
    To load "clsql-sqlite3":
      Load 1 ASDF system:
        clsql-sqlite3
    ; Loading "clsql-sqlite3"
    [package clsql-uffi]..............................
    [package clsql-sqlite3]...........................
    [package sqlite3]........
    ("clsql-sqlite3")
    CL-USER> (clsql:connect '("./test.db") :database-type :sqlite3)
    #<CLSQL-SQLITE3:SQLITE3-DATABASE ./test.db OPEN {10080C08E3}>
    CL-USER> (clsql:enable-sql-reader-syntax)
    ; No value
    CL-USER> (clsql:create-table [test_insert]
                                 '(([id] integer)
                                   ([first_name] text)
                                   ([last_name] text)))
    ; No value
    CL-USER> (clsql:insert-records :into [test_insert]
                                   :attributes '(id first_name last_name)
                                   :values '(0 "John" "Neumann"))
    ; No value
    CL-USER> (clsql:select [id] [first_name] [last_name] :from [test_insert])
    ((0 "John" "Neumann"))
    ("ID" "FIRST_NAME" "LAST_NAME")
    CL-USER> (clsql:insert-records
               :into [test_insert]
               :attributes '(id first_name last_name)
               :query (clsql:sql-expression :string
               "select 1 as id, 'Albert' as first_name, 'Einstein' as last_name
                union select 2, 'Alan', 'Turing'"))
    ; No value
    CL-USER> (clsql:select [id] [first_name] [last_name] :from [test_insert])
    ((0 "John" "Neumann") (1 "Albert" "Einstein") (2 "Alan" "Turing"))
    ("ID" "FIRST_NAME" "LAST_NAME")
    

    Maybe you could construct the insertion query in some other way (other databases may provide different syntax). clsql has (or, more properly has not) a syntax for column renaming... so you'd have to manipulate strings / extend it to have it use symbols instead.