【问题标题】:How do I update records only if I find a duplicate or otherwise insert data?仅当我发现重复数据或以其他方式插入数据时,如何更新记录?
【发布时间】:2010-07-27 22:12:53
【问题描述】:

在下面的代码中有一个散列,其中包含具有 namepidtypetime1 等字段的记录。 pidname 是包含重复项的重复字段。

我发现更新需要修改的字段 否则插入,这里namepid 有重复项(重复字段)。

其余的都是独一无二的。在创建表Serial no 时,我还有一个独特的字段。我应该怎么继续?我只在这段代码中做了一个插入。我不知道如何使用 Perl 将检索到的记录存储到数组中。请指导我。

for my $test11 (sort keys %seen) {
    my $test1 = $seen{$test11}{'name'};
    my $test2 = $seen{$test11}{'pid'};
    my $test3 = $seen{$test11}{'type'};
    my $test4 = $seen{$test11}{'time1'};

    print "$test11\t$test1$test2$test3$test4\n";

    $db_handle = &getdb_handle;
    $sth       = $dbh->prepare("Select username,pid,sno from svn_log1");
    $sth->execute() or die "SQL Error: $DBI::errstr\n";
    my $ref = $sth->fetchall_arrayref();
    print "hai";
    print "****$ref";
    $sth = $dbh->prepare("INSERT INTO svn_log1 values('$sno','$test11','$test1','$test4','$test2','$test3')");
    $sth->execute() or die "SQL Error: $DBI::errstr\n";
}

【问题讨论】:

  • 对不起,你必须更清楚你在问什么。您的代码示例似乎遍历了 %seen 中的所有记录,并为 每条记录 从数据库中获取整个表,然后再向其中添加一条记录。这对我来说毫无意义。我知道您想捕获重复项并对它们做一些不同的事情,最好通过另一个哈希来完成,将可能重复的值作为键;但我看不清楚你想做什么来给你答案。

标签: sql mysql perl dbi


【解决方案1】:

认为您想说的是,如果您在数据库中已经有了该名称/pid 组合,您不想尝试插入一些数据,但我不能告诉,所以我不能帮你。

但是,这里有一些可以清除您的代码的东西。首先,选择合理的变量名称。其次,始终、始终、始终在 SQL 语句中使用占位符来保护它们:

for my $test11 ( sort keys %seen ) {
    my $name  = $seen{$test11}{'name'};
    my $pid   = $seen{$test11}{'pid'};
    my $type  = $seen{$test11}{'type'};
    my $time1 = $seen{$test11}{'time1'};

    my $dbh = getdb_handle();
    my $sth = $dbh->prepare("Select username,pid,sno from svn_log1");
    $sth->execute() or die "SQL Error: $DBI::errstr\n";
    my $ref = $sth->fetchall_arrayref();
    # XXX why are we fetching this data and throwing it away?

    $sth = $dbh->prepare("INSERT INTO svn_log1 values(?,?,?,?,?,?)");
    $sth->execute( $sno, $test11, $name, $time1, $pid, $type )
      or die "SQL Error: $DBI::errstr\n";
}

假设如果存在“$name”和“$pid”,您不希望在数据库中插入某些内容(并进行一些清理以避免一遍又一遍地准备相同的 SQL):

my $dbh = getdb_handle();
my $seen_sth   = $dbh->prepare( "Select 1 from svn_log1 where username = ? and pid = ?");

# This really needs to be "INSERT INTO svnlog1 (@columns) VALUES (@placeholders)
my $insert_sth = $dbh->prepare("INSERT INTO svn_log1 values(?,?,?,?,?,?)");
for my $test11 ( sort keys %seen ) {
    my $name  = $seen{$test11}{'name'};
    my $pid   = $seen{$test11}{'pid'};
    my $type  = $seen{$test11}{'type'};
    my $time1 = $seen{$test11}{'time1'};

    $seen_sth->execute($name, $pid) or die "SQL Error: $DBI::errstr\n";
    my @seen = $seen_sth->fetchrow_array;
    next if $seen[0];

    $insert_sth->execute( $sno, $test11, $name, $time1, $pid, $type )
      or die "SQL Error: $DBI::errstr\n";
}

这不是我写这篇文章的方式,但它相当清楚。我怀疑这并不是您真正想要的,但我希望它能让您更接近解决方案。

【讨论】:

    【解决方案2】:

    你想插入一些数据,但如果存在,那么更新现有行?

    如何测试数据是否已经存在于数据库中?您使用的是用户名和 pid 吗?

    如果是这样,您可能希望更改数据库的结构: ALTER TABLE svn_log1 ADD UNIQUE (username, pid);

    这会在 usernamepid 上创建一个复合且唯一的索引。这意味着每个用户名/pid 组合都必须是唯一的。

    这允许您执行以下操作:

    INSERT INTO svn_log1 (username, pid, ...) VALUES (?, ?, ...) ON DUPLICATE KEY UPDATE time = NOW();

    【讨论】:

    • DBD::mysql::st 执行失败:您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以在 task_last.pl 行的第 1 行的“13:00:44 (Mon, 12 Apr 2010) ,21534 , Loc Information Page ) ON DUPLICATE KEY UP 附近使用正确的语法60, 第 17 行。
    • 您能否发布您尝试运行的最终查询以及表结构?
    【解决方案3】:

    这是什么数据库?

    我的感觉是你想要一个UPDATEINSERT 查询,通常称为UPSERT 查询。

    如果这是 PostgreSQL,你可以创建一个 upsert 函数来处理你需要的东西。请参阅comments 以获得一个不错的示例。否则,在 Stack Overflow 中搜索“upsert”,您应该会找到所需的内容。

    【讨论】:

    • 是 MySQL;查看之前的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-26
    • 1970-01-01
    • 1970-01-01
    • 2013-06-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多