【问题标题】:(Perl) Create query for DBI with SQL::Abstract(Perl) 使用 SQL::Abstract 为 DBI 创建查询
【发布时间】:2013-03-30 19:18:30
【问题描述】:

我想在 SQLite 上向 table1 添加新记录

use SQL::Abstract;
my %data = (
  id => \'max(id)', # it is doesn't work so which variant is right?
  record => 'Something'
);

my $sql = SQL::Abstract->new;

my ($stmt, @bind) = $sql->insert('table1', \%data);


...
my $sth = $dbh->prepare($stmt);

如果我在 Catalyst 应用程序中使用 DBIx::Class,我会这样写:

id => $c->model('Model')->get_column('id')->max()

它会正常工作。 那么我怎样才能达到相同的目标,但只使用 DBIx::Class 中使用的 SQL::Abstract。 有人可以修复它吗?谢谢。

【问题讨论】:

  • 这似乎效率很低。为什么不让列自动递增或使用计数器表?
  • 如果您有超过 1 个进程进行插入,它也会受到竞争条件的影响。
  • 我只是想了解如何使用这个模块进行复杂的查询。
  • 回想一下——你认为 SQL 应该是什么样的?您可以一步完成还是必须两个(找到最大 id 然后插入新记录)?您如何找到最大 id(是函数调用还是单独的 SQL)?它可能不是这个 Perl 模块的最佳用例。
  • 警告:我不使用这个 perl 模块,但也许你正在寻找调用 SQL 函数的语法:search.cpan.org/~frew/SQL-Abstract-1.73/lib/SQL/…

标签: sql perl sqlite perl-module dbi


【解决方案1】:

这是一段代码。如您所见,首先您需要获取最大 id+1,然后执行插入命令。我必须注意到这是不安全的,因为在多(用户、进程、线程)环境中,第二个进程可以执行相同的代码并获得竞争条件。 但我假设你只是在学习 SQL::Abstract api,这个问题并不重要

use DBI;
use SQL::Abstract;

#create table TEST(ID integer, NAME varchar);
my $dbh = DBI->connect('dbi:SQLite:dbname=test.db', '', '', {AutoCommit=>1});

my $sql = SQL::Abstract->new;

my($stmt, @bind) = $sql->select("TEST", [ 'max(ID)+1 as ID' ] );
my $sth = $dbh->prepare($stmt);
$sth->execute(@bind);

my ($id) = $sth->fetchrow_array // 1;

print "Select ID: $id", "\n";
$sth->finish;

($stmt, @bind) = $sql->insert("TEST", { ID=>$id, NAME=>"test-name"} );
$sth = $dbh->prepare($stmt);
$sth->execute(@bind);

$dbh->disconnect;

【讨论】:

  • 感谢您的建议。您向我展示了一个包含两个步骤的变体,但我想一步一步地做同样的事情。像这样的东西:id => { -in => \'select max(id) from table1' }
猜你喜欢
  • 2014-01-28
  • 2011-10-06
  • 1970-01-01
  • 2017-07-14
  • 2013-06-21
  • 1970-01-01
  • 2011-09-21
  • 2013-07-20
  • 2011-08-18
相关资源
最近更新 更多