首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SQL::Abstract with select查询

SQL::Abstract with select查询
EN

Stack Overflow用户
提问于 2013-04-09 19:07:36
回答 3查看 1K关注 0票数 2

insert into table1(id, text) select (max(id)+1), "Something" from table1

如何使用SQL::抽象或SQL::抽象::More生成此查询?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-04-17 03:06:20

您可以这样做:

代码语言:javascript
复制
use strict;
use warnings;
use SQL::Abstract;

my $sa = SQL::Abstract->new;
my $select = $sa->select('table1', "MAX(id) + 1, 'Something'");
my $full_sql = "INSERT INTO table1 (id, text) $select";

但说真的,你为什么要这么做呢?您的示例很简单,正如其他人所指出的那样,最好只编写SQL。如果你想让“某物”成为一个变量,你可以这样做:

代码语言:javascript
复制
my $new_id = $sa->select('table1', 'MAX(id) + 1');
my $data = {
   id => \["($new_id)"],
   text => $some_value_from_elsewhere
};
my ($sql, @binds) = $sa->insert('table1', $data);
票数 2
EN

Stack Overflow用户

发布于 2013-04-12 22:09:04

正如Rachcha指出的那样,您的SQL语句包含一些缺陷。我假设你在尝试像这样的东西

代码语言:javascript
复制
insert into table1(id, text) values((select (max(id)+1) from table1), "Something")

如果您想将新数据添加到具有唯一ID的table1中,那么您真的应该考虑在数据库的id字段中添加一个主键。

已更新答案

旧的anwser 确实创建了一个关于数据和语法的有效SQL语句,但是DBI中的准备和执行函数对这些值进行了一些魔术处理。

如果我像这样运行查询:

代码语言:javascript
复制
my $query = "insert into table1 values((select (max(id)+1) from table1), 'Something')";
$dbh->do($query);

查询在执行时将保持原样。当我改为使用prepare和execute时,DBI会自动将值放在单引号之间,如'this‘,这会导致:

代码语言:javascript
复制
insert into table1(id, text) values('(select (max(id)+1) from table1)', 'Something');

显然,这会将值打印为文本(如果这是有效的数据类型)。在我看来,这并不意味着从代码生成的查询是错误的,而不是来自DBI的不需要的引用。我找不到能不能去掉它们的答案。问题是如果DBI支持insert ...select语句。否则,您将无法对这些查询使用SQL::Abstract (或准备/执行)。

您可以将其构建为两步火箭,只要您的数据库没有多个事务,这可能会导致重复。

代码语言:javascript
复制
my $select_stmt = $sql->select('table1', '(max(id)+1)'):
# Prepare with $stmt
# Fetch your result and declare $max_id, e.g.
my $sth = $dbh->prepare($select_stmt);
$sth->execute();

my $max_id = 0;
my @max_id_arr = $sth->fetchrow_array();
$max_id = $max_id_arr[0];

die($max_id . " is 0") unless($max_id);

my %data = (
    id => $max_id,
    text => 'Something',
);

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

旧答案

然而,为了回答你的问题,这应该能起到作用:

代码语言:javascript
复制
my $max_id = $sql->select('table1', 'max(id)+1');
my %data = (
    id => "($max_id)",
    text => "Something",
);
my($stmt, @bind) = $sql->insert('table1', \%data);

printf("My SQL statement was %s\nThe values was %s\n", $insert_stmt, join(", ", @insert_bind));

这将打印出来

我的

语句是INSERT INSERT到table1 ( id,text)值( ?,?)值是(SELECT max(id)+1 FROM table1),即

票数 1
EN

Stack Overflow用户

发布于 2013-04-16 19:51:07

虽然我在我的代码中使用了很多SQL::Abstract,但我不建议在您的示例中使用它。主要是因为如果您直接编写SQL-Code,它有时会更具可读性和可维护性。因为您必须确保插入字段的顺序与选择字段的顺序完全匹配。

但是,如果有必要,您可以使用$sql->where()方法从select查询中提取where部分:

代码语言:javascript
复制
    my $stmt1 = <<'END_SQL';
    INSERT INTO table1(id, text) 
    SELECT (MAX(id)+1) id, 'Something' text
    FROM table1
    END_SQL

    my ($stmt2,@binds) = $sql->where( key1=>$value1, key2=>$value2 );

然后简单地连接这两个SQL语句。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15900230

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档