MS SQL Перенос атрибутов из одной таблицы в другую. Копирование данных из одной таблицы в другую
) Вводные: -Есть таблица "Table_1" t1 с атрибутами "ID", "Comment" -Есть таблица "Table_2" t2 с атрибутами "ID", "Name", "Explanation"
t1.ID = t2.ID t1.ID - Уникальное поле в таблице (Ключ) t2.ID - Не уникальное поле, ID могут повторятся.
Необходимо t2.Name и t2.Explanation записывать в t1.Comment следующим образом: "Name" : "Explanation";"Name" : "Explanation"
Получается необходимо обработать все строки из t2 записав в таком формате в t1 через точку с запятой, разделяя "Name" и "Explanation" вот так: " : "
Необходимо это делать каждый час, получается поле "Comment" необходимо не перезаписывать, а добавлять в него данные по формату выше. Так же после того, как из таблицы t2 атрибуты из строки были добавлены в t1. - эту строку необходимо в t2 удалить. Чтобы при следующей итерации (через час) - она опять не записалась в таблицу t1. БД MS SQL. Очень вас прошу, помогите пожалуйста с решением данной задачи. Если вводных не хватает - говорите - я их добавлю. Заранее спасибо вам большущие!!!) Обнял.
Ответы (1 шт):
Не хочу вас расстраивать, но для вашей задаче лучше подойдёт триггер или вьюха... При этом не раз в час будет обновляться, а будет сохраняться консистентность постоянно. Вод код:
-- Всё делаем во временной БД
USE tempdb
GO
-- Чистим БД, чтобы при повторных запусках не ругалось
IF OBJECT_ID('V_Table1_V1') IS NOT NULL DROP VIEW V_Table1_V1
IF OBJECT_ID('V_Table1_V2') IS NOT NULL DROP VIEW V_Table1_V2
IF OBJECT_ID('T_IUD_Table2') IS NOT NULL DROP TRIGGER T_IUD_Table2
IF OBJECT_ID('Table2') IS NOT NULL DROP TABLE Table2
IF OBJECT_ID('Table1') IS NOT NULL DROP TABLE Table1
GO
CREATE TABLE Table1 (
Id INT PRIMARY KEY,
Comment VARCHAR(1024)
)
CREATE TABLE Table2 (
Id INT REFERENCES Table1 (Id),
Name VARCHAR(1024),
Explanation VARCHAR(1024),
)
GO
--Собственно сам триггер:
CREATE TRIGGER T_IUD_Table2
ON Table2
AFTER INSERT, UPDATE, DELETE
AS
UPDATE T1
SET Comment = STUFF(
(SELECT(
SELECT CONCAT('; "',Name,'" : "',Explanation,'"')
FROM Table2 WHERE Table2.Id = T1.Id
ORDER BY Name, Explanation FOR XML PATH('')
)), 1, 2, '')
FROM Table1 T1
WHERE T1.Id
IN (SELECT Id FROM INSERTED UNION SELECT Id FROM DELETED)
GO
INSERT Table1 VALUES(1,NULL),(2,'')
-- Тестим INSERT
INSERT Table2 VALUES
(1,'Мама','Мыла'),(1,'Раму','Рама'),(1,'Шла','Саша'),
(2,'ASDF','ZXCV'),(2,'QWER','QAZ')
SELECT * FROM Table1
-- Тестим UPDATE
UPDATE Table2
SET Name += '_UPD', Explanation += '_UPD'
WHERE Name = 'ASDF'
SELECT * FROM Table1
-- Тестим DELETE
DELETE FROM Table2 WHERE Name = 'QWER'
SELECT * FROM Table1
GO
--Ну и вьюху можно сделать
CREATE VIEW V_Table1_V1 AS
SELECT T1.Id,
STUFF(
(SELECT(
SELECT CONCAT('; "',Name,'" : "',Explanation,'"')
FROM Table2 WHERE Table2.Id = T1.Id
ORDER BY Name, Explanation FOR XML PATH('')
)), 1, 2, '') AS CalcCommentV1
FROM Table1 T1
GO
SELECT * FROM V_Table1_V1
GO
--Так же если позволяет версия сервера, можно использовать STRING_AGG вместо FOR XML PATH для конкатенации строк
CREATE VIEW V_Table1_V2 AS
SELECT T1.Id,
--STRING_AGG можно использовать и в триггере
STRING_AGG(CONCAT('"',Name,'" : "',Explanation,'"'), '; ') AS CalcCommentV2
FROM Table1 T1
LEFT JOIN Table2 T2 ON T1.Id = T2.Id
GROUP BY T1.Id
GO
SELECT * FROM V_Table1_V2
Результат работы триггера после вставки в Т2
| Id | Comment |
|---|---|
| 1 | "Мама" : "Мыла"; "Раму" : "Рама"; "Шла" : "Саша" |
| 2 | "ASDF" : "ZXCV"; "QWER" : "QAZ" |
Результат триггера после обновления Т2
| Id | Comment |
|---|---|
| 1 | "Мама" : "Мыла"; "Раму" : "Рама"; "Шла" : "Саша" |
| 2 | "ASDF_UPD" : "ZXCV_UPD"; "QWER" : "QAZ" |
Результат после удаления из Т2
| Id | Comment |
|---|---|
| 1 | "Мама" : "Мыла"; "Раму" : "Рама"; "Шла" : "Саша" |
| 2 | "ASDF_UPD" : "ZXCV_UPD" |
Результат выгрузки данных из вьюхи с FOR XML PATH('')
| Id | CalcCommentV1 |
|---|---|
| 1 | "Мама" : "Мыла"; "Раму" : "Рама"; "Шла" : "Саша" |
| 2 | "ASDF_UPD" : "ZXCV_UPD" |
Результат выгрузки данных из вьюхи с STRING_AGG
| Id | CalcCommentV2 |
|---|---|
| 1 | "Мама" : "Мыла"; ; "Раму" : "Рама"; ; "Шла" : "Саша" |
| 2 | "ASDF_UPD" : "ZXCV_UPD" |
Если выбирать способ конкатенации строк - лучше конечно STRING_AGG - но вам надо проверить, поддерживает ли его ваша версия сервера