Проверка ограничений SQL или триггер? - PullRequest
2 голосов
/ 21 февраля 2012

Я искал в сети какой-то ответ на этот вопрос. но все, что я получаю, это простые ответы.

У меня есть несколько столбцов в моей базе данных, которые должны иметь ограничение на их максимальное значение, но не, если для другого столбца установлено значение false

например. У меня есть следующие значения в таблице

ROW    ValueA          TRUE/FALSE       ValueB
0      3750            TRUE              0
1      5000            TRUE              0
2      5000            FALSE             0    [INITIAL VALUES PROVIDED]
2      3750            FALSE             1250 [ACTUAL VALUES ACCEPTED]

В этой таблице Row2 предоставляется внешней программой, где ValueA изначально равно 5000, однако для этой строки установлено значение FALSE, поэтому оно ограничит значение до 3750 и добавит 1250 к ValueB

Теперь идея заключается в том, что если установлено значение true, оно может обойти проверку. но если для этой строки установлено значение false, а значение больше 3750, следует уменьшить значение ValueA до 3750 и поместить остаток в ValueB.

Возможно ли это сделать с помощью выражения проверки ограничений, или было бы разумнее использовать для этого триггер до обновления?

Ответы [ 3 ]

1 голос
/ 21 февраля 2012

Вам необходим триггер для этого, потому что ограничения не могут установить значение другого столбца на основе условия (как вы делаете здесь)

1 голос
/ 22 февраля 2012

Я предлагаю вам две таблицы: промежуточную таблицу для хранения необработанных данных из внешней программы и вторую таблицу, к которой были применены бизнес-правила. Эта вторая таблица может быть просто VIEW, который запрашивает данные, применяя правила, например (Я использую CTE для имитации промежуточной таблицы с примерами данных; также SQL Server не имеет истинного логического типа, поэтому я имитирую его с помощью столбца CHAR(1), и имя делает мою голову так, чтобы я изменит его на some_flag!):

WITH Staging
     AS
     (
      SELECT * 
        FROM (
              VALUES (0, 3750, 'T'), 
                     (1, 5000, 'T'), 
                     (2, 5000, 'F')
             ) AS T (ROW, ValueA, some_flag)
     )
SELECT ROW, ValueA, some_flag,  
       0 AS ValueB
  FROM Staging
 WHERE ( ValueA <= 3750 OR some_flag = 'T' )
UNION
SELECT ROW, 3750 AS ValueA, some_flag,  
       ( ValueA - 3750 ) AS ValueB
  FROM Staging
 WHERE ValueA > 3750 AND some_flag = 'F';

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

IF some_flag = 'F' THEN ValueA <= 3750
IF some_flag = 'T' THEN ValueB = 0
IF some_flag = 'F' AND ValueA < 3750 THEN ValueB = 0

В SQL как CHECK ограничения (я угадал некоторые бизнес-правила «здравого смысла»):

CREATE TABLE MyTable
(
 ROW INTEGER NOT NULL UNIQUE, 
 ValueA INTEGER NOT NULL CHECK ( ValueA > 0 ), 
 some_flag CHAR(1) NOT NULL CHECK ( some_flag IN ( 'T', 'F' ) ), 
 ValueB INTEGER NOT NULL CHECK ( ValueB >= 0 ), 
 CHECK ( some_flag <> 'F' OR ValueA <= 3750 ), 
 CHECK ( some_flag <> 'T' OR ValueB = 0 ), 
 CHECK ( some_flag <> 'F' OR ValueA >= 3750 OR ValueB = 0 )
);

Затем вы можете использовать вышеупомянутый запрос для копирования данных из промежуточной таблицы в базовую таблицу, не нарушая при этом никаких ограничений, но при этом понимая, что если вы ошиблись в запросе, процедура потерпит неудачу!

1 голос
/ 21 февраля 2012

На мой взгляд, это звучит как "сложная" бизнес-логика.

под сложным, я имею в виду некоторые проверки, если некоторые, и другое поведение, основанное на правилах.

в этом случае я бы сделал проверку в триггере.

...