2012-03-19 49 views
13

看來,SQLite默認情況下不強制執行外鍵。我正在使用sqlitejdbc-v056.jar,我讀過使用PRAGMA foreign_keys = ON;將打開外鍵約束,並且需要在每個連接的基礎上打開它。如何通過Java在SQLite中實施外鍵約束?

我的問題是:我需要執行哪些Java語句來打開此命令?我已經試過:

connection.createStatement().execute("PRAGMA foreign_keys = ON"); 

Properties properties = new Properties(); 
properties.setProperty("PRAGMA foreign_keys", "ON"); 
connection = DriverManager.getConnection("jdbc:sqlite:test.db", properties); 

connection = DriverManager.getConnection("jdbc:sqlite:test.db;foreign keys=true;"); 

但這些都不工作。有什麼我在這裏失蹤?

我見過this answer我只想用JDBC來做同樣的事情。

+1

你正在使用什麼版本的SQLite? (在3.6.19中引入了外鍵約束。) – dan04 2012-03-22 23:18:54

+0

3.6.14.2,顯然。甚至沒有意識到。 – Zarjio 2012-03-22 23:25:30

回答

14

當你在看SQLite Foreign Key Support page我會解釋說

  1. SQLlite已與國外關鍵支撐
  2. 編譯你仍然需要打開它與PRAGMA
  3. 你必須給每個連接在創建表時將外鍵定義爲約束條件

Ad 1)引用自here

If the command "PRAGMA foreign_keys" returns no data instead of a single row containing "0" or "1", then the version of SQLite you are using does not support foreign keys (either because it is older than 3.6.19 or because it was compiled with SQLITE_OMIT_FOREIGN_KEY or SQLITE_OMIT_TRIGGER defined).

你的結果是PRAGMA foreign_keys;

更新:從您的評論我看你使用的是3.6.14.2,這意味着你的版本不支持外鍵約束!所以你必須更新SQLite,如果這是可能的!

廣告2)你的第一個代碼片段執行PRAGMA作爲語句,我不認爲這會工作。第三個剪輯沒有根據您的評論工作:SQLite驅動程序將整個字符串解釋爲數據庫的位置,而不是將「外鍵=真」部分作爲連接設置「」。因此,只有第二個片段將會。工作

廣告3)你創建一個外鍵的支持表從here報價:

CREATE TABLE artist(
    artistid INTEGER PRIMARY KEY, 
    artistname TEXT 
); 
CREATE TABLE track(
    trackid  INTEGER, 
    trackname TEXT, 
    trackartist INTEGER, 
    FOREIGN KEY(trackartist) REFERENCES artist(artistid) 
); 
+0

是的,該表是使用外鍵支持創建的。我應該很快注意到第三種方法根本不起作用,SQLite驅動程序將整個字符串解釋爲數據庫的位置,而不是將「外鍵=真」部分作爲連接設置。 – Zarjio 2012-03-23 14:25:04

1

嘗試

connection = DriverManager.getConnection("jdbc:sqlite:test.db;foreign keys=true;"); 

根據您鏈接的問題,它看起來是一個可能的候選人。

+0

對不起,應該提到我已經嘗試過,但它也沒有工作。 – Zarjio 2012-03-19 19:04:13

0

我發現這個問題,而谷歌搜索同樣的問題,我是用sqlitejdbc-v056.jarZentus,其使用。舊版本的SQLite驅動程序,並且不支持外鍵。

我試了一下,似乎從Maven Repository

我還沒有研究這些驅動程序之間的區別是Xerial司機v3.7.2,但兩者之間的熱交換並沒有破壞任何東西固定我的問題,所以, 我希望這可以幫助別人。

1

在Linux桌面上,當我試圖,

connection = DriverManager.getConnection("jdbc:sqlite:/path/to/test.db;foreign keys=true;"); 

sqlite3的(3.7.13)認爲我的數據庫文件/path/to/test.db;foreign鍵=真。這導致了奇怪的,但我想適當的程序,error:表不存在

how to solve no such table while inserting exception in sqlite data base

我想通過餡外鍵語句轉換成像這樣的屬性我有固定的兩個問題:

private final Properties connectionProperties = new Properties(); 
connectionProperties.setProperty("PRAGMA foreign_keys", "ON"); 
private final String connectionString = String.format("jdbc:sqlite:%s", absolute_path_to_sqlite_db); 
Connection connection = DriverManager.getConnection(connectionString, connectionProperties); 

但即使壽數據庫名稱問題解決時,SQLite仍然允許違反約束。一些更noodling與Xerial的驅動程序,這是最後的工作:

private final Properties connectionProperties = new Properties(); 
SQLiteConfig config = new SQLiteConfig(); 
config.enforceForeignKeys(true); 
connectionProperties = config.toProperties(); 
private final String connectionString = String.format("jdbc:sqlite:%s", absolute_path_to_sqlite_db); 
Connection connection = DriverManager.getConnection(connectionString, connectionProperties); 
26

這樣的代碼:

DriverManager.getConnection("jdbc:sqlite:some.db;foreign keys=true;") 

不工作。 您必須創建org.sqlite.SQLiteConfig,並在從DriverManager調用getConnection時將其設置爲屬性。

public static final String DB_URL = "jdbc:sqlite:database.db"; 
public static final String DRIVER = "org.sqlite.JDBC"; 

public static Connection getConnection() throws ClassNotFoundException { 
    Class.forName(DRIVER); 
    Connection connection = null; 
    try { 
     SQLiteConfig config = new SQLiteConfig(); 
     config.enforceForeignKeys(true); 
     connection = DriverManager.getConnection(DB_URL,config.toProperties()); 
    } catch (SQLException ex) {} 
    return connection; 
} 

此代碼取自this

+0

這工作就像一個魅力!這又是應該被接受爲答案的答案之一。 – 2015-03-31 16:42:33

+0

謝謝!很好的答案。 – noobProgrammer 2015-08-31 08:20:23

+0

完美,它解決了我的問題。 – 2017-09-23 15:20:14

4

我很遺憾不能在以前的海報的答案,但作爲一個擡頭給其他人誰可能會通過這裏,第一代碼片段評論:

connection.createStatement().execute("PRAGMA foreign_keys = ON"); 

絕對不工作的時候你的SQLite版本最新並支持外鍵支持。

0

此頁面在翻譯爲Clojure時很有用,但我的解決方案有所不同。因此,對於後人,即使OP要求Java中,這是我做到了用Clojure:

(def db-spec {:connection-uri "jdbc:sqlite:db.sqlite3?foreign_keys=on;"})

0

我使用的MyBatis,MyBatis的中-config.xml中:
<property name="url" value="jdbc:sqlite:example.db?foreign_keys=on;"/>
這是工作mybatis框架。