使用 DataMapper 和旧版 PostgreSQL 数据库自动增量键

发布于 2024-10-21 15:23:20 字数 1099 浏览 1 评论 0原文

我有一个现有的 PostgreSQL 数据库,我想使用 Ruby DataMapper 访问它。我已经根据现有的数据库模式创建了模型,但主键不会自动递增。

我的模型如下所示:

class Company
  include DataMapper::Resource

  property :id, Serial
  property :name, String
end

id 定义为 Serial 无效:当我创建实例时,我收到 DataObjects::IntegrityError 因为违反了非空约束。

该数据库与 PHP/Doctrine 应用程序共享,因此我无法更改架构。 PHP 应用程序使用序列来创建主键,如下所示:

SELECT NEXTVAL('"production"."sequence_id_seq"') 
INSERT INTO "production"."companies" ("name", "id") VALUES ('Acme Inc.', 40711)

该表如下所示:

CREATE TABLE production.companies
(
  id bigint NOT NULL,
  "name" character varying(255) NOT NULL,
  CONSTRAINT companies_pkey PRIMARY KEY (id),
)
WITH (
  OIDS=FALSE
);

这是等效的 Doctrine 模式定义:

CompanyOrm:
  tableName: companies
  columns:
    id:
      type: integer(8)
      unsigned: 1
      primary: true
      sequence: sequence_id
    name:
      type: string(255)
      notnull: true

如何使用 DataMapper 重新创建该行为?或者在这种情况下还有哪些其他(更好)的解决方案可以创建自动递增键?

I have an existing PostgreSQL database that I want to access with Ruby DataMapper. I have created my models according to the existing database schemata, but primary keys are not auto incremented.

My models look like this:

class Company
  include DataMapper::Resource

  property :id, Serial
  property :name, String
end

Defining the id as Serial has no effect: when I create an instance I get an DataObjects::IntegrityError because of a violated not-null constraint.

The database is shared with a PHP/Doctrine application, so I cannot change the schema. The PHP application uses a sequence to create the primary keys like this:

SELECT NEXTVAL('"production"."sequence_id_seq"') 
INSERT INTO "production"."companies" ("name", "id") VALUES ('Acme Inc.', 40711)

The table looks like this:

CREATE TABLE production.companies
(
  id bigint NOT NULL,
  "name" character varying(255) NOT NULL,
  CONSTRAINT companies_pkey PRIMARY KEY (id),
)
WITH (
  OIDS=FALSE
);

This is the equivalent Doctrine schema definition:

CompanyOrm:
  tableName: companies
  columns:
    id:
      type: integer(8)
      unsigned: 1
      primary: true
      sequence: sequence_id
    name:
      type: string(255)
      notnull: true

How can I recreate that behavior with DataMapper? Or what other (better) solutions exist to create auto incrementing keys in this situation?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

夏九 2024-10-28 15:23:20

您可以在表达式中使用 nextval() 函数来获取下一个序列值并将其用作 id

INSERT INTO "production"."companies" ("name", "id") 
VALUES ('Acme Inc.', nextval('production.sequence_id_seq') )

我对 DataMapper 的了解不够,无法判断是否可以可能会导致在 INSERT 中使用函数,但也许可以通过定义自己的 Datamapper 来实现此目的: :Property(而不是串行)?

或者,您可以更改表以使行默认使用序列,这不会破坏与手动使用相同序列的任何内容的兼容性:

ALTER TABLE production.companies 
  ALTER COLUMN id SET DEFAULT nextval('production.sequence_id_seq');

You can use the nextval() function in an expression to fetch and use the next sequence value as the id:

INSERT INTO "production"."companies" ("name", "id") 
VALUES ('Acme Inc.', nextval('production.sequence_id_seq') )

I don't know enough about DataMapper to say whether or not it's possible to cause a function to be used in an INSERT, but maybe there's some way to do it by defining your own Datamapper::Property (instead of Serial)?

Alternatively, you could alter the table to make the row default to using the sequence, which shouldn't break compatibility with anything that manually uses the same sequence:

ALTER TABLE production.companies 
  ALTER COLUMN id SET DEFAULT nextval('production.sequence_id_seq');
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文