我有一个地址簿的sqlite3数据库,我用
创建了地址表 my $dbcreate = qq(CREATE TABLE IF NOT EXISTS address
(ID INTEGER PRIMARY KEY AUTOINCREMENT,
LASTNAME TEXT NOT NULL,
FIRSTNAME TEXT NOT NULL,
COMPANY TEXT,
STREET TEXT,
CITY TEXT,
STATE TEXT,
COUNTRY TEXT,
ZIPCODE TEXT,
MOBILE TEXT,
OTHERPHONE TEXT,
FAX TEXT,
EMAIL TEXT,
EMAIL2 TEXT,
WEBSITE TEXT,
WEBSITE2 TEXT,
DOB DATE,
NOTES TEXT,
TAGS TEXT););
因此,据我所知,第一栏应该是一个自动增量的主要ID,但它不是自动增量的。我从阅读sqlite教程的理解是,我只需要输入其他18个值,该列应该自动增量,但如果我插入18个值,我告诉我错过了一个。 如果我手动设置ROWID,我只能插入行。 是什么给了什么?
以下是我如何添加行(未成功)
#!/usr/bin/perl -w
# script to enter a new addressbook entry
use DBI;
use strict;
use warnings;
print "Please enter a DB username? \n";
my $userid=<STDIN>;
chomp($userid);
print "Please enter a DB password? \n";
my $password=<STDIN>;
chomp($password);
my $driver = "SQLite";
my $database = "myaddress.db";
my $dsn = "DBI:$driver:dbname=$database";
my $dbh = DBI->connect($dsn, $userid, $password, { RaiseError => 1 })
or die $DBI::errstr;
print "Successfull DB connection\n";
print "Creating new address book entry\n";
my $arval = 0;
my @dbits = ('LASTNAME','FIRSTNAME','COMPANY','STREET','CITY','STATE','COUNTRY','ZIPCODE','MOBILE','OTHERPHONE','FAX','EMAIL','EMAIL2','WEBSITE','WEBSITE2','DOB','NOTES','TAGS');
# print "@dbits";
# for $b (0 .. 17) {
# print "\'$dbits[$b]\', ";
# }
print "-----\n";
my @nubits = ();
foreach my $databit(@dbits) {
print "Enter $databit: \n";
my $nubit = <STDIN>;
chomp($nubit);
print "$databit = $nubit\n\n";
push(@nubits,$nubit);
print "$databit = $nubits[$arval]\n";
my $arval = (++$arval);
print "$arval\n";
}
# print "new entry will be:\n";
# for $b (0 .. 17) {
# print "$nubits[$b] | ";
# }
my $entry = qq(INSERT INTO address VALUES('$nubits[0]','$nubits[1]','$nubits[2]','$nubits[3]','$nubits[4]','$nubits[5]','$nubits[6]','$nubits[7]','$nubits[8]','$nubits[9]','$nubits[10]','$nubits[11]','$nubits[12]','$nubits[13]','$nubits[14]','$nubits[15]','$nubits[16]','$nubits[17]'););
my $retval = $dbh->do($entry);
if($retval < 0){
print $DBI::errstr;
} else {
print "entry created successfully\n";
}
my $query = qq(select * from address);
print $query;
$dbh->disconnect();
我可以手动使用cli中的sqlite3来输入行,但是,如上所述,我必须手动设置ROWID / Primary ID。
过去,我只使用sqlite和tcl / tk,而不是perl,但即使我是一个完整的perl n00b,我也不认为perl是我的问题。 sqlite3没有按预期运行(除非我完全误读了十几个教程,这些教程声明主键id设置为自动增量应该,自动增量)。
答案 0 :(得分:4)
它不是自动递增的,因为你已经给它一个id,$nubits[0]
。
如果没有列列表,INSERT INTO address VALUES (...)
会在表中插入所有列。您could use NULL
as @ReenactorRob suggests,但这只是隐藏了该查询的另一个问题。
INSERT INTO address VALUES (...)
需要了解创建address
的顺序,才能知道元素5是街道。如果有任何更改表中的顺序,则INSERT会中断。如果添加了列,则查询会中断。如果你把一个值放在错误的插槽中(正如你所做的那样)很难说清楚。使用显式列列表会好得多。
INSERT INTO address
(lastname, firstname, company, street, ...)
VALUES
(...)
现在,您的ID将增加和,以防止您将来更改表格。如果这似乎很多工作,那么使它成为一个函数,它接受一个值的哈希来构建一个查询。它比记住$nubits[12]
更具可读性。但在您这样做之前,请查看已经为您完成此操作的DBIx::Class。
如果我没有提及bind parameters,我会失职。这些更快,允许您使用预准备语句,它们可以保护您免受SQL injection attacks。
答案 1 :(得分:0)
尝试在插件中使用null,如下所示:
my $entry = qq(INSERT INTO address VALUES(null,'$nubits[0]','$nubits[1]',...
答案 2 :(得分:0)
正如已经解释的那样,问题是VALUES
部分的INSERT
部分中的项目按照他们第一次的顺序一对一地分配到表格的列中创建。如果您只需要为列的子集提供值,那么您还需要提供应该接收值的列名列表。
如果没有列名,则值将按照创建顺序分配给列,因此最后的列不会接收值。在这种情况下,数据库会将LASTNAME
列的值分配给ID
,并且最后的TAGS
元素没有值。
将占位符用于SQL语句中的值也更好,并使用prepare
和execute
而不是do
。这样DBI
模块将根据数据类型适当地引用和转义实际值。
该程序显示了如何做到这一点
#!/usr/bin/perl
use strict;
use warnings;
use DBI;
use DBD::SQLite;
STDOUT->autoflush;
my ($driver, $dbname) = qw/ SQLite myaddress.db /;
my $dsn = "DBI:$driver:dbname=$dbname";
print 'Please enter a DB username: ';
my $username = <STDIN>;
chomp($username);
print 'Please enter a DB password: ';
my $password = <STDIN>;
chomp($password);
my $dbh = DBI->connect($dsn, $username, $password, { RaiseError => 1 });
print "Successful DB connection\n";
print "Creating new address book entry...\n";
print "-----\n";
my @dbits = qw/
LASTNAME FIRSTNAME COMPANY STREET
CITY STATE COUNTRY ZIPCODE
MOBILE OTHERPHONE FAX EMAIL
EMAIL2 WEBSITE WEBSITE2 DOB
NOTES TAGS
/;
my @nubits;
for my $databit (@dbits) {
print "Enter $databit: ";
my $nubit = <STDIN>;
chomp($nubit);
push @nubits, $nubit;
print "$databit = $nubits[-1]\n";
print scalar @nubits, "\n";
}
my $columns = join ', ', @dbits;
my $placeholders = join ', ', ('?') x @dbits;
my $insert = <<"__END__SQL__";
INSERT INTO address (
$columns
)
VALUES (
$placeholders
)
__END__SQL__
$insert = $dbh->prepare($insert);
$insert->execute(@nubits);
print "Entry created successfully\n";
$dbh->disconnect;
这会在$insert
中创建一个类似于
INSERT INTO address (
LASTNAME, FIRSTNAME, COMPANY, STREET, CITY, STATE, COUNTRY, ZIPCODE, MOBILE, OTHERPHONE, FAX, EMAIL, EMAIL2, WEBSITE, WEBSITE2, DOB, NOTES, TAGS
)
VALUES (
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
)