我试图创建一个包含两个表的数据库:客户和交易(一个客户可以进行多次交易,一个交易只能由一个客户完成)。我使用以下Perl代码:
my $dbh = DBI->connect("dbi:SQLite:dbname=$RealBin/active.db","","")
or die $DBI::errstr;
my @ddl = (
"CREATE TABLE IF NOT EXISTS customer (
id INTEGER PRIMARY KEY UNIQUE,
id_1 INTEGER,
id_2 INTEGER,
name TEXT
)",
"CREATE TABLE IF NOT EXISTS transaction (
id INTEGER PRIMARY KEY AUTOINCREMENT,
customer_id INTEGER REFERENCES customer(id),
)"
);
for my $sql (@ddl){
$dbh->do($sql);
}
当我运行脚本时,我收到以下错误:
DBD::SQLite::db do failed: near "transaction": syntax error at
t/oneToMany.t line 28 (#1)
DBD::SQLite::db do failed: near "transaction": syntax error at t/oneToMany.t line 28.
DBD::SQLite::db do failed: near "transaction": syntax error at
t/oneToMany.t line 38 (#1)
第28行是这一行:
$dbh->do($sql);
你能告诉我我做错了什么吗?
答案 0 :(得分:4)
transaction
是SQLite keyword,因此如果您想将其用作标识符,则必须引用它(尽管为您的表选择不同的名称可能更好)
您的外键约束也有点偏差。除约束外,您还需要为customer_id
指定列定义,并使用FOREIGN KEY
开始约束定义。
您的查询应如下所示:
CREATE TABLE IF NOT EXISTS "transaction" (
id INTEGER PRIMARY KEY AUTOINCREMENT,
customer_id INTEGER,
FOREIGN KEY (customer_id) REFERENCES customer(id)
)
此外,只有explicitly enable them:
才会强制执行外键约束SQLite长期以来能够使用外键解析模式,但尚未强制执行约束。现在,您可以发出
foreign_keys
pragma来启用此功能并强制执行约束,最好是在您连接到数据库并且不在事务中时:$dbh->do("PRAGMA foreign_keys = ON");
您可以随时关闭编译实例来明确禁用该功能:
$dbh->do("PRAGMA foreign_keys = OFF");
在撰写本文时,SQLite团队默认禁用此功能,并且我们为了保证向后兼容性,因为此功能可能会破坏您的应用程序,并且实际上为我们打破了一些。如果您使用了具有外键约束的模式但是没有多关注它们并且认为它们总是被SQLite忽略,请做好准备,并且请进行大量测试以确保您的应用程序在以后继续工作默认情况下启用外键支持。
所有在一起:
use strict;
use warnings 'all';
use DBI;
my $dbh = DBI->connect('dbi:SQLite:dbname=foo.sqlite', '', '', {
RaiseError => 1,
PrintError => 0,
});
$dbh->do('PRAGMA foreign_keys = ON');
my @ddl = (
'CREATE TABLE IF NOT EXISTS customer (
id INTEGER PRIMARY KEY UNIQUE,
id_1 INTEGER,
id_2 INTEGER,
name TEXT
)',
'CREATE TABLE IF NOT EXISTS "transaction" (
id INTEGER PRIMARY KEY AUTOINCREMENT,
customer_id INTEGER,
FOREIGN KEY (customer_id) REFERENCES customer(id)
)'
);
for my $sql (@ddl) {
$dbh->do($sql);
}