Как я могу выполнить MERGE в DbFit?
Я хотел бы убедиться, что справочные таблицы заполнены, прежде чем выполнять тесты для базы данных. Конкретные данные, которые я хочу использовать, могут или не могут быть уже в тестовой базе данных, поэтому я хотел бы выполнить MERGE (также известный как UPSERT), который вставил бы данные, если их еще не было в таблице, и обновил бы это если бы было.
Из того, что я вижу из Google, DbFit, похоже, не поддерживает команду MERGE, а также не поддерживает выполнение SQL, загруженного из внешнего файла сценария SQL (план B состоял в том, чтобы создать MERGE в файле сценария SQL, а затем загрузить файл и запустить его в DbFit).
Есть ли какой-нибудь прямой способ выполнить MERGE в DbFit, или мне нужно будет создать специальный класс фикстур для этого?
1 ответ
Я понял, как это сделать, используя только стандартные команды из версии FitSharp DbFit.
Этот пример выполняется для базы данных SQL Server. У Oracle аналогичный синтаксис для оператора MERGE, хотя я не знаю, как он обрабатывает временные таблицы. MySQL не имеет оператора MERGE; у него есть нестандартная команда, которая выполняет то же самое. Он также поддерживает временные таблицы, но я не знаком с синтаксисом временных таблиц MySql.
Вот определение целевой таблицы, в которую я хочу объединить данные:
CREATE TABLE Student
(
[Name] NVARCHAR(200),
DateOfBirth DATETIME,
Notes NVARCHAR(1000)
);
Вот страница режима потока DbFit, которая объединит в нее данные:
!| 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. Команда Query в конце не нужна для MERGE, она была добавлена только для проверки правильности обновления целевой таблицы.
Обратите внимание, что команда Вставка должна использовать имя из трех частей для временной таблицы, по крайней мере, в SQL Server. Когда команда "Вставить" выполняется в отношении SQL Server, за кулисами она запрашивает 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 будет возвращать идентификатор объекта временной таблицы, только если имя таблицы задано как имя из трех частей. Это связано с тем, что SQL Server всегда создает временные таблицы в базе данных tempdb, а не в той базе данных, где будет использоваться временная таблица. Функция OBJECT_ID не найдет метаданные для временной таблицы, если ей не предложено искать ее в базе данных tempdb.