如何在DbFit中执行MERGE?

时间:2016-12-01 23:23:40

标签: .net fitnesse dbfit

我想确保在对数据库执行测试之前填充参考表。我想要使​​用的特定数据可能已经或可能不在测试数据库中,因此我想执行MERGE(也称为UPSERT),如果数据尚未包含在表中并更新,则会插入数据如果是的话。

从我在Googling中可以看到,DbFit似乎不支持MERGE命令,也不支持执行从外部SQL脚本文件加载的SQL(计划B是在SQL脚本文件中创建MERGE,然后加载文件并在DbFit中运行它。

在DbFit中是否有直接的方法来执行MERGE,或者我需要创建一个特殊的夹具类才能完成它?

1 个答案:

答案 0 :(得分:0)

我想出了如何使用FitSharp版本的DbFit中的标准命令来完成它。

此示例针对 SQL Server 数据库执行。 Oracle的MERGE语句有类似的语法,虽然我不知道它如何处理临时表。 MySQL没有MERGE语句;它有一个非标准的命令,可以实现同样的目的。它还支持临时表,但我不熟悉MySql临时表的语法。

这是我想要将数据合并到的目标表的定义:

CREATE TABLE Student 
(
    [Name] NVARCHAR(200), 
    DateOfBirth DATETIME, 
    Notes NVARCHAR(1000)
);

这是将数据合并到其中的DbFit Flow模式页面:

!| Execute | CREATE TABLE #MergeSource ([Name] NVARCHAR(200), DateOfBirth DATETIME, Notes NVARCHAR(1000)); |

!| Insert | tempdb.dbo.#MergeSource |
| Name       | DateOfBirth | Notes                |
| Jane Smith | 1997-09-24  | These are some notes |
| John Doe   | 2000-04-06  | Other notes          |

!| Execute | !-
MERGE INTO Student AS target
USING 
    (
        SELECT [Name], [DateOfBirth], [Notes]
        FROM #MergeSource
    ) AS source
ON target.[Name] = source.[Name]
WHEN MATCHED THEN
    UPDATE 
    SET [DateOfBirth] = source.[DateOfBirth], 
        [Notes] = source.[Notes]
WHEN NOT MATCHED BY TARGET THEN 
    INSERT ([Name], [DateOfBirth], [Notes])
    VALUES (source.[Name], source.[DateOfBirth], source.[Notes]);
    -! |

!| Query | SELECT [Name], DateOfBirth, Notes FROM Student; |
| Name       | DateOfBirth | Notes                |
| Jane Smith | 1997-09-24  | These are some notes |
| John Doe   | 2000-04-06  | Other notes          |

首先创建一个临时表作为MERGE的数据源。要合并的数据将插入临时表,然后执行MERGE语句。 MERGE不需要最后的Query命令,只是添加它来检查目标表是否已正确更新。

请注意,Insert命令必须使用临时表的三部分名称,至少在SQL Server中是这样。当针对SQL Server执行Insert命令时,它会在后台查询sys.columns以获取有关要插入的表的列信息:

exec sp_executesql N'select c.[name], TYPE_NAME(c.system_type_id) as [Type], c.max_length, 
    0 As is_output, 0 As is_cursor_ref, c.precision, c.scale
    from tempdb. sys.columns c 
    where c.object_id = OBJECT_ID(@objname) 
    order by column_id',
        N'@objname nvarchar(23)',
        @objname=N'tempdb.dbo.#MergeSource'

如果将表名指定为由三部分组成的名称,OBJECT_ID函数将仅返回临时表的对象ID。这是因为SQL Server始终在tempdb数据库中创建临时表,而不是将要使用临时表的数据库。 OBJECT_ID函数将找不到临时表的元数据,除非它被告知在tempdb数据库中查找它。