I'm still learning SQL. I have question about updating table. How can I update my table based on other table? Please see the example below:
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
Edit: batch开发者_StackOverflow中文版 key is surrogate so it should be incremental, not (1, 1, 1) as in my join query.
Assuming that combinations of batch_num and bat_end_date are unique, then this should do the trick:
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
)
If another combination of values establishes uniqueness, then those can be added to oldest
in the first query, and e
in the second.
I agree with @Jim that this should be split into two tables. The difficulty of performing this operation is a harbinger of the difficulties that this design is going to create. You are trying to put two different things (batches and batch runs) into a single table, and that is never a good idea.
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
EDIT: The INSERT
is generating all matching rows & inserting it afresh. New Identity values will be added to those. The existing row (with other fields null) is used for INSERT
statement & later deleted using the 2nd statement.
I was going to point you to the Merge Statement, but I don't think this can be done with that either. I think you are going to be stuck using a Cursor.
With that said and not knowing your existing requirements, it really should be two tables. Pushing all into one table is denormalizing the table design.
Make the batch_info.batch_key field autoincrement.
create table batch_info (
batch_key int identity(1, 1) not null primary key, -- <<- make autoincrement.
...
精彩评论