Эквивалент C # «только для чтения» для столбца MS SQL? - PullRequest
4 голосов
/ 02 августа 2011

Представьте, что в таблице Products есть столбец Price, и цена может измениться.
Я в порядке, если он меняется, но Я хочу сохранить исходное значение Price в другом столбце.

Есть ли какой-нибудь автоматический способ, которым сервер MS SQL может сделать это?

Могу ли я сделать это, используя Значение по умолчанию поле?
Обязательно лиобъявить триггер?

Обновление

Я пытался использовать Price, чтобы упростить вопрос, но, похоже, этот спровоцированный тип ответов "использовать отдельную таблицу".
Извинитеза путаницу, которую я вызвал.

В реальном мире Мне нужно сохранить идентификатор внешнего ключа, и я на 100% мне нужны только текущие и оригинальные значения .

Обновление 2

Меня немного смутили различные предложенные подходы, поэтому, пожалуйста, позвольте мне объяснить ситуацию еще раз.

Воображаемая таблица Products состоит из трех полей: ID, Price и OriginalPrice.
Я хочу установить OriginalPrice в Price значение на любой вставке .

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

После установки OriginalPrice я никогда не собираюсь обновлять его.

Надеюсь, теперь мой вопрос прояснился.
Спасибо за ваши усилия.

Окончательное обновление

Я хочу поблагодарить всех, особенно @ gbn , за помощь.
Хотя я отправил мой собственный ответ ,это в значительной степени основано на ответе @ gbn и его дальнейших предложениях.Его ответ также более полный, поэтому я отмечаю его как правильный.

Ответы [ 4 ]

3 голосов
/ 02 августа 2011

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

Давайте проигнорируем, если такое же обновление происходит в быстрой последовательности из-за ошибки в коде клиента и что вас не интересует история (другие ответы)

Вы можете использовать триггер или хранимую процедуру.

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

  CREATE PROC etc
  ...
  UPDATE
    MyTable
  SET
    OldPrice = Price,
    Price = @NewPrice,
    UpdatedBy = (variable or default)
    UpdatedWhen = DEFAULT --you have a DEFAULT right?
  WHERE
    PKCol = @SomeID
    AND --provide some modicum of logic to trap useless updates
    Price <> @NewPrice;

Триггер будет аналогичным, но вам нужно иметь JOIN с таблицами INSERTED и DELETED Что если кто-то обновит OldPrice напрямую?

  UPDATE
    T
  SET
    OldPrice = D.Price
  FROM
    Mytable T
    JOIN
    INSERTED I ON T.PKCol = I.PKCol
    JOIN
    DELETED D ON T.PKCol = D.PKCol
  WHERE
    T.Price <> I.Price;

Теперь вы понимаете, почему на вас прыгнули ...?

После редактирования вопроса, для INSERT * только 1018 *

  UPDATE
    T
  SET
    OriginalPrice = I.Price
  FROM
    Mytable T
    JOIN
    INSERTED I ON T.PKCol = I.PKCol

Но если бы все INSERT происходили с помощью хранимой процедуры, я бы установил их там ...

2 голосов
/ 02 августа 2011

Нет атрибута только для чтения для столбца таблицы SQL Server.НО вы можете реализовать описанную вами функциональность с помощью триггера (и ограничения разрешений)

За исключением , это не лучший способ решения проблемы.Вместо этого рассматривайте цену как тип 2 «медленно меняющееся измерение». Это предполагает наличие столбца «ValidTo» (столбцы «StartDate» и «EndDate») и закрытие записи:

Supplier_Key    Supplier_Code   Supplier_Name   Supplier_State  Start_Date  End_Date
123           ABC             Acme Supply Co    CA            01-Jan-2000   21-Dec-2004
124           ABC             Acme Supply Co    IL            22-Dec-2004   

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

1 голос
/ 02 августа 2011

Я бы рекомендовал хранить вашу цену в отдельной таблице Prices со столбцами Price и Date.

Затем, когда цена обновляется, INSERT новая запись в таблице Prices. Тогда, когда вам нужно узнать текущую цену, вы можете вытащить оттуда.


Однако, если вы хотите обновить столбец OriginalPrice автоматически, вы можете добавить TRIGGER в таблицу, чтобы сделать это:

http://msdn.microsoft.com/en-us/library/aa258254%28v=sql.80%29.aspx

0 голосов
/ 02 августа 2011

Это то, чем я закончил, с тяжелой помощью от @ gbn , @ Mitch и @ Curt :

create trigger TRG_Products_Price_I --common-ish naming style
    on dbo.Products after insert as
begin
    set nocount on

        update m
        set OriginalPrice = i.Price 
        from Products p
        join inserted i on p.ID = i.ID

end

Я тоже пытался следовать этой статье .
Спасибо всем!

...