2011-05-12 10 views
8

Tengo una tabla que contiene una relación estudiante-grado:Operación de estilo "Combinar" con valores literales?

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

Estoy tratando de escribir un procedimiento almacenado que toma Student, Grade y StartDate, y me gustaría que

  1. cheque para asegurarse de que estos valores no sean duplicados
  2. inserte el registro si no es un duplicado
  3. si hay un registro de estudiante existente, y tiene un EndDate = NULL, luego actualice ese registro con el StartDate del nuevo registro.

Por ejemplo, si llamo el procedimiento y el pase en 1, 2, 09/01/2010, me gustaría terminar 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 

Esto suena como que podría utilizar MERGE, excepto que estoy pasando valores literales, y necesito realizar más de una acción. También tengo un terrible dolor de cabeza esta mañana y parece que no puedo pensar con claridad, así que me estoy concentrando en esta solución MERGE. Si hay una manera más obvia de hacerlo, no tengas miedo de señalarlo.

Respuesta

18

Puede usar un MERGE incluso si está pasando valores literales. Aquí hay un ejemplo para su 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, excelente. ¡No sabía que podrías usar valores literales con 'MERGE'! Intenté algo similar, pero no pensé usar los alias, lo que parece obvio ahora. Esto no es exactamente lo que necesito, ya que necesito insertarlo y actualizarlo cuando coincida, pero estoy seguro de que puedo encontrar una solución allí. El quid de la cuestión fue cómo usar 'MERGE' con mis valores. ¡Muchas gracias! –

+3

También podría usar algo como esto: USO (VALORES (@Student, @Grade, @StartDate)) AS [fila] (Estudiante, Grado, Fecha de inicio) – Davos

+0

@Davos Me gustaría ver su comentario en un responder. – yzorg

10

Prefiero lo siguiente, es más limpio y fácil de leer y modificar.

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

Esto no responde la pregunta que le hizo al OP acerca de escribir un procedimiento almacenado, que toma los parámetros que se deben insertar. Esto también ignora la parte 3 de la pregunta sobre las actualizaciones cuando la fecha de finalización es nula. Este ejemplo solo insertará nuevos registros y, como tal, no es en realidad mejor que una instrucción de inserción. – Davos

Cuestiones relacionadas