2011-10-30 2 views
2

sqlite 데이터베이스에서 메타 데이터를 가져 오려고합니다. 그 순간의 주요 목적은 테이블 목록을 얻는 것이 었습니다. (: link 여기에서) 아래Clojure : 데이터베이스의 메타 데이터 읽기

코드

(defn db-get-tables 
"Demonstrate getting table info" 
[] 
(sql/with-connection db 
    (into [] 
     (resultset-seq 
     (-> (sql/connection) 
      (.getMetaData) 
      (.getTables nil nil nil (into-array ["TABLE" "VIEW"]))))))) 

이 나에게 데이터베이스의 테이블에 대한 메타 데이터와지도의 목록을 제공합니다. 나는이 목록을 반복하려고 ('에 대한'사용 또는 '첫 번째') 그러나 그것은 나를 제공 :

"Don't know how to create ISeq from proj00.operations.database$tables-list" 

내가 이렇게 쉬운 방법이있을 것으로 생각합니다. 하지만 웹에서 올바른 정보를 찾을 수 없습니다. 또한, 나는 그 오류가 어디서 왔는지 이해할 수 없다.

답변

4

데이터베이스와의 연결이 "sql/with connection db"범위 내에서만 열려 있기 때문일 수 있습니다. Microsoft SQL을 사용하여 이와 같은 컬렉션을 반복하면 연결이 닫히는 오류가 발생합니다.

doetall에서 resultset-seq를 래핑하는 경우이 문제가 수정되어야합니다. 이렇게하면 모든 결과를 메모리에 저장하고 연결을 닫을 수 있다는 장점이 있지만 게으르지 않게됩니다. lazyness를 유지하려면 "with-connection"범위 내에서 반복을 넣어야하지만, 완료 될 때까지 연결을 유지합니다. 이제와 메타 데이터를 호출 할 수 있도록

(defmacro get-sql-metadata [db method & args] 
    `(with-connection 
    ~db 
    (doall 
     (resultset-seq 
     (~method 
      (.getMetaData (connection)) 
      [email protected]))))) 

: 또한

, 당신은 (내 질문에 Verneri Åberg의 대답 덕분에)이의 매크로를 만들어 모든 메타 데이터 방식을 지원에이 기능을 일반화 할 수 있습니다 그래서 같은 메타 데이터 방법과 자신의 매개 변수 :

(get-sql-metadata db .getTables nil nil nil (into-array ["TABLE" "VIEW"])) 
or 
(get-sql-metadata db .getColumns nil nil nil nil) 

추가 답변 : 가 만든이 testdatabase이, 연결, 모든 것이 이런 식으로 작동합니다.

Leiningen

(defproject sqlitetest "1.0.0-SNAPSHOT" 
    :description "FIXME: write description" 
    :dependencies [[org.clojure/clojure "1.3.0"] 
        [org.xerial/sqlite-jdbc "3.6.16"] 
        [org.clojure/java.jdbc "0.1.0"]]) 

프로그램

(ns sqlitetest 
    (:use [clojure.java.jdbc])) 

(def db { :classname "org.sqlite.JDBC" 
      :subprotocol "sqlite" 
      :subname "E:/temp/chinook.db"}) 

(defmacro get-sql-metadata [db method & args] 
    `(with-connection 
    ~db 
    (doall 
     (resultset-seq 
     (~method 
      (.getMetaData (connection)) 
      [email protected]))))) 

(def tables-list 
    (get-sql-metadata db .getTables nil nil nil (into-array ["TABLE" "VIEW"]))) 

REPL

sqlitetest=>(map :table_name tables-list) 
("SQLITE_SEQUENCE" "ALBUM" "ARTIST" "CUSTOMER" "EMPLOYEE" "GENRE" "INVOICE" "INVOICELINE" "MEDIATYPE" "PLAYLIST" "PLAYLISTTRACK" "TRACK") 

sqlitetest=>(first tables-list) 
{:self_referencing_col_name nil, :table_name "SQLITE_SEQUENCE", :type_schem nil, :ref_generation nil, :table_type "TABLE", :table_schem nil, :table_cat nil, :type_cat nil, :type_name nil, :remarks nil} 

귀하의 코멘트에 비와 오류는 defn이 대신 데프의 수행으로 인해 발생 질문에 답변 탁자 위에 귀하의 의견과 마찬가지로 전자 목록. defn을 사용하면 같은 오류가 발생합니다.

+0

감사합니다 Nielsk, 큰 도움이됩니다. 그러나, 매크로 호출을 감싸는 경우에도 동일한 실수가 계속 발생합니다. (defn tables-list [] (get-sql-metadata db.getTables nil nil nil (into 배열 [ "TABLE" "VIEW "]))) – kfk

+0

완벽합니다. 설명을 주셔서 감사합니다. 나는 그 개념에 대해 아주 새로운 것입니다. – kfk

+0

같은, 아직 내 머리를 다 잡으려고 노력하고있어. 다행스러워! 오, 대답이 맞으면 녹색 체크 표시를 할 수 있습니다 :) – NielsK

관련 문제