#sql #sql-server #sql-server-2008 #tsql #sql-update
#sql #sql-server #sql-server-2008 #tsql #sql-обновление
Вопрос:
Я все еще изучаю SQL. У меня вопрос об обновлении таблицы. Как я могу обновить свою таблицу на основе другой таблицы? Пожалуйста, посмотрите пример ниже:
create table batch_info (
batch_key int identity(1, 1) not null primary key,
batch_num int not null,
batch_name varchar(50) null,
batch_start datetime null,
batch_end datetime null,
table_name varchar(50) null,
insert_rows int null
)
go
insert into batch_info (batch_num, batch_name, batch_start)
values ('32', 'Batch_to_insert_rows', '20110414')
go
select * from batch_info
create table ref_table (
bat_num int not null,
bat_end_date datetime null,
bat_table_name varchar(50) null,
bat_ins_rows int null,
)
go
insert into ref_table
values ('32','20110414 02:12:00.000','Table1','10'),
('32','20110414 02:12:00.000','Table2','33'),
('32','20110414 02:12:00.000','Table3','12')
select * from ref_table
--How can I update batch_info table to get this info?
select
bi.batch_key,
bi.batch_num,
bi.batch_name,
bi.batch_start,
rt.bat_end_date,
rt.bat_table_name,
rt.bat_ins_rows
from batch_info as bi
inner join ref_table as rt on bi.batch_num = rt.bat_num
Редактировать: пакетный ключ является суррогатным, поэтому он должен быть инкрементным, а не (1, 1, 1), как в моем запросе join.
Ответ №1:
Предполагая, что комбинации batch_num и bat_end_date уникальны, это должно сработать:
update batch_info
set batch_end = rt.bat_end_date,
table_name = rt.bat_table_name,
insert_rows = rt.bat_ins_rows
from batch_info bi
inner join ref_table rt on rt.bat_num = bi.batch_num
inner join
(
select bat_num,
MIN(bat_end_date) as min_bat_end_date
from ref_table
) oldest on oldest.bat_num = rt.bat_num
and oldest.min_bat_end_date = rt.bat_end_date
where bi.batch_end is null
insert into batch_info
(batch_num, batch_name, batch_start, batch_end, table_name, insert_rows)
select bi.batch_num,
bi.batch_name,
bi.batch_start,
rt.bat_end_date,
rt.bat_table_name,
rt.bat_ins_rows
from batch_info bi
inner join ref_table rt on rt.bat_num = bi.batch_num
where not exists
(
select *
from batch_info e
where e.batch_num = bi.batch_num
and e.batch_end = rt.bat_end_date
)
Если уникальность устанавливается другой комбинацией значений, то они могут быть добавлены к oldest
в первом запросе и e
во втором.
Я согласен с @Jim, что это должно быть разделено на две таблицы. Сложность выполнения этой операции является предвестником трудностей, которые создаст этот дизайн. Вы пытаетесь поместить две разные вещи (пакеты и пакетные запуски) в одну таблицу, а это никогда не бывает хорошей идеей.
Комментарии:
1. @Jeffrey 1 тебе за ответ на вопрос без курсора (ick), как я предлагал. Но, как мы оба согласны, это должно быть две таблицы.
2. Спасибо. Первая инструкция выдает ошибку: Сообщение 8120, уровень 16, состояние 1, строка 9, столбец ‘ref_table.bat_num’ недопустим в списке выбора, поскольку он не содержится ни в агрегатной функции, ни в предложении GROUP BY.
3. И оператор insert, похоже, ничего не вставляет в этом примере.
4. @jrara — В этом примере это ничего не делает, потому что, очевидно, bat_num end_date не определяет уникальные записи. Вы никогда не указывали в вопросе, что определяет уникальные записи. Я сказал в своем ответе, что эти вещи необходимо добавить в запрос, чтобы заставить его работать. Вероятно, я мог бы сделать другое предположение на основе данных примера, но только вы знаете правильный ответ на этот вопрос, поэтому мои предположения были бы бессмысленными.
5. Что касается другой ошибки, я пропустил GROUP BY. Должно быть, я спешил! Просто поместите «group by rt.bat_num» после «from ref_table» в производном табличном выражении (подзапросе) инструкции update.
Ответ №2:
insert into batch_info
SELECT batch_num, batch_name, batch_start,
bat_end, bat_table_name, bat_ins_rows
FROM batch_info inner join ref_table
on batch_info.batch_num = ref_table.bat_num
delete from batch_info
where batch_end is null
РЕДАКТИРОВАТЬ: INSERT
генерирует все совпадающие строки и вставляет их заново. К ним будут добавлены новые значения идентификаторов. Существующая строка (с другими полями null) используется для INSERT
инструкции и позже удаляется с помощью 2-й инструкции.
Ответ №3:
Я собирался указать вам на инструкцию Merge, но я не думаю, что это можно сделать и с ее помощью. Я думаю, вы застряли, используя курсор.
Учитывая сказанное и не зная ваших существующих требований, действительно должно быть две таблицы. Перенос всех данных в одну таблицу приводит к денормализации структуры таблицы.
Комментарии:
1. Я не работаю с операционной базой данных. Эта таблица batch_info является таблицей журнала в хранилище данных, поэтому я думаю, что это нормально для денормализации.
Ответ №4:
Сделайте автоматическое увеличение поля batch_info.batch_key.
create table batch_info (
batch_key int identity(1, 1) not null primary key, -- <<- make autoincrement.
...