Случайное значение в вычисляемых столбцах - PullRequest
0 голосов
/ 10 апреля 2020

У меня есть следующий скрипт, который создает таблицу:

CREATE TABLE [dbo].[Persons] 
(
    [Id]            INT IDENTITY(1,1) NOT NULL,
    [Name]          NVARCHAR(250)     NOT NULL,
    [Surname]       NVARCHAR(250)     NOT NULL,
    [NumberOfNotes] INT               NOT NULL,
    [TotalCash]     FLOAT             NULL,
    [Result] AS ([NumberOfNotes] * [TotalCash] * (RAND()*(100-30)+30)),

    CONSTRAINT [PK_Persons] PRIMARY KEY ([Id] ASC)
);

В моем случае при вставке новой записи есть только 2 возможных сценария ios:

  • вставка новая запись с [Имя], [Фамилия], [NumberOfNotes], [Результат]
  • вставка новой записи с [Имя], [Фамилия], [NumberOfNotes], [TotalCash]

Таким образом, я должен удовлетворять следующим двум критериям при создании

  1. Я должен иметь возможность вставить новую запись, где вычисляется [Result], если я не вставляю ее. Формула вычисления: [NumberOfNotes] * [TotalCash] * SomeRandomNumber , и я точно знаю, что в этом случае [TotalCash] всегда будет присутствовать для формулы и никогда не будет нулевым. Но если вместо этого я вставляю [Result] вручную, он вставит мое значение, а не вычисленное (в этом случае [TotalCash] может быть нулевым).
  2. SomeRandomNumber фиксируется для каждой записи. До сих пор я пробовал (RAND () * (100-30) +30)) , потому что я хочу случайное число от 30 до 100, но оно меняется при каждом выборе, который я запускаю в записях. Если вместо этого я заполняю его как (RAND (Id) * (100-30) +30)) , то же самое для нескольких записей.

Ответы [ 2 ]

0 голосов
/ 10 апреля 2020

Второе условие не может быть выполнено с использованием вычисляемого столбца, если только вычисляемый столбец не объявлен persisted.
Но для того, чтобы вычисляемый столбец сохранялся, он должен основываться на детерминированности. c функция - и Rand недетерминирован c.

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

CREATE TRIGGER tr_Persons_InsteadOfInsert
ON dbo.Persons
INSTEAD OF INSERT
AS

INSERT INTO dbo.Persons (Name, SurName, NumberOfNotes, TotalCach, Result)
SELECT  Name
      , SurName
      , NumberOfNotes
      , TotalCach
      , CASE WHEN TotalCach IS NOT NULL AND Result IS NULL THEN  
          [NumberOfNotes] * [TotalCash] * (RAND()*(100-30)+30)
        ELSE 
            Result
        END)
FROM Inserted

GO

Из Конечно, это будет означать, что столбец Result должен быть обычным столбцом, а не вычисляемым столбцом, я предполагаю, что вы хотите, чтобы он был float - поэтому вы должны изменить определение этого столбца.

0 голосов
/ 10 апреля 2020

Если вы хотите иметь возможность фактически записать в столбец Result, вы не можете использовать вычисляемый столбец.

Я бы рекомендовал иметь обычный столбец для Result и использовать представление реализовать отображение логики c, например:

create view PersonsView as
select
    Id,
    Name,
    Surname,
    NumberOfNotes,
    TotalCash,
    coalesce(Result, NumberOfNotes * TotalCash * rand(Id) * (100 - 30) + 30) Result
from [dbo].[Persons] 
...