我正在使用Scriptella进行ETL操作,使用自动生成的id引用的许多表。我想在不使用子查询的情况下重用这些id,这是我的etl文件的脚本片段:
<script connection-id="out" if="rownum>1">
SELECT nextval('SQC_CLASE') AS claseId;
INSERT INTO zoologia.clase VALUES( ?claseId, ?phylumId, ?clase, ?subclase, ?infraclase, true );
SELECT nextval('SQC_ORDEN') AS ordenId;
INSERT INTO zoologia.orden VALUES( ?ordenId, ?claseId, ?orden, ?suborden, true );
SELECT nextval('SQC_SUPERFAMILIA') AS superfamiliaId;
INSERT INTO zoologia.superfamilia VALUES( ?superfamiliaId, ?ordenId, ?superfamilia, true );
SELECT nextval('SQC_FAMILIA') AS familiaId;
INSERT INTO zoologia.familia VALUES( ?familiaId, ?superfamiliaId, ?familia, ?subfamilia, ?tribu, true );
SELECT nextval('SQC_GENERO') AS generoId;
INSERT INTO zoologia.genero VALUES( ?generoId, ?familiaId, ?genero, true );
SELECT nextval('SQC_ESPECIE') AS especieId;
INSERT INTO zoologia.especie VALUES( ?especieId, ?generoId, ?especie, ?subespecie, ?variedad, ?genero, true );
</script>
这显然是错误的,因为SELECT
无法在脚本中执行,对吧?我不确定如何在子查询中执行此操作。我正在使用PostgreSQL。
编辑: 我想要实现的是,例如,获取第一个表的插入中使用的自动生成的id的值,以便在第二个表的插入中使用它,因为应该引用记录
答案 0 :(得分:3)
感谢Scriptella论坛的用户,这是一个解决方案,一个包含所有序列值的查询:
<query connection-id="external">
<query connection-id="sizoo">
SELECT nextval('SQC_PHYLUM') AS phylumId
, nextval('SQC_CLASE') AS claseId
, nextval('SQC_ORDEN') AS ordenId
, nextval('SQC_SUPERFAMILIA') AS superfamiliaId
, nextval('SQC_FAMILIA') AS familiaId
, nextval('SQC_GENERO') AS generoId
, nextval('SQC_ESPECIE') AS especieId;
<script connection-id="sizoo" if="rownum>1">
INSERT INTO zoologia.phylum VALUES( ?phylumId, ?phylum, true );
INSERT INTO zoologia.clase VALUES( ?claseId, ?phylumId, ?clase, ?subclase, ?infraclase, true );
INSERT INTO zoologia.orden VALUES( ?ordenId, ?claseId, ?orden, ?suborden, true );
INSERT INTO zoologia.superfamilia VALUES( ?superfamiliaId, ?ordenId, ?superfamilia, true );
INSERT INTO zoologia.familia VALUES( ?familiaId, ?superfamiliaId, ?familia, ?subfamilia, ?tribu, true );
INSERT INTO zoologia.genero VALUES( ?generoId, ?familiaId, ?genero, true );
INSERT INTO zoologia.especie VALUES( ?especieId, ?generoId, ?especie, ?subespecie, ?variedad, ?genero, true );
</script>
</query>
</query>
答案 1 :(得分:1)
您的代码最初看起来完全是虚假的,因为似乎无法将SELECT
连接到以下INSERT
,所以即使它已经运行,您只需要生成ID并将其丢弃。看起来您的脚本工具可能会自动将SELECT
列别名的结果定义为可在以后的查询中引用的变量;见"copy to another database" in the Scriptella tutorial。快速浏览一下就可以看出你想要做什么可能有用,但是你必须使用嵌套的<query/>
和<script/>
块来完成它。
使用序列生成ID的正确方法是:
INSERT INTO zoologia.especie VALUES( nextval('SQC_ESPECIE'), ?generoId, ?especie, ?subespecie, ?variedad, ?genero, true );
INSERT INTO zoologia.especie VALUES( DEFAULT, ?generoId, ?especie, ?subespecie, ?variedad, ?genero, true );
INSERT INTO zoologia.especie(generoId, especie, subespecie, variedad, genero, someothercol)
VALUES( ?generoId, ?especie, ?subespecie, ?variedad, ?genero, true );
你的问题最初似乎是关于重新使用已删除的ID(即无间隙序列),但看起来你已经澄清它以删除它。
更新更改了问题的含义:
如果您尝试在后续INSERT
中使用从一行生成的ID,则必须:
使用INSERT ... RETURNING
或currval('the_id_sequence')
之后调用INSERT
来捕获ID,将ID存储在脚本语言的客户端变量中,并将其传递给后续版本INSERT
S;或
在currval('the_id_sequence')
后续插入列表中使用VALUES
。
我从来没有听说过Scriptella,更不用说使用它了,所以我无法帮助使用客户端变量的第一个选项。如果它没有办法存储SELECT
或INSERT ... RETURNING
的结果供以后使用,我会感到非常惊讶。一个非常快速的一瞥表明它已经完成了嵌套的<query/>
和<script/>
块,但这只是对教程的一瞥30秒。
第二个选项很简单。假设您刚刚插入:
INSERT INTO zoologia.genero VALUES( DEFAULT, ?familiaId, ?genero, true );
并希望在especie
中插入一个新行,该行包含刚刚插入的generoId
的{{1}}。假设genero
的ID序列遵循PostgreSQL使用的标准命名genero
,您将使用:
tablename_columnname_id_seq
请参阅: