1

テーブル B を参照するテーブル A がある場合を考えてみましょう。

create table tableA
(
   id INT NOT NULL PRIMARY KEY,
   information VARCHAR(32)
);
create table tableB
(
   id INT NOT NULL PRIMARY KEY,
   tableAid INT NOT NULL REFERENCES tableA(id),
   other_information VARCHAR(32)
):

私は Perl でコードを書いており、データベースは PostgreSQL であることに注意してください。

したがって、1 つtableBのエントリに関連付けられている 2 つのエントリがありますtableA。私は次のようなことを言いたいです:

use DBI;
my $dbh = DBI->connect("DBI:Pg:dbname=mydb;host=localhost","userid","password",('RaiseError' -> 1));

my $otherinfo = "other info, Table B";
my $moreotherinfo = "more other info, table B";
my info = "table A info";
my $insertitA = $dbh->prepare("insert into tableA (information) values (?)");
my $insertitB = $dbh->prepare("insert into tableB (tableAid,other_information) values (?,?)");
my $nrowsA = $insertitA($info);
my $tableAidreference = ????;
my $nrowsB = $insertitB($tableAidreference, $otherinfo);
my $nrowsB2 = $insertitB($tableAidreference, $moreotherinfo);

どこで入手でき$tableAidreferenceますか? 私はそれを検索tableAする必要がありますか?

4

2 に答える 2

3

nextval('seq_name')後続の目的で個別に呼び出すメソッドINSERTは時代遅れであり、非常に非効率的です。サーバーへの追加の往復が必要です。これを使用しないでください。より良いオプションがあります:

-> sqlfiddle

まず、テスト セットアップを変更しました。

CREATE TABLE tbl_a
(  tbl_a_id serial NOT NULL PRIMARY KEY,
   information text
);
CREATE TABLE tbl_b
(  tbl_b_id serial NOT NULL PRIMARY KEY,
   tbl_a_id int NOT NULL REFERENCES tbl_a(tbl_a_id),
   other_information text
);
  • id列名として使用しないでください。説明的ではありません。それほどスマートではない ORM の中には、それを行うものがありますが、これはアンチパターンです。

  • 回避できる場合は、PostgreSQL で大文字と小文字が混在する識別子を使用しないでください。

  • serial代理主キーのタイプを使用します。

次に、コマンドの句を使用して、1 つのデータ変更 CTE (PostgreSQL 9.1 以降が必要)ですべてを実行します。RETURNINGINSERT

WITH x AS (
    INSERT INTO tbl_a (information)
    VALUES ('foo')
    RETURNING tbl_a_id
    )
INSERT INTO tbl_b (tbl_a_id, other_information)
SELECT tbl_a_id, 'bar'
FROM   x
RETURNING tbl_a_id, tbl_b_id; -- optional, if you want IDs back

サーバーへの1回の往復で、必要に応じて両方の新しい ID が返されます。3回の往復ではありません。


DBI でこれを使用するには?

DBD::Pg モジュールの場合:

$SQL = q{ WITH x AS (
    INSERT INTO tbl_a (information)
    VALUES (?) 
    RETURNING tbl_a_id
    )
INSERT INTO tbl_b (tbl_a_id, other_information)
SELECT tbl_a_id, 'bar'
FROM   x
RETURNING tbl_a_id, tbl_b_id};
$answer = $dbh->prepare($SQL);
$sth->execute('foo');
$tbl_a_id = $answer->fetch()->[0];
$tbl_b_id = $answer->fetch()->[1];

未テスト。マニュアルには、それを行う方法の完全なDBD::Pgがあります。

于 2012-10-16T03:13:41.333 に答える
0

これは、主キーの処理方法によって異なります。一般に、シーケンスから値を選択してインクリメントを自分で処理するのが最善の策です。がシーケンスでインクリメントされると仮定するtableA.idと、次のような SQL ステートメントを実行して、データベースから追​​加の選択を実行できます。

SELECT NEXTVAL('seq_name'); <-- where seq_name is the name of the sequence you create

その値を選択し、データベースから取得した値を使用して、id以下の変更された挿入でパラメーターを設定します。

my $insertitA = $dbh->prepare("insert into tableA (id, information) values (?, ?)");

値を明示的に選択したので、それを参照テーブルにも挿入できます。

于 2012-10-15T20:56:21.090 に答える