原文: http://zetcode.com/db/sqliteperltutorial/queries/

我们已经建立了到数据库的连接。 现在我们要修改并从数据库中获取数据。

使用SELECT语句从数据库中检索数据。 在 Perl DBI 中,首先我们使用prepare()方法准备 SQL 语句。 SQL 字符串被发送到数据库引擎,该引擎检查语句的有效性,语法,并在某些数据库中检查执行某些查询的用户权限。 如果一切正常,则对语句句柄的引用将返回到 Perl 脚本。 下一步是对execute()方法的调用。 该方法在数据库内执行查询。 此时,结果保留在数据库中。 Perl 脚本尚不包含数据。 对于非选择语句,execute()方法返回已知的受影响的行数。 在最后一步中,从数据库中获取数据。 数据被逐行提取并填充到 Perl 数据结构中。

Perl DBI 有几种从数据库表中获取数据的方法。

方法 描述
fetchrow_arrayref() 获取下一行数据并返回对数组的引用。
fetchrow_array() 获取下一行数据,并将其作为列表返回。
fetchrow_hashref() 获取下一行数据,并将其返回为对哈希的引用。
fetchall_arrayref() 提取所有数据&返回对每行有一个引用的数组的引用。
fetch() 该方法是fetchrow_arrayref()的别名。
fetchrow() 该方法是fetchrow_array()的别名。

准备并执行完 SQL 语句后,我们调用可用的访存方法之一。

方法 描述
selectrow_arrayref() prepare()execute()fetchrow_arrayref()合并为一个调用
selectrow_hashref() prepare()execute()fetchrow_hashref()合并为一个调用
selectrow_array() prepare()execute()fetchrow_array()合并为一个调用。
selectall_arrayref() prepare()execute()fetchall_arrayref()合并为一个调用。
selectall_hashref() prepare()execute()fetchall_hashref()合并为一个调用。
selectcol_arrayref() 合并prepare()execute()并从所有行中提取一个col到一个调用中。

在第二张表中,我们列出了工具方法,这些方法将三个方法组合为一个调用。 它们是方便的方法。

提取方法

在第一个示例中,我们将演示fetchrow_arrayref()方法的用法。

  1. #!/usr/bin/perl
  2. use strict;
  3. use DBI;
  4. my $dbh = DBI->connect(
  5. "dbi:SQLite:dbname=test.db",
  6. "",
  7. "",
  8. { RaiseError => 1 },
  9. ) or die $DBI::errstr;
  10. my $sth = $dbh->prepare("SELECT * FROM Cars LIMIT 5");
  11. $sth->execute();
  12. my $row;
  13. while ($row = $sth->fetchrow_arrayref()) {
  14. print "@$row[0] @$row[1] @$row[2]\n";
  15. }
  16. $sth->finish();
  17. $dbh->disconnect();

在示例中,我们从Cars表中选择 5 行。 使用fetchrow_arrayref()方法检索数据。

  1. my $sth = $dbh->prepare("SELECT * FROM Cars LIMIT 5");
  2. $sth->execute();

这是数据检索过程的前两个阶段。 我们准备并执行SELECT语句。

  1. my $row;
  2. while ($row = $sth->fetchrow_arrayref()) {
  3. print "@$row[0] @$row[1] @$row[2]\n";
  4. }

现在,我们正在获取数据。 fetchrow_arrayref()方法获取下一行数据,并返回对包含字段值的数组的引用。 当没有更多的行了时,我们将方法放入终止的while循环中。

  1. $ ./fetchrow_arrayref.pl
  2. 1 Audi 52642
  3. 2 Mercedes 57127
  4. 3 Skoda 9000
  5. 4 Volvo 29000
  6. 5 Bentley 350000

示例输出。

在第二个示例中,我们将使用fetchrow_array()方法。

  1. #!/usr/bin/perl
  2. use strict;
  3. use DBI;
  4. my $dbh = DBI->connect(
  5. "dbi:SQLite:dbname=test.db",
  6. "",
  7. "",
  8. { RaiseError => 1 },
  9. ) or die $DBI::errstr;
  10. my $sth = $dbh->prepare( "SELECT * FROM Cars LIMIT 5" );
  11. $sth->execute();
  12. my @row;
  13. while (@row = $sth->fetchrow_array()) {
  14. print "@row\n";
  15. }
  16. $sth->finish();
  17. $dbh->disconnect();

在此脚本中,我们连接到数据库,并使用fetchrow_array()方法一张一张地获取 5 行Cars表。

  1. my @row;
  2. while (@row = $sth->fetchrow_array()) {
  3. print "@row\n";
  4. }

fetchrow_array()方法获取下一行数据,并将其作为包含字段值的列表返回。 我们使用while循环遍历所有 5 行。

在下一个示例中,我们将按列名称获取数据。 为此,我们将使用fetchrow_hashref()方法。

  1. #!/usr/bin/perl
  2. use strict;
  3. use DBI;
  4. my $dbh = DBI->connect(
  5. "dbi:SQLite:dbname=test.db",
  6. "",
  7. "",
  8. { RaiseError => 1 },
  9. ) or die $DBI::errstr;
  10. my $sth = $dbh->prepare( "SELECT * FROM Cars LIMIT 5" );
  11. $sth->execute();
  12. my $row;
  13. while($row = $sth->fetchrow_hashref()) {
  14. print "$row->{Id} $row->{Name} $row->{Price}\n";
  15. }
  16. $sth->finish();
  17. $dbh->disconnect();

在示例中,数据以对 Perl 哈希的引用形式返回。

  1. my $row;
  2. while($row = $sth->fetchrow_hashref()) {
  3. print "$row->{Id} $row->{Name} $row->{Price}\n";
  4. }

fetchrow_hashref()方法获取下一行数据,并将其返回为对包含字段名称和字段值对的哈希的引用。 使用此方法,我们可以按列名称检索值。

在本节的最后一个示例中,我们一步一步从SELECT语句中获取所有数据。 我们使用fetchall_arrayref()方法。

  1. #!/usr/bin/perl
  2. use strict;
  3. use DBI;
  4. my $dbh = DBI->connect(
  5. "dbi:SQLite:dbname=test.db",
  6. "",
  7. "",
  8. { RaiseError => 1 },
  9. ) or die $DBI::errstr;
  10. my $sth = $dbh->prepare("SELECT * FROM Cars LIMIT 5");
  11. $sth->execute();
  12. my $all = $sth->fetchall_arrayref();
  13. foreach my $row (@$all) {
  14. my ($id, $name, $price) = @$row;
  15. print "$id $name $price\n";
  16. }
  17. $sth->finish();
  18. $dbh->disconnect();

该示例从Cars表中选择并打印五行。

  1. my $all = $sth->fetchall_arrayref();

我们通过一个方法调用获取所有数据。 fetchall_arrayref()方法返回对数组的引用,该数组每行包含一个引用。

  1. foreach my $row (@$all) {
  2. my ($id, $name, $price) = @$row;
  3. print "$id $name $price\n";
  4. }

我们使用foreach循环遍历检索到的数据。

转储数据

Perl DBI 有一个称为dump_results()的特殊方法。 此方法被设计为用于原型设计和测试查询的便捷工具。 它使用neat_list()方法格式化和编辑字符串以供人类阅读。 不建议将其用于数据传输应用。

  1. #!/usr/bin/perl
  2. use strict;
  3. use DBI;
  4. my $dbh = DBI->connect(
  5. "dbi:SQLite:dbname=test.db",
  6. "",
  7. "",
  8. { RaiseError => 1 }
  9. ) or die $DBI::errstr;
  10. my $sth = $dbh->prepare( "SELECT * FROM Cars LIMIT 5" );
  11. $sth->execute();
  12. $sth->dump_results();
  13. $sth->finish();
  14. $dbh->disconnect();

在示例中,我们将转储结果集中的所有数据。

  1. my $sth = $dbh->prepare( "SELECT * FROM Cars LIMIT 5" );
  2. $sth->execute();

SQL 语句从Cars表中选择五行。 和所有三列。

  1. $sth->dump_results();

dump_results()从语句句柄中选择所有行并进行打印。 这是用于原型制作和测试的方法。

  1. $ ./dump.pl
  2. 1, 'Audi', 52642
  3. 2, 'Mercedes', 57127
  4. 3, 'Skoda', 9000
  5. 4, 'Volvo', 29000
  6. 5, 'Bentley', 350000
  7. 5 rows

这是示例的输出。

便利方法

我们将展示两个使用上述便利方法的示例。

  1. #!/usr/bin/perl
  2. use strict;
  3. use DBI;
  4. my $dbh = DBI->connect(
  5. "dbi:SQLite:dbname=test.db",
  6. "",
  7. "",
  8. { RaiseError => 1 },
  9. ) or die $DBI::errstr;
  10. my $ary = $dbh->selectrow_arrayref("SELECT * FROM Cars WHERE Id = 5");
  11. print join(" ", @$ary), "\n";
  12. $dbh->disconnect();

在第一个代码示例中,我们将调用selectrow_arrayref()方法。 我们从Cars表中选择第五行。

  1. my $ary = $dbh->selectrow_arrayref("SELECT * FROM Cars WHERE Id = 5");

selectrow_arrayref()方法将prepare()execute()fetchrow_arrayref()合并为一个调用。 它返回对语句第一行数据的引用。 请注意,我们不使用语句句柄。 我们使用$dbh数据库句柄对象。

  1. print join(" ", @$ary), "\n";

我们将行打印到控制台。

下面的示例显示selectall_arrayref()方法。

  1. #!/usr/bin/perl
  2. use strict;
  3. use DBI;
  4. my $dbh = DBI->connect(
  5. "dbi:SQLite:dbname=test.db",
  6. "",
  7. "",
  8. { RaiseError => 1 },
  9. ) or die $DBI::errstr;
  10. my $all = $dbh->selectall_arrayref("SELECT * FROM Cars LIMIT 5");
  11. foreach my $row (@$all) {
  12. my ($id, $name, $price) = @$row;
  13. print "$id $name $price\n";
  14. }
  15. $dbh->disconnect();

我们再次从Cars表中检索 5 行。

  1. my $all = $dbh->selectall_arrayref("SELECT * FROM Cars LIMIT 5");

selectall_arrayref()方法返回对数组的引用,其中包含对获取的每一行数据的数组的引用。 提供的 SQL 语句从Cars表中选择 5 行。 请注意,我们既没有调用prepare()也没有调用execute()方法。 这是因为selectall_arrayref()方法将prepare()execute()fetchall_arrayref()组合到一个调用中。

  1. foreach my $row (@$all) {
  2. my ($id, $name, $price) = @$row;
  3. print "$id $name $price\n";
  4. }

我们遍历提取的数组数组并将数据打印到终端。

  1. $ ./retrieve.pl
  2. 1 Audi 52642
  3. 2 Mercedes 57127
  4. 3 Skoda 9000
  5. 4 Volvo 29000
  6. 5 Bentley 350000

这是示例的输出。

参数化查询

现在,我们将关注参数化查询。 当使用参数化查询时,我们使用占位符,而不是直接将值写入语句。 参数化查询可提高安全性和性能。

当程序收到用户的输入时,程序员必须始终保持谨慎。 稍后,我们将值绑定到预备语句,而不是从用户输入构建字符串。

  1. #!/usr/bin/perl
  2. use strict;
  3. use DBI;
  4. my $dbh = DBI->connect(
  5. "dbi:SQLite:dbname=test.db",
  6. "",
  7. "",
  8. { RaiseError => 1 },
  9. ) or die $DBI::errstr;
  10. my $id = 3;
  11. my $sth = $dbh->prepare( "SELECT * FROM Cars WHERE Id = ?" );
  12. $sth->execute($id);
  13. my $ret = $sth->fetch();
  14. foreach my $row (@$ret) {
  15. print "$row ";
  16. }
  17. print "\n";
  18. $sth->finish();
  19. $dbh->disconnect();

在代码示例中,我们从表中选择特定的行。 SQL 语句具有一个占位符,稍后将在代码中填充该占位符。

  1. my $id = 3;

这可能是用户的输入。

  1. my $sth = $dbh->prepare( "SELECT * FROM Cars WHERE Id = ?" );

问号?是值的占位符。 该值稍后添加。

  1. $sth->execute($id);

execute()语句采用一个参数,该参数绑定到占位符。

  1. $ ./parameterized.pl
  2. 3 Skoda 9000

我们已经使用参数化查询从Cars表中检索了一行。

在第二个示例中,我们将使用便利选择方法之一使用参数化查询。

  1. #!/usr/bin/perl
  2. use strict;
  3. use DBI;
  4. my $dbh = DBI->connect(
  5. "dbi:SQLite:dbname=test.db",
  6. "",
  7. "",
  8. { RaiseError => 1 },
  9. ) or die $DBI::errstr;
  10. my $id = 2;
  11. my @ary = $dbh->selectrow_array("SELECT * FROM Cars WHERE Id = ?", undef, $id);
  12. print join(" ", @ary), "\n";
  13. $dbh->disconnect();

我们需要在SELECT查询中填充一个占位符。

  1. my @ary = $dbh->selectrow_array("SELECT * FROM Cars WHERE Id = ?", undef, $id);

selectrow_array()方法的第三个参数采用占位符的值。

在 SQLite Perl 教程的这一部分中,我们已经演示了如何使用各种 Perl DBI 方法从数据库中获取数据。