开发者

SQL Server beginner: How to update table data from another table?

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.
...
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜