Как поместить функцию в ограничение внешнего ключа? - PullRequest
0 голосов
/ 18 апреля 2019

У меня есть определение таблицы:

CREATE TABLE [dbo].[T] (
   [A]        NVARCHAR (128) NOT NULL,
   [B]        NVARCHAR (128) NOT NULL,
   [C]        BIT            NOT NULL,
   [D]        INT            NOT NULL,
   [E]        DATETIME       NOT NULL,
   CONSTRAINT [PK_dbo.T] PRIMARY KEY CLUSTERED (A,B,C)
);

И частично еще одно:

CREATE TABLE [dbo].[W] (
   [A]      INT IDENTITY(1,1),
   [B]      NVARCHAR (128) NOT NULL,
   [C]      BIT            NOT NULL,
   [D]      INT            NOT NULL,
   [E]     TIME        NULL,
   [F]      TIME           NULL,
   CONSTRAINT [PK_dbo.W] PRIMARY KEY CLUSTERED ([A] ASC),
   CONSTRAINT [FK_dbo.W_T] FOREIGN KEY(PARSENAME(REPLACE([B], '_', '.'), 2), PARSENAME(REPLACE([B], '_', '.'), 1), [C]) REFERENCES T(A,B,C) ON DELETE CASCADE
);

Это не работает, потому что не позволит мне поместить функцию вограничение внешнего ключа.

T.A_T.B равно W.B

Я пытаюсь сказать, что все W должны соответствовать T, где W.B равно CONCAT(T.A, '_', T.B) и W.C равноT.C

Затем, если запись в T удалена, все соответствующие W на основе внешнего ключа должны быть удалены.

1 Ответ

0 голосов
/ 18 апреля 2019

Я не согласен, что это лучшая идея (отнюдь не так), но вы могли бы заново изобрести колесо и сделать детерминистическую версию PARSENAME, а затем создать столбец PERSISTEDна что:

USE Sandbox;
GO

CREATE FUNCTION dbo.fn_parsename (@ObjectName nvarchar(386), @PartNum tinyint)
RETURNS sysname
WITH SCHEMABINDING
AS BEGIN
    DECLARE @PartName sysname;
    SELECT @PartName = SUBSTRING(@ObjectName,
                                 CASE @PartNum WHEN 1 THEN 1
                                               WHEN 2 THEN one.CI+1
                                               WHEN 3 THEN two.CI+1   
                                               WHEN 4 THEN three.CI+1
                                 END,
                                 CASE @PartNum WHEN 1 THEN one.CI-1
                                               WHEN 2 THEN ISNULL(two.CI -1,LEN(obj)) - one.CI
                                               WHEN 3 THEN ISNULL(three.CI -1,LEN(obj)) - two.CI
                                               WHEN 4 THEN ISNULL(four.CI -1,LEN(obj)) - three.CI
                                 END) 
    FROM (VALUES(@ObjectName)) V(Obj)
         CROSS APPLY (VALUES(NULLIF(CHARINDEX('.',V.obj),0))) one(CI)
         CROSS APPLY (VALUES(NULLIF(CHARINDEX('.',V.obj,one.CI+1),0))) two(CI)
         CROSS APPLY (VALUES(NULLIF(CHARINDEX('.',V.obj,two.CI+1),0))) three(CI)
         CROSS APPLY (VALUES(NULLIF(CHARINDEX('.',V.obj,three.CI+1),0))) four(CI);

    RETURN @PartName;
END;



GO
CREATE TABLE Test (ObjectName nvarchar(386),
                   DatabaseName AS dbo.fn_parsename(ObjectName,1) PERSISTED)
GO

INSERT INTO dbo.Test (ObjectName)
VALUES('Sandbox.dbo.Test'),
      ('AdventureWorks2012.Person.Address');
SELECT *
FROM dbo.Test;

GO        

DROP TABLE Test;
DROP FUNCTION dbo.fn_parsename;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...