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

Я пытаюсь сохранить целостность таблицы MEMORY OPTIMIZED, которая у меня есть. В этой таблице есть внешний ключ (уникальный идентификатор), указывающий на другую таблицу, и активный флаг (бит), обозначающий, активна запись или нет.

Я хочу, чтобы вставки не происходили, если входящая запись имеет тот же внешний ключ, что и существующая запись, только если существующая запись активна (Active = 1).

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

ОБНОВЛЕНИЕ. В итоге я использовал хранимую процедуру для решения своей проблемы. Хранимая процедура проверит меня перед вставкой или обновлением записи.


person Joe H    schedule 20.11.2019    source источник


Ответы (1)


Большинство людей обходят ограничения таблиц в памяти с помощью триггеров. Здесь приведено несколько примеров:

https://www.mssqltips.com/sqlservertip/3080/workaround-for-lack-of-support-for-constraints-on-sql-server-memoryoptimized-tables/

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

-- note the use of checksum to make a single unique value from the combination of two columns

CREATE TRIGGER InMemory.TR_Customers_Insert ON InMemory.Customers
 WITH EXECUTE AS 'InMemoryUsr'
  INSTEAD OF INSERT  
AS
 SET NOCOUNT ON
 --CONSTRAINT U_OnDisk_Customersg_1 UNIQUE NONCLUSTERED (CustomerName, CustomerAddress)
  IF EXISTS (
    -- Check if rows to be inserted are consistent with CHECK constraint by themselves
    SELECT 0
        FROM  INSERTED I
    GROUP BY CHECKSUM(I.CustomerName, I.CustomerAddress) 
    HAVING COUNT(0) > 1
    UNION ALL

       -- Check if rows to be inserted are consistent with UNIQUE constraint with existing data
    SELECT 0
        FROM  INSERTED I
    INNER JOIN InMemory.tblCustomers C WITH (SNAPSHOT)
      ON  C.ChkSum = CHECKSUM(I.CustomerName, I.CustomerAddress)
    ) 
    BEGIN
      ;THROW 50001, 'Violation of UNIQUE Constraint! (CustomerName, CustomerAddress)', 1
    END
  INSERT INTO InMemory.tblCustomers WITH (SNAPSHOT)
      ( CustomerID ,
       CustomerName ,
       CustomerAddress,
    chksum
      )
  SELECT  NEXT VALUE FOR InMemory.SO_Customers_CustomerID ,
      CustomerName ,
      CustomerAddress,
   CHECKSUM(CustomerName, CustomerAddress)
 FROM INSERTED
 GO
person RThomas    schedule 20.11.2019