4

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

4

2 回答 2

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>
于 2012-10-10T17:33:09.113 回答
1

您的代码最初看起来完全是伪造的,因为似乎没有任何东西将其连接SELECT到以下内容INSERT,所以即使它运行了,您也只会生成一个 ID 并将其丢弃。不过,看起来您的脚本工具可能会自动将SELECT列别名的结果定义为可以在以后的查询中引用的变量;请参阅Scriptella 教程中的“复制到另一个数据库”。快速浏览一下这表明您想要做的事情可能会奏效,但您必须使用嵌套<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(即无缝序列),但看起来您已经澄清它以删除它。


编辑后更新+评论改变了问题的含义:

如果您尝试在后续 s 中使用从一行生成的 ID INSERT,则必须:

  • 使用或通过在 之后INSERT ... RETURNING调用来捕获 ID ,将 ID 存储在脚本语言中的客户端变量中,并将其传递给后续s;或者currval('the_id_sequence')INSERTINSERT

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

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

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

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

并想在其中插入一个新行,especie其中包含generoId刚刚插入的genero. 假设 ID 序列genero遵循 PostgreSQL 使用的标准命名tablename_columnname_id_seq,您将使用:

INSERT INTO zoologia.especie VALUES( DEFAULT, currval('genero_generoId_seq'), ...);

看:

于 2012-10-10T06:20:21.260 回答