10

我想用一个插入语句插入多行。

以下代码插入一行,并且工作正常:

create temp table mytmptable
(external_id char(10),
int_id integer,
cost_amount decimal(10,2)
) with no log;

insert into mytmptable values 
('7662', 232, 297.26);

select * from mytmptable;

我尝试将插入更改为此,但它给出了语法错误:

insert into mytmptable values 
('7662', 232, 297.26),
('7662', 232, 297.26);

有没有办法让它工作,还是我需要运行许多插入?

4

5 回答 5

7

你总是可以做这样的事情:

insert into mytmptable
select * 
from (
  select '7662', 232, 297.26 from table(set{1})
  union all
  select '7662', 232, 297.26 from table(set{1})
)

很确定这是标准 SQL,并且可以在 Informix 上工作(派生表对于 Informix 接受UNION ALLinINSERT .. SELECT语句是必需的)。

于 2012-09-09T23:40:10.830 回答
7

如您所见,不能在 Informix 的单个 INSERT 语句中使用多个值列表。

最简单的解决方案是使用多个 INSERT 语句,每个语句都有一个值列表。

如果您正在使用诸如 ESQL/C 之类的 API 并且您关心性能,那么您可以创建一个 INSERT 游标并重复使用它。这会保存插入,直到缓冲区已满,或者您刷新或关闭游标:

$ PREPARE p FROM "INSERT INTO mytmptable VALUES(?, ?, ?)";
$ DECLARE c CURSOR FOR p;
$ OPEN c;
while (...there's more data to process...)
{
    $PUT c USING :v1, :v2, :v3;
}
$ CLOSE c;

变量v1, v2,v3是主变量,用于保存要插入的字符串和数字。(如果您愿意,您可以选择$ FLUSH c;在循环中使用。)因为这会缓冲值,所以它非常有效。当然,你也可以简单地$ EXECUTE p USING :v1, :v2, :v3;在循环中使用;这也放弃了语句的每行准备。

如果您不介意编写冗长的 SQL,您可以使用Matt Hamilton建议的 UNION 技术,但是您需要在 Informix 的每个 SELECT 中使用 FROM 子句。您可以指定:

  • FROM "informix".systables WHERE tabid = 1, 或者
  • FROM sysmaster:"informix".sysdual, 或者
  • 使用其他一些技术来确保 SELECT 具有 FROM 子句但只生成一行数据。

在我的数据库中,我要么有一个dual包含单行的表,要么有一个同义词dual,它是sysmaster:"informix".sysdual. 如果数据库是“正常的”,你可以不用"informix".这些语句的一部分而逃脱;如果您的数据库是 Informix MODE ANSI 数据库,则所有者名称至关重要。

于 2012-09-09T23:49:44.310 回答
5

TABLE在某些版本的 Infomix 中,您可以使用关键字后跟COLLECTION数据类型之一的值(例如LIST集合)来构建虚拟表。在您的情况下,使用构造函数语法使用 a LISTofUnnamed Row类型的值。ROW(...)

创建TABLECOLLECTIONhttp://www.ibm.com/support/knowledgecenter/SSGU8G_11.50.0/com.ibm.sqls.doc/ids_sqs_1375.htm

ROW(...)构造语法,用于Unnamed Row数据类型 http://www.ibm.com/support/knowledgecenter/SSGU8G_11.50.0/com.ibm.sqlr.doc/ids_sqr_136.htm

例子:

select * 
from TABLE(LIST{
  ROW('7662', 232, 297.26),
  ROW('7662', 232, 297.26)
}) T(external_id, int_id, cost_amount)
into temp mytmptable with no log

在上面,值隐含了数据类型,但是当需要时,您可以在行构造函数中将每个值显式转换为所需的数据类型,如下所示:

ROW('7662'::char(10), 232::integer, 297.26::decimal(10,2))
于 2016-04-18T22:47:32.753 回答
3

您还可以通过将值存储在外部文件中并在 dbaccess 中执行以下语句来插入多行:

LOAD FROM "externalfile" INSERT INTO mytmptable;

但是,这些值必须由管道“|”分隔 符号,或者您将 DBDELIMITER 环境变量设置为的任何值。

如果您使用管道分隔符,则外部文件中的数据如下所示:

7662|232|297.26|
7663|233|297.27|
...

请注意,外部文件中的数据必须正确格式化或能够转换为成功插入到每个 mytmptable.column 数据类型中。

于 2012-09-12T04:22:56.323 回答
0

这是一个简单的批量插入解决方案,其中 SELECT 部分解决了剩下的问题

INSERT INTO cccmte_pp 
( cmte, pref, nro, eje, id_tri, id_cuo, fecha, vto1, vto2, id_tit, id_suj, id_bie, id_gru ) 
SELECT * FROM TABLE (MULTISET { 
row('RC', 4, 10, 2020, 1, 5, MDY(05,20,2020), MDY(05,20,2020),MDY(05,27,2020),101, 1, 96, 1 ), 
row('RC', 4, 11, 2020, 1, 5, MDY(05,20,2020), MDY(05,20,2020),MDY(05,27,2020),101, 1, 96, 1 ) }) 
AS t( cmte, pref, nro, eje, id_tri, id_cuo, fecha, vto1, vto2, id_tit, id_suj, id_bie, id_gru )
;
于 2020-05-20T21:48:49.133 回答