gpt4 book ai didi

sqlite - 在 Clojure 中通过 clojure.java.jdbc 使用外键约束

转载 作者:行者123 更新时间:2023-12-03 00:38:20 27 4
gpt4 key购买 nike

我正在开发一个 wiki 程序并使用 SQLite 作为数据库。我想在 wiki 页面和描述这些页面的标签之间创建多对多关系。我使用 clojure.java.jdbc 来处理数据库操作。我想在页面到标签交叉引用表中强制执行外键约束。我查看了 SQLite 站点( https://www.sqlite.org/foreignkeys.html )上有关外键的信息,并相信这样的东西就是我想要的;

(def the-db-name "the.db")
(def the-db {:classname "org.sqlite.JDBC"
:subprotocol "sqlite"
:subname the-db-name})

(defn create-some-tables
"Create some tables and a cross-reference table with foreign key constraints."
[]
(try (jdbc/db-do-commands
the-db false
["PRAGMA foreign_keys = ON;"
(jdbc/create-table-ddl :pages
[[:page_id :integer :primary :key]
;...
[:page_content :text]])
(jdbc/create-table-ddl :tags
[[:tag_id :integer :primary :key]
[:tag_name :text "NOT NULL"]])
(jdbc/create-table-ddl :tags_x_pages
[[:x_ref_id :integer :primary :key]
[:tag_id :integer]
[:page_id :integer]
["FOREIGN KEY(tag_id) REFERENCES tags(tag_id)"]
["FOREIGN KEY(page_id) REFERENCES pages(page_id)"]])])

(catch Exception e (println e))))

但是尝试打开编译指示没有效果。

只是尝试打开编译指示并检查效果:

(println "Check before:" (jdbc/query the-db ["PRAGMA foreign_keys;"]))
; Transactions on or off makes no difference.
(println "Result of execute!:" (jdbc/execute! the-db
["PRAGMA foreign_keys = ON;"]))
(println "Check after:" (jdbc/query the-db ["PRAGMA foreign_keys;"]))

;=> Check before: ({:foreign_keys 0})
;=> Result of execute!: [0]
;=> Check after: ({:foreign_keys 0})

结果表明库(org.xerial/sqlite-jdbc“3.21.0.1”)已编译为支持外键,因为没有错误,但尝试设置编译指示没有效果。

我找到了this早在 2012 年,就出现在 clojure JDBC 的 JIRA 中。从那时起,所描述的更改已经实现,但代码仍然没有效果。

终于找到了指向 this post 的 Stackoverflow 问题的答案早在 2011 年。这让我能够拼凑出一些似乎确实设定了实用的东西。下面的代码取决于创建专门配置的连接

(ns example
(:require [clojure.java.jdbc :as jdbc])
(:import (java.sql Connection DriverManager)
(org.sqlite SQLiteConfig)))

(def the-db-name "the.db")
(def the-db {:classname "org.sqlite.JDBC"
:subprotocol "sqlite"
:subname the-db-name})

(defn ^Connection get-connection
"Return a connection to a SQLite database that
enforces foreign key constraints."
[db]
(Class/forName (:classname db))
(let [config (SQLiteConfig.)]
(.enforceForeignKeys config true)
(let [connection (DriverManager/getConnection
(str "jdbc:sqlite:" (:subname db))
(.toProperties config))]
connection)))

(defn exec-foreign-keys-pragma-statement
[db]
(let [con ^Connection (get-connection db)
statement (.createStatement con)]
(println "exec-foreign-keys-pragma-statement:"
(.execute statement "PRAGMA foreign_keys;"))))

基于上述,我将上面的建表代码重写为:

(defn create-some-tables
"Create some tables and a cross-reference table with foreign key constraints."
[]
(when-let [conn (get-connection the-db)]
(try
(jdbc/with-db-connection
[conn the-db]
; Creating the tables with the foreign key constraints works.
(try (jdbc/db-do-commands
the-db false
[(jdbc/create-table-ddl :pages
[[:page_id :integer :primary :key]
[:page_content :text]])
(jdbc/create-table-ddl :tags
[[:tag_id :integer :primary :key]
[:tag_name :text "NOT NULL"]])
(jdbc/create-table-ddl :tags_x_pages
[[:x_ref_id :integer :primary :key]
[:tag_id :integer]
[:page_id :integer]
["FOREIGN KEY(tag_id) REFERENCES tags(tag_id)"]
["FOREIGN KEY(page_id) REFERENCES pages(page_id)"]])])

; This still doesn't work.
(println "After table creation:"
(jdbc/query the-db "PRAGMA foreign_keys;"))

(catch Exception e (println e))))

; This returns the expected results.
(when-let [statement (.createStatement conn)]
(try
(println "After creating some tables: PRAGMA foreign_keys =>"
(.execute statement "PRAGMA foreign_keys;"))
(catch Exception e (println e))
(finally (when statement
(.close statement)))))
(catch Exception e (println e))
(finally (when conn
(.close conn))))))

表已按预期创建。不过,一些 clojure.java.jdbc 函数似乎仍然无法按预期工作。 (请参阅 list 中间的 jdbc/query 调用。)让事情始终按预期工作似乎非常“手动”,必须依靠 java 互操作。似乎与数据库的每次交互都需要使用 get-connection 函数返回的专门配置的 Connection

是否有更好的方法在 Clojure 中的 SQLite 中强制执行外键约束?

最佳答案

随着 next.jdbc 的出现你现在可以这样做:

(ns dev
(:require [next.jdbc :as jdbc]
[next.jdbc.sql :as sql]))

(with-open [conn (jdbc/get-connection {:dbtype "sqlite" :dbname "test.db"})]
(println (sql/query conn ["PRAGMA foreign_keys"]))
(jdbc/execute! conn ["PRAGMA foreign_keys = ON"])
; jdbc/execute whatever you like here...
(println (sql/query conn ["PRAGMA foreign_keys"])))

此输出

[{:foreign_keys 0}]
[{:foreign_keys 1}]

关于sqlite - 在 Clojure 中通过 clojure.java.jdbc 使用外键约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48029392/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com