2011-05-12 2 views
8

Ho una tabella che contiene un rapporto studente-grade:Operazione di tipo "Unisci" con valori letterali?

Student Grade StartDate EndDate 
    1  1 09/01/2009 NULL 
    2  2 09/01/2010 NULL 
    2  1 09/01/2009 06/15/2010 

Sto cercando di scrivere una stored procedure che prende Student, Grade e StartDate, e vorrei che a

  1. controllo per assicurarsi che questi valori non sono duplicati
  2. inserire il record se non è un duplicato
  3. se v'è un record studente esistente, e ha un EndDate = NULL, quindi aggiorna quel record con lo StartDate del nuovo record.

Per esempio, se io chiamo la procedura e passare 1, 2, 09/01/2010, mi piacerebbe finire con:

Student Grade StartDate EndDate 
    1  2 09/01/2010 NULL 
    1  1 09/01/2009 09/01/2010 
    2  2 09/01/2010 NULL 
    2  1 09/01/2009 06/15/2010 

Questo suona come ho potuto utilizzare MERGE, se non che io sto passando valori letterali, e ho bisogno di eseguire più di un'azione. Ho anche mal di testa stamattina e non riesco a pensare chiaramente, quindi mi sto fissando su questa soluzione MERGE. Se c'è un modo più ovvio per farlo, non aver paura di farlo notare.

risposta

18

È possibile utilizzare un MERGE anche se si passano valori letterali. Ecco un esempio per il tuo problema:

CREATE PROCEDURE InsertStudentGrade(@Student INT, @Grade INT, @StartDate DATE) 
AS 
BEGIN; 

    MERGE StudentGrade AS tbl 
    USING (SELECT @Student AS Student, @Grade AS Grade, @StartDate AS StartDate) AS row 
    ON tbl.Student = Row.Student AND tbl.Grade = row.Grade 
    WHEN NOT MATCHED THEN 
     INSERT(Student, Grade, StartDate) 
     VALUES(row.Student, row.Grade, row.StartDate) 
    WHEN MATCHED AND tbl.EndDate IS NULL AND tbl.StartDate != row.StartDate THEN 
     UPDATE SET 
     tbl.StartDate = row.StartDate; 

END; 
+0

Oh, eccellente. Non sapevo che potresti usare valori letterali con 'MERGE'! Ho provato qualcosa di simile, ma non ho pensato di usare gli alias, che ora sembrano ovvi. Questo non è esattamente ciò di cui ho bisogno, dal momento che ho bisogno di inserire e aggiornare quando abbinato, ma sono sicuro che posso trovare una soluzione lì. Il vero nodo di ciò era come usare "MERGE" con i miei valori. Grazie mille! –

+3

Puoi anche usare qualcosa del tipo: UTILIZZO (VALORI (@Student, @Grade, @StartDate)) AS [riga] (Studente, Grado, Data di inizio) – Davos

+0

@Davos Mi piacerebbe molto vedere il tuo commento in un risposta. – yzorg

10

Preferisco quanto segue, è più pulito e più facile da leggere e modificare.

MERGE Definition.tdSection AS Target 
USING 
    (SELECT * 
    FROM (VALUES 
      (1, 1, 'Administrator', 1, GETDATE(), NULL, Current_User, GETDATE()) 
      ,(2, 1, 'Admissions', 1, GETDATE(), NULL, Current_User, GETDATE()) 
      ,(3, 1, 'BOM', 1, GETDATE(), NULL, Current_User, GETDATE()) 
      ,(4, 1, 'CRC', 1, GETDATE(), NULL, Current_User, GETDATE()) 
      ,(5, 1, 'ICM', 1, GETDATE(), NULL, Current_User, GETDATE()) 
      ,(6, 1, 'System', 1, GETDATE(), NULL,Current_User, GETDATE()) 
      ,(7, 1, 'Therapy', 1, GETDATE(), NULL, Current_User, GETDATE()) 
      ) 
      AS s (SectionId 
        ,BusinessProcessId 
        ,Description, Sequence 
        ,EffectiveStartDate 
        ,EffectiveEndDate 
        ,ModifiedBy 
        ,ModifiedDateTime) 
    ) AS Source 
ON Target.SectionId = Source.SectionId 
WHEN NOT MATCHED THEN 
    INSERT (SectionId 
      ,BusinessProcessId 
      ,Description 
      ,Sequence 
      ,EffectiveStartDate 
      ,EffectiveEndDate 
      ,ModifiedBy 
      ,ModifiedDateTime 
      ) 
    VALUES (Source.SectionId 
      ,Source.BusinessProcessId 
      ,Source.Description 
      ,Source.Sequence 
      ,Source.EffectiveStartDate 
      ,Source.EffectiveEndDate 
      ,Source.ModifiedBy 
      ,Source.ModifiedDateTime 
      ); 
+0

Questo non risponde all'interrogazione dell'OP sulla scrittura di una stored procedure, che richiede l'inserimento di parametri. Questo ignora anche la parte 3 della domanda riguardante gli aggiornamenti quando la data di fine è nullo. Questo esempio inserirà solo nuovi record e, in quanto tale, non è migliore di un'istruzione di inserimento. – Davos