2011-04-14 5 views
1

Je suis encore en train d'apprendre le SQL. J'ai une question sur la mise à jour de la table. Comment puis-je mettre à jour ma table en fonction d'une autre table? S'il vous plaît voir l'exemple ci-dessous:SQL Server débutant: comment mettre à jour les données de table d'une autre table?

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: clé de lot est porteuse de sorte qu'il devrait être progressive, et non (1, 1, 1) comme dans ma requête de jointure.

Répondre

3

En supposant que les combinaisons de batch_num et bat_end_date sont uniques, cela devrait faire l'affaire:

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 
     ) 

Si une autre combinaison de valeurs établit l'unicité, alors celles-ci peuvent être ajoutés à oldest dans la première requête, et e dans la seconde.

Je suis d'accord avec @Jim que cela devrait être divisé en deux tables. La difficulté d'effectuer cette opération est un signe avant-coureur des difficultés que cette conception va créer. Vous essayez de mettre deux choses différentes (lots et lots) dans une seule table, et ce n'est jamais une bonne idée.

+0

@Jeffrey +1 pour vous d'avoir répondu à la question sans un curseur (ick) comme je l'ai suggéré. Mais comme nous sommes tous les deux d'accord, cela devrait être deux tables. – Jim

+0

Merci. La première instruction génère une erreur: Msg 8120, niveau 16, état 1, ligne 9 La colonne 'ref_table.bat_num' n'est pas valide dans la liste de sélection car elle n'est contenue ni dans une fonction d'agrégat ni dans la clause GROUP BY. – jrara

+0

Et l'instruction d'insertion ne semble rien insérer dans cet exemple. – jrara

0
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: Le INSERT est la génération de toutes les lignes correspondant à l'insertion de ce nouveau &. De nouvelles valeurs d'identité seront ajoutées à celles-ci. La ligne existante (avec les autres champs NULL) est utilisée pour INSERT instruction & plus tard supprimé en utilisant la 2ème instruction.

0

J'allais vous pointer vers le Merge Statement, mais je ne pense pas que cela puisse être fait non plus. Je pense que vous allez être coincé en utilisant un Cursor. Avec cela dit et ne sachant pas vos exigences existantes, il devrait vraiment être deux tables. Pousser tous dans une table dénormaliser la conception de la table.

+0

Je ne travaille pas avec la base de données opérationnelle. Cette table batch_info est une table de journal dans l'entrepôt de données, donc je pense qu'il est bon de dénormaliser cela. – jrara

0

Rendre le champ batch_info.batch_key auto-incrémenté.

create table batch_info (
batch_key int identity(1, 1) not null primary key, -- <<- make autoincrement. 
... 
Questions connexes