如果我在数据库中有两个表
table1
id_app | description
id_app是table1的主键
table2
id_person | name | id_app
(id_person,id_app)是table2的主键
如果我执行此操作:
this.stat = conn.createStatement();
String sql = "INSERT INTO `table2` (id_person,name,aplication) VALUES (\""+id_person+"\", \""+name+"\", \""+aplication+"\")";
stat.executeUpdate(sql);
我可以插入一个没有在table1中定义的应用程序的人,这是可行的吗?或者我在数据库中定义了错误的内容? 我可以在我的java程序中限制它,但我想知道是否有办法从数据库中限制它?
我的数据库定义看起来像这样
CREATE TABLE `table1` (
`id_app` TEXT NOT NULL UNIQUE,
`description` TEXT NOT NULL UNIQUE,
PRIMARY KEY(`id_app`)
);
CREATE TABLE `table2` (
`id_person` TEXT NOT NULL UNIQUE,
`aplication` TEXT NOT NULL,
FOREIGN KEY(`aplication`) REFERENCES `table1`(`id_app`),
PRIMARY KEY(`id_person`,`aplication`)
);
答案 0 :(得分:1)
您错过了从table2
到table1
的{{3}}限制。外键限制告诉数据库确保table1
中存在值,然后才允许该列table2
中的值。
想到两个想法:
您是否启用了 FOREIGN KEY支持?
在SQLite的某些设置中,外键功能要么未编译,要么已编译但默认情况下已禁用。对于后一种情况,您可能需要FOREIGN KEY。
我通常不会将TEXT列设置为PRIMARY KEY。如果您可以将id_app
列重构为INTEGER类型,则可能会获得更多成功。
答案 1 :(得分:0)
您可以在数据库结构中使用外键:
答案 2 :(得分:0)
默认情况下,SQLite不会强制执行外键,如documentation中所述:
从SQLite版本3.6.19开始,外键强制的默认设置为OFF。但是,这可能会在SQLite的未来版本中发生变化。可以使用SQLITE_DEFAULT_FOREIGN_KEYS预处理器宏在编译时指定外键强制的默认设置。为了最大限度地减少将来出现的问题,应用程序应根据应用程序的要求设置外键强制标志,而不是依赖于默认设置。
如果要启用外键实施,则需要执行语句PRAGMA foreign_keys=1;
。我相信你需要为每个新的Connection
做这个,但我可能会弄错。 1
可以替换为true
,yes
或on
。
使用Connection
参数使用DriverManager.getConnection(String, Properties)
打开Properties
时,也可以配置SQLiteConfig
。你没有在你的问题中提到它,但由于这是Java而你正在使用SQLite,我假设你正在使用xerial/sqlite-jdbc提供的驱动程序。该库提供SQLiteConfig
类,它具有以下便捷方法:enforceForeignKeys(boolean)
。
您可以使用SQLiteConfig.toProperties()
将Properties
个实例转换为Got negative length for block
。