【问题标题】:How to maintain transaction integrity per common column value for inserting into two tables?如何维护每个公共列值的事务完整性以插入两个表?
【发布时间】:2019-07-09 16:26:55
【问题描述】:

假设我有两个表变量声明如下:

DECLARE @Table1 TABLE (
  A INT,
  B NVARCHAR(100)
)

DECLARE @Table2 TABLE (
  A INT,
  C NVARCHAR(100)
)

这是@Table1的内容:

1, 'Hello'
2, 'Hi'
3, 'Ola'

这些是@Table2的内容:

1, 'my old friend'
1, 'sweetheart'
2, 'buddy'
4, 'the end'

现在我想将@Table1 插入到表 X 中,将@Table2 插入到表 Y 中。场景是我必须维护事务完整性,以便为 A 列的每个相同值插入 X 和 Y。

例如,假设我将@Table1 的第一行 (1,'Hello') 插入 X。这意味着我还必须插入前两行 ((1,'my old friend'), (1 ,'sweetheart')) 在同一事务中将 @Table2 放入 Y 中。因此,如果 Y 的任何插入因 A=1 失败,则 X 也因 A=1 失败。对于不在@Table1 和@Table2 中的列A 的任何值,它们本身就是单独的事务(例如@Table1 中的A=3 和@Table2 中的A=4)。

以下是我看到的处理此问题的方法:

  1. 我在 @Table1 和 @Table2 中获取 A 的所有值,在其上运行游标,然后对于 A 的每个值,我在单个事务中插入表 X 和 Y。这里的问题首先是,我不想尽可能多地使用游标,而且这意味着大量的单独插入。

  2. 我预先验证了我的@Table1 和@Table2 值,然后在X 上插入@Table1,在Y 上插入@Table2。这将比上述方法快得多。但我在这里看到的问题是,首先,不把它放在“交易”中似乎不正确,而且,我可能在某个地方错过了验证(不太可能,但仍然如此)。

我应该采用哪种方法?有没有更好的解决方案?

附:另请注意,如果仅插入一个或几个 A 值时出现问题,我不想在 X 和 Y 上的整个插入失败。此外,根据失败的插入返回并从我的数据库中删除表也是不是一个选项,因为它与我试图避免的运行 ID 连续性相混淆。

【问题讨论】:

    标签: sql sql-server


    【解决方案1】:

    一条 DML 语句完全执行或根本不执行。

    您可以混合使用两种选择

    首先添加尽可能多的验证,如果失败则使用临时表而不是游标运行第二个

    BEGIN TRY
        BEGIN TRAN Opt2
        --Option 2
        COMMIT TRAN Opt2
    END TRY
    BEGIN CATCH
        ROLLBACK TRAN Opt2
        DECLARE @A INT, @B VARCHAR(100)
        SELECT * INTO #TMP FROM @Table1
        WHILE EXISTS (SELECT 1 FROM #TMP)
        BEGIN
            SELECT TOP 1 @A = A, @B = B FROM @Table1
            -- Option 1
            DELETE #Temp WHERE A = @A
        END
    END CATCH
    

    【讨论】:

      猜你喜欢
      • 2017-05-27
      • 1970-01-01
      • 1970-01-01
      • 2011-03-06
      • 1970-01-01
      • 1970-01-01
      • 2021-09-21
      • 2011-11-26
      • 2023-01-30
      相关资源
      最近更新 更多