Ruby on Rails + PostgreSQL: использование пользовательских последовательностей - PullRequest
8 голосов
/ 19 октября 2011

Скажем, у меня есть модель с именем Transaction, которая имеет атрибут :transaction_code.Я хочу, чтобы этот атрибут автоматически заполнялся порядковым номером, который может отличаться от id (например, транзакция с id=1 может иметь transaction_code=1000).

Я попытался создать последовательность на postgres, а затемсделать значение по умолчанию для столбца transaction_code nextval этой последовательности.Дело в том, что если я не присваиваю значение @transaction.transaction_code в RoR, то при выдаче @transaction.save в RoR он пытается выполнить следующий SQL:

INSERT INTO transactions (transaction_code) VALUES (NULL);

Это создает новую строку в таблице транзакций с кодом транзакции NULL вместо вычисления следующего значения последовательности и вставки ее в соответствующий столбец.Таким образом, как я выяснил, если вы указываете NULL для postgres, предполагается, что вы действительно хотите вставить NULL в этот столбец, независимо от того, имеет ли он значение по умолчанию (я пришел из ORACLE, который ведет себя по-другому).

Я открыт для любого решения по этому вопросу, будь то в базе данных или в RoR:

  • или есть способ исключить атрибуты из ActiveRecord save
  • или есть способ изменить значение столбца перед вставкой с помощью триггера
  • , или есть способ сгенерировать эти порядковые номера в RoR
  • или любым другим способом, еслиэто работает: -)

Заранее спасибо.

Ответы [ 2 ]

6 голосов
/ 31 июля 2012

На данный момент вы можете застрять, выбирая и назначая последовательность в вашей модели ROR следующим образом:

before_create :set_transaction_code_sequence

def set_transaction_code_sequence
  self.transaction_code = self.class.connection.select_value("SELECT nextval('transaction_code_seq')")
end

Мне не особенно нравится это решение, так как я хотел бы увидеть этоисправлено в AR напрямую ... но это делает свое дело.

2 голосов
/ 20 октября 2011

Если вы хотите вставить значение по умолчанию в столбец в инструкции INSERT, вы можете использовать ключевое слово DEFAULT - без кавычек:

INSERT INTO mytable (col1, col2) VALUES (105, DEFAULT);

ИлиВы можете указать по умолчанию, nextval(...) в вашем случае.См. Руководство здесь .


A триггер для этого случая просто.Это действительно то, что я бы порекомендовал, если вы хотите убедиться, что вводятся только цифры из вашей последовательности, независимо от того, что.

CREATE OR REPLACE FUNCTION trg_myseq()
  RETURNS trigger AS
$BODY$
BEGIN

NEW.mycol := nextval('my_seq');
RETURN NEW;

END;
$BODY$
  LANGUAGE plpgsql VOLATILE;

CREATE TRIGGER myseq
  BEFORE INSERT
  ON mytable
  FOR EACH ROW
  EXECUTE PROCEDURE trg_myseq();

Примечание: если вы хотите назначить свои собственные (непоследовательные) числа как «последовательность», решение для этого я написал в ответе пару дней назад:
Как указать список значений для последовательности postgresql

...