#sql-server
#sql-сервер
Вопрос:
Представьте приведенную ниже таблицу в виде
col1 col2 col3 rank
1 2 n 5
1 2 n 6
2 3 a 3
При вставке нижеприведенных записей из таблицы B в таблицу A значение столбца rank должно постоянно увеличиваться, если вставляются одни и те же записи.
Записи в таблице B, которые собираются вставить в A, являются
col1 col2 col3
1 2 n
2 3 a
Желаемый результат в таблице A после вставки вышеуказанных записей является,
col1 col2 col3 rank
1 2 n 5
1 2 n 6
1 2 n 7
2 3 a 3
2 3 a 4
Пожалуйста, помогите мне, как этого достичь.Спасибо.
Ответ №1:
Если запись в B уникальна, то вы могли бы использовать запрос, подобный этому
—————РЕДАКТИРОВАТЬ——————-
Если в B может быть несколько записей, вы можете использовать функцию row_number() с разделом
insert into TestA
select b.*,
(select max([rank]) from TestA where col1 = b.col1 and col2 = b.col2 and col3 = b.col3)
row_number()over (partition by col1, col2, col3 order by col1, col2,col3 asc) as N
from TestB b
—————ЗАВЕРШЕНИЕ РЕДАКТИРОВАНИЯ——————-
Примечание: я переименовал таблицу: TestA и TestB
insert into TestA
select b.*, (select max([rank]) 1 from TestAwhere col1 = b.col1 and col2 = b.col2 and col3 = b.col3)
from TestB b
или с ОБЪЕДИНЕНИЕМ, подобным этому
insert into testa
select b.*, mr 1 from TestB b
join
(select col1, col2, col3, max([rank]) as mr
from TestA A
group by col1, col2, col3) as M
on
b.col1 = M.col1 and b.col2 = M.col2 and b.col3 =M.col3
Комментарии:
1. Привет, спасибо за твою помощь. Первый код не может работать, поскольку в таблице b отсутствует столбец ran. Я попробовал второй вариант. Проблема с этим заключается в том, что если таблица B имеет повторяющуюся строку, такую же, как и первая строка, то она присваивает тот же ранг и второй записи. Его необходимо увеличить.
2. Я изменил запрос для работы с множественной записью в таблице B
Ответ №2:
Я бы использовал для этого INSTEAD OF
INSERT
триггер. Вот так:
CREATE TRIGGER rankInsertTrigger
ON A
INSTEAD OF INSERT
AS
BEGIN
INSERT INTO A(col1, col2, col3, rank)
SELECT i.col1, i.col2, i.col3,
MAX(SELECT a.rank
FROM A AS a
WHERE a.col1 = i.col1
AND a.col2 = i.col2
AND a.col3 = i.col3) 1
FROM inserted i
END
Теперь каждый раз, когда вы вставляете значения в таблицу A
, запускается этот триггер и заменяет исходную вставку вставкой, которая задает rank
нужное значение.
Например, когда вы это делаете INSERT INTO A(col1, col2, col3) VALUES (1, 2, n)
, на самом деле выполняется оператор insert в триггере (который принимает исходные значения для col1
, col2
, col3
но перезаписывает rank
).
Комментарии:
1. не могли бы вы, пожалуйста, объяснить, что это за предложение select в триггере собирается извлечь? Мне будет полезно изменить. Спасибо за вашу помощь.
2. Не похоже, что это будет обрабатывать параллельные вставки.
3. @Robin Внутри триггера ВСТАВКИ есть таблица с именем
inserted
, которая представляет вставленные записи. Оператор select выбирает данные изinserted
таблицы и определяет следующиеrank
и использует эти данные для вставки в таблицуA
.4. @Martin Правильно, при одновременных вставках вы, скорее всего, получите повторяющиеся
rank
значения. Единственное исправление заключается в том, чтобы убедиться, что одновременные вставки не выполняются, или в том, что каждая отдельная вставка выполняется внутри сериализуемой транзакции (поскольку вам нужна блокировка чтения для строк, выбранных вMAX
запросе). Не уверен, что триггер — лучшее место для включения такой логики.