Хранимая процедура. Проверьте, используются ли ограничения в другой таблице - PullRequest
0 голосов
/ 30 августа 2018

Я получаю это сообщение об ошибке:

Оператор DELETE конфликтует с ограничением REFERENCE. "FK_FieldMapper_Field". Конфликт произошел в базе данных "SCAM", таблица "dbo.FieldMapper", столбец "FieldID".

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

Когда я удаляю accesshelper, мне нужно проверить, используются ли fields в данном accesshelper другими accesshelpers. Если они есть, я удалю помощник доступа, но не поля, так как это сломало бы другие помощники доступа. Как мне это сделать?

Это то, что я придумал сам до сих пор.

USE [SCAM]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[deleteAccessHelperById]

@Id int
AS
BEGIN

    SET NOCOUNT ON;

    DECLARE @projectIds TABLE (id int);
    INSERT INTO @projectIds ([id]) SELECT dbo.AccessHelperMapper.ProjectID FROM dbo.AccessHelperMapper WHERE dbo.AccessHelperMapper.AccessHelperID = @Id;

    DELETE dbo.AccessHelperMapper  WHERE dbo.AccessHelperMapper.AccessHelperID = @Id;

    DECLARE @fieldIds TABLE (id int);

    INSERT INTO @fieldIds ([id]) SELECT dbo.FieldMapper.FieldID FROM dbo.FieldMapper WHERE dbo.FieldMapper.AccessHelperID = @Id;


    DECLARE @AHfields TABLE (id int)
    Insert into @AHfields 
    Select fids.id from dbo.FieldMapper, @fieldIds as fids
    where dbo.FieldMapper.AccessHelperID != @Id
    and fids.id != dbo.FieldMapper.FieldID;

    delete dbo.FieldMapper where dbo.FieldMapper.AccessHelperID = @Id and dbo.FieldMapper.FieldID IN (SELECT d.id FROM @AHfields as d);
    delete dbo.Field where dbo.Field.ID in (SELECT g.id FROM  @AHfields as g);
    delete dbo.AccessHelper where dbo.AccessHelper.ID = @Id;


END

Ответы [ 2 ]

0 голосов
/ 30 августа 2018

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

ALTER PROCEDURE [dbo].[deleteAccessHelperById]
  @Id int
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @fieldIds TABLE (id int);

    BEGIN TRY
      BEGIN TRAN

      DELETE ahm
      FROM dbo.AccessHelperMapper ahm 
      WHERE ahm.AccessHelperID = @Id;

      DELETE fm
        OUTPUT DELETED.fieldID
        INTO @fieldIds(id)
      FROM dbo.FieldMapper fm
      WHERE fm.AccessHelperID = @Id 

      DELETE f
      FROM dbo.Field f
      WHERE exists(select 1 from @fieldIDs fid where fid.ID = f.ID)
        and not exists(
          select 1 from dbo.FieldMapper fm
          where fm.fieldID = f.ID 
             and fm.AccessHelperID != @ID  -- redundant, may be removed.
        )

      DELETE ah
      FROM dbo.AccessHelper ah
      where ah.ID = @Id

      COMMIT TRAN
    END TRY
    BEGIN CATCH
      IF XACT_STATE() IN (1, -1)
        ROLLBACK TRAN

      THROW;
    END CATCH
END
0 голосов
/ 30 августа 2018

Попробуйте приведенный ниже код. Надеюсь, это то, что вы искали:

USE [SCAM]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[deleteAccessHelperById]

@Id int
AS
BEGIN

SET NOCOUNT ON;

DELETE dbo.AccessHelperMapper  WHERE dbo.AccessHelperMapper.AccessHelperID = @Id;

DECLARE @fieldIds TABLE (id int);

INSERT INTO @fieldIds ([id]) SELECT dbo.FieldMapper.FieldID FROM dbo.FieldMapper WHERE dbo.FieldMapper.AccessHelperID = @Id
AND dbo.FieldMapper.FieldID NOT IN (SELECT DISTINCT dbo.FieldMapper.FieldID FROM dbo.FieldMapper WHERE dbo.FieldMapper.AccessHelperID != @Id);

delete dbo.FieldMapper where dbo.FieldMapper.AccessHelperID = @Id --and dbo.FieldMapper.FieldID IN (SELECT d.id FROM @fieldIds as d);
delete dbo.Field where dbo.Field.ID in (SELECT g.id FROM  @fieldIds as g);
delete dbo.AccessHelper where dbo.AccessHelper.ID = @Id;


END
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...