2

関数やマクロを使用して、key-value 形式のパラメーターを並べたリストを使用して SQL 文を作成したいと考えています。

例えば: (("id" 3) ("version" 3) ("name" "foo") ("age" 10))

のような文字列を返したい

"insert into table ('id','version','name','age') values(3,3,'foo',10);"

これが私のコードです:

(defvar *param* '(("id" 3) ("version" 3) ("name" "foo") ("age" 10)))

(defun dis (elt)
  (if (stringp elt)
      (concatenate 'string "'" elt "'")
      (write-to-string elt)))

(defun tostring (lst)
  (if (eql 1 (length lst))
      (dis (car lst))
      (concatenate 'string (dis (car lst)) "," (tostring (cdr lst)))))

(defun fillinsert (lst)
  (let ((keys (mapcar #'car lst))
        (values (mapcar #'cadr lst)))
    (concatenate 'string
                 "insert into table ("
                 (tostring keys)
                 ") values("
                 (tostring values)
                 ");")))

文字列を作成するために一度だけリストにアクセスする方法がわかりません。ありがとう

4

3 に答える 3

1

フォーマットソリューションは次のとおりです。

CL-USER>
(setf *entry* '(("id" 3) ("version" 3) ("name" "foo") ("age" 10)))
(("id" 3) ("version" 3) ("name" "foo") ("age" 10))
CL-USER>
(format nil "insert into table (~{~S~^,~}) values (~{~S~^,~});"
        (mapcar #'first *entry*)
        (mapcar #'second *entry*))
"insert into table (\"id\",\"version\",\"name\",\"age\") values (3,3,\"foo\",10);"
CL-USER>

フォーマット文字列は list ( ~{) ディレクティブを使用して、リスト内の項目を指定されたフォーマットで出力します。また、チルダサーカムフレックス ( ~^) ディレクティブを使用して、リストの右端にある最後のコンマの出力を無効にします。format ディレクティブは、~S各オブジェクトが Lisp リーダーで読み込める形式で出力されることを保証します。つまり、文字列は引用符で囲まれますが、数字は引用符で囲まれません。

SQL エンジンが二重引用符を単一引用符と同じように解釈すると仮定しています。一重引用符が必要な場合は、機能させるためにもう少しロジックが必要になります。これを行う 1 つの方法は、フォーマット ディレクティブを拡張し、~文字列を一重引用符で囲む独自のディレクティブを定義することです。しかし、IME のほとんどの SQL エンジンは二重引用符を単一引用符と同じように解釈するため、私はこれを行いませんでした。

于 2013-07-24T05:38:50.223 に答える
0

文字列を作成するために使用loopし、リストを 1 回だけトラバースする場合は、ループの分割機能を使用できます。関数fillinsertは、次のように定義できます。

(defun fillinsert (lst)
  (loop for (key value) in lst
        collect key into keys
        collect value into values
        finally (return (concatenate 'string
                                     "insert into table ("
                                     (tostring keys)
                                     ") values("
                                     (tostring values)
                                      ");")))

または(format文字列を構築するために使用):

(defun fillinsert (lst)
  (loop for (key value) in lst
        collect key into keys
        collect value into values
        finally (return (format nil
                                "insert into table (~a) values (~a);"
                                (tostring keys)
                                (tostring values)))))
于 2013-07-23T22:23:16.120 に答える