Scriptella - 如何获取和重用自动生成的ID?

时间:2012-10-09 20:43:59

标签: postgresql scriptella

我正在使用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的值,以便在第二个表的插入中使用它,因为应该引用记录

2 个答案:

答案 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 ... RETURNINGcurrval('the_id_sequence')之后调用INSERT来捕获ID,将ID存储在脚本语言的客户端变量中,并将其传递给后续版本INSERT S;或

  • currval('the_id_sequence')后续插入列表中使用VALUES

我从来没有听说过Scriptella,更不用说使用它了,所以我无法帮助使用客户端变量的第一个选项。如果它没有办法存储SELECTINSERT ... RETURNING的结果供以后使用,我会感到非常惊讶。一个非常快速的一瞥表明它已经完成了嵌套的<query/><script/>块,但这只是对教程的一瞥30秒。

第二个选项很简单。假设您刚刚插入:

INSERT INTO zoologia.genero VALUES( DEFAULT, ?familiaId, ?genero, true );

并希望在especie中插入一个新行,该行包含刚刚插入的generoId的{​​{1}}。假设genero的ID序列遵循PostgreSQL使用的标准命名genero,您将使用:

tablename_columnname_id_seq

请参阅: