T-SQL触发器抛出:更新或删除的行值不会使该行唯一或它们会更改多行

时间:2017-04-06 21:45:34

标签: sql-server tsql

下面的触发器在三个相关表中的一个上定义,并更新另一个表。然而,它不起作用。相反,它抛出:

第3行中的数据未提交。 错误源:Microsoft.SqlServer.Management.DataTools。 错误消息:更新或删除的行值不会使该行唯一,也不会更改多行(24行)。

CREATE TABLE [Develop].[TemplateSqlProjects]
(
    [Id] INT IDENTITY (1, 1) NOT NULL,
    [Name] NVARCHAR (50) NOT NULL,
    CONSTRAINT [PK_Develop.TemplateSqlProjects] PRIMARY KEY CLUSTERED ([Id] ASC)
);
GO

CREATE UNIQUE NONCLUSTERED INDEX [Develop_TemplateSqlProjects_Name_Unique]
    ON [Develop].[TemplateSqlProjects]([Name] ASC);
GO
-------------------------------------------------------------------------------------------------
CREATE TABLE [Develop].[TemplateSqlStatements]
(
    [Id] INT IDENTITY (1, 1) NOT NULL,
    [ProjectId] INT NOT NULL,
    [SqlStatement] NVARCHAR (MAX) NOT NULL,
    CONSTRAINT [PK_Develop.TemplateSqlStatements] PRIMARY KEY NONCLUSTERED ([Id] ASC),
    CONSTRAINT [FK_Develop.TemplateSqlStatements_Develop.TemplateSqlProjects_ProjectId]
        FOREIGN KEY ([ProjectId]) REFERENCES [Develop].[TemplateSqlProjects] ([Id]) ON DELETE CASCADE
);
-------------------------------------------------------------------------------------------------
CREATE TABLE [Develop].[TemplateSqlStatementGuids]
(
    [Id] INT IDENTITY (1, 1) NOT NULL,
    [SqlStatementId] INT NOT NULL,
    [Guid] UNIQUEIDENTIFIER NOT NULL,
    CONSTRAINT [PK_Develop.TemplateSqlStatementGuids] PRIMARY KEY NONCLUSTERED ([Id] ASC),
    CONSTRAINT [FK_Develop.TemplateSqlStatementGuids_Develop.TemplateSqlStatements_SqlStatementId]
        FOREIGN KEY ([SqlStatementId]) REFERENCES [Develop].[TemplateSqlStatements] ([Id]) ON DELETE CASCADE
);

GO
CREATE UNIQUE CLUSTERED INDEX [SqlStatementId_Guid_Unique]
    ON [Develop].[TemplateSqlStatementGuids]([SqlStatementId] ASC, [Guid] ASC);
GO
CREATE NONCLUSTERED INDEX [Develop_TemplateSqlStatementGuids_Guid]
    ON [Develop].[TemplateSqlStatementGuids]([Guid] ASC);
GO
-------------------------------------------------------------------------------------------------
CREATE TRIGGER [Develop].[Trigger_Develop_TemplateSqlStatements_AfterInsertOrUpdate] ON [Develop].[TemplateSqlStatements]
AFTER INSERT, UPDATE, DELETE
AS 
BEGIN

    DELETE FROM Develop.TemplateSqlStatementGuids
    WHERE SqlStatementId IN (SELECT Id FROM DELETED);

    DELETE FROM Develop.TemplateSqlStatementGuids
    WHERE SqlStatementId IN (SELECT Id FROM INSERTED);

    INSERT INTO Develop.TemplateSqlStatementGuids (SqlStatementId, [Guid])
    SELECT DISTINCT i.Id, f.Value
    FROM INSERTED i
    CROSS APPLY Utility.ft_ExtractGuids(i.SqlStatement) f
    ORDER BY i.Id, f.Value

END
GO
-------------------------------------------------------------------------------------------------
CREATE FUNCTION [Utility].[ft_ExtractGuids] (@Text NVARCHAR(MAX))
RETURNS @Guids TABLE ( Value UNIQUEIDENTIFIER)
AS
BEGIN
    DECLARE @IndexStart AS BIGINT;
    DECLARE @IndexEnd AS BIGINT;
    SELECT @IndexStart = PATINDEX(N'%' + REPLACE(N'00000000-0000-0000-0000-000000000000', N'0', N'[0-9a-fA-F]') + N'%', @Text)
    WHILE @IndexStart > 0 AND LEN(@Text) > 36
        BEGIN
            INSERT INTO @Guids (Value) VALUES (TRY_CONVERT(UNIQUEIDENTIFIER, SUBSTRING(@Text, @IndexStart, 36)));
            SET @Text = SUBSTRING(@Text, @IndexStart + 36, LEN(@Text) - 36);
            SET @IndexStart = PATINDEX(N'%' + REPLACE(N'00000000-0000-0000-0000-000000000000', N'0', N'[0-9a-fA-F]') + N'%', @Text);
        END
    DELETE FROM  @Guids WHERE Value = N'00000000-0000-0000-0000-000000000000';
    RETURN;
END

它似乎应该有效。这些值是唯一的。我尝试了很多变体,例如消除, DELETE操作,插入没有约束的 temp 表等等。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

请检查以下选择您要插入TemplateSqlStatementGuids表的内容。

SELECT DISTINCT i.Id, f.Value
    FROM INSERTED i
    CROSS APPLY Utility.ft_ExtractGuids(i.SqlStatement) f
    ORDER BY i.Id, f.Value

您似乎正在尝试使用交叉应用将f.value插入到guid列中。如果我错了,请纠正我。