Или ИЛИ непустые ограничения в MySQL

Я понял это, вот решение.

Контроллер:

 # GET /agreements/1/release
 def release
   @agreement.released_at = Time.now.utc

   if @agreement.save
     render json: {success: ["Agreement released."]}
   else
     render json: @agreement.errors, status: :unprocessable_entity
   end
 end    

Модель:

class Agreement < ApplicationRecord
  validate :released_agreement_cannot_be_released

  def released_agreement_cannot_be_released
    if released_at_was.present?
      errors.add(:released_at, "already released")
    end
  end
end
11
задан mpeters 4 October 2008 в 15:14
поделиться

4 ответа

Это не ответ непосредственно на Ваш вопрос, но некоторую дополнительную информацию.

При контакте с несколькими столбцами и проверке, являются ли все пустыми или каждый не является пустым, я обычно использую COALESCE() - это кратко, читаемо и легко удобно в сопровождении, если список растет:

COALESCE(a, b, c, d) IS NULL -- True if all are NULL

COALESCE(a, b, c, d) IS NOT NULL -- True if any one is not null

Это может использоваться в Вашем триггере.

8
ответ дан 3 December 2019 в 03:54
поделиться

Я сделал что-то подобное в SQL Server, я не уверен, будет ли это работать непосредственно в MySQL, но:

ALTER TABLE tableName ADD CONSTRAINT constraintName CHECK ( (fieldA IS NOT NULL) OR (fieldB IS NOT NULL) );

По крайней мере, я полагаю, что это - синтаксис.

Однако имейте в виду, что Вы не можете создать проверочные ограничения через таблицы, можно только проверить столбцы в одной таблице.

2
ответ дан 3 December 2019 в 03:54
поделиться

@Sklivvz: Тестируя с MySQL 5.0.51a, я нахожу, что он анализирует ограничение CHECK, но не осуществляет его. Я могу вставить (ПУСТОЙ УКАЗАТЕЛЬ, ПУСТОЙ УКАЗАТЕЛЬ) без ошибки. Протестированный и MyISAM и InnoDB. Впоследствии использование ВЫСТАВОЧНОГО CREATE TABLE показывает, что ограничение CHECK не находится в определении таблицы, даже при том, что никакая ошибка не была дана, когда я определил таблицу.

Это соответствует руководству MySQL, в котором говорится: "Пункт ПРОВЕРКИ анализируется, но игнорируется всеми механизмами устройства хранения данных".

Таким образом для MySQL, необходимо было бы использовать триггер для осуществления этого правила. Единственная проблема состоит в том, что триггеры MySQL не имеют никакого способа повысить ошибку или прервать операцию ВСТАВКИ. Одна вещь, которую можно сделать в триггере для порождения ошибки, состоит в том, чтобы установить столбец NOT NULL в NULL.

CREATE TABLE foo (
  FieldA INT,
  FieldB INT,
  FieldA_or_FieldB TINYINT NOT NULL;
);

DELIMITER //
CREATE TRIGGER FieldABNotNull BEFORE INSERT ON foo
FOR EACH ROW BEGIN
  IF (NEW.FieldA IS NULL AND NEW.FieldB IS NULL) THEN
    SET NEW.FieldA_or_FieldB = NULL;
  ELSE
    SET NEW.FieldA_or_FieldB = 1;
  END IF;
END//

INSERT INTO foo (FieldA, FieldB) VALUES (NULL, 10); -- OK
INSERT INTO foo (FieldA, FieldB) VALUES (10, NULL); -- OK
INSERT INTO foo (FieldA, FieldB) VALUES (NULL, NULL); -- gives error

Вам также нужен подобный триггер ПЕРЕД ОБНОВЛЕНИЕМ.

7
ответ дан 3 December 2019 в 03:54
поделиться

Это - стандартный синтаксис для такого ограничения, но MySQL блаженно игнорирует ограничение впоследствии

ALTER TABLE `generic` 
ADD CONSTRAINT myConstraint 
CHECK (
  `FieldA` IS NOT NULL OR 
  `FieldB` IS NOT NULL
) 
4
ответ дан 3 December 2019 в 03:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: