2012-04-18 11 views
35

la siguiente:T SQL fusionar ejemplo necesaria para ayudar a la comprensión

MERGE dbo.commissions_history AS target 
USING (SELECT @amount, @requestID) AS source (amount, request) 
ON (target.request = source.request) 
WHEN MATCHED THEN 
    UPDATE SET amount = source.amount 
WHEN NOT MATCHED THEN 
    INSERT (request, amount) 
    VALUES (source.request, source.amount); 

de https://stackoverflow.com/a/2967983/857994 es una forma bastante interesante que pueda hacer de inserción/actualización (y borrar con un poco de trabajo adicional). Me resulta difícil seguir aunque incluso después de googlear.

Puede alguien por favor:

  • explicar esto un poco en términos simples - la documentación de MSDN mutilado mi cerebro en este caso.
  • ¿cómo puedo modificarlo para que el usuario pueda escribir los valores para la cantidad & en lugar de tenerlos seleccionados desde otra ubicación de base de datos?

Básicamente, me gustaría utilizar esto para insertar/actualizar desde una aplicación C# con información tomada de los archivos XML que obtengo. Entonces, necesito entender cómo puedo formular una consulta manualmente para obtener mis datos analizados en la base de datos con este mecanismo.

+0

Di un tutorial a continuación, pero si fuera usted, publicaría una segunda pregunta aquí o n SO que tiene la estructura de su tabla de destino y un fragmento de muestra de su fuente xml y pregunte ... cómo escribiría una declaración MERGE para actualizar esta tabla desde este xml. También tenga en cuenta que una declaración MERGE al final tal vez ni siquiera sea la mejor herramienta para el trabajo. – RThomas

+0

Gracias, eso fue en realidad justo lo que necesitaba. Sin embargo, podría hacer una pregunta extra más tarde, es una buena sugerencia. –

Respuesta

67

Si no está familiarizado con join statements, entonces ahí es donde debe comenzar. Comprender cómo funcionan las uniones es clave para el resto. Una vez que esté familiarizado con las uniones, entender la fusión es más fácil al considerarla una combinación completa con instrucciones sobre qué hacer para las filas que coinciden o no coinciden.

Por lo tanto, utilizando el ejemplo de código proporcionado permite mira el commissions_history mesa

| Amount | Request | <other fields | 
-------------------------------------------- 
| 12.00 | 1234  | <other data | 
| 14.00 | 1235  | <other data | 
| 15.00 | 1236  | <other data | 

La declaración de combinación crea una unión completa entre una tabla, llamada el "objetivo" y una expresión que devuelve una tabla (o una conjunto de resultados que es lógicamente muy similar a una tabla como un CTE) llamada la "fuente".

En el ejemplo dado, está utilizando variables como la fuente que supondremos han sido establecidas por el usuario o pasadas como un parámetro.

DECLARE @Amount Decimal = 18.00; 
DECLARE @Request Int = 1234; 

MERGE dbo.commissions_history AS target  
USING (SELECT @amount, @requestID) AS source (amount, request)  
ON (target.request = source.request) 

Crea el siguiente conjunto de resultados cuando se considera una unión.

| Amount | Request | <other fields | Source.Amount | Source.Request | 
------------------------------------------------------------------------------ 
| 12.00 | 1234  | <other data | 18.00  |  1234  | 
| 14.00 | 1235  | <other data | null  |  null  | 
| 15.00 | 1236  | <other data | null  |  null  | 

Utilizando las instrucciones sobre qué hacer con el objetivo con la condición de que se haya encontrado una coincidencia.

WHEN MATCHED THEN   
UPDATE SET amount = source.amount  

La tabla objetivo resultante ahora tiene este aspecto. La fila con la solicitud 1234 se actualiza para ser 18.

| Amount | Request | <other fields | 
-------------------------------------------- 
| 18.00 | 1234  | <other data | 
| 14.00 | 1235  | <other data | 
| 15.00 | 1236  | <other data | 

Dado que se encontró un partido, no sucedió nada más. Pero digamos que los valores de la fuente fueron así.

DECLARE @Amount Decimal = 18.00; 
DECLARE @Request Int = 1239; 

El resultado se unen se vería así:

| Amount | Request | <other fields | Source.Amount | Source.Request | 
------------------------------------------------------------------------------ 
| 12.00 | 1234  | <other data | null  |  null  | 
| 14.00 | 1235  | <other data | null  |  null  | 
| 15.00 | 1236  | <other data | null  |  null  | 
| null | null  | null   | 18.00  |  1239  | 

Desde ese registro no se encontró en el objetivo de la instrucción se ejecuta la otra cláusula.

WHEN NOT MATCHED THEN         
INSERT (request, amount)         
VALUES (source.request, source.amount); 

resultando en una tabla de destino que ahora se ve así:

| Amount | Request | <other fields | 
-------------------------------------------- 
| 12.00 | 1234  | <other data | 
| 14.00 | 1235  | <other data | 
| 15.00 | 1236  | <other data | 
| 18.00 | 1239  | <other data | 

Las declaraciones de combinación verdadero potencial es cuando el origen y el destino son las dos grandes mesas. Como puede hacer una gran cantidad de actualizaciones y/o insertos para cada fila con una sola declaración simple.

Una nota final. Es importante tener en cuenta que not matched se predetermina a la cláusula completa not matched by target, sin embargo, puede especificar not matched by source en lugar de, o además de, la cláusula predeterminada. La instrucción de combinación admite ambos tipos de discrepancias (registros en el origen no en el destino o registros en el destino que no están en la fuente según lo definido por la cláusula on). You can find full documentation, restrictions, and complete syntax on MSDN.

+4

¡Gran respuesta, gracias! –

+0

'FULL JOIN' puede hacer cosas increíbles! – ErikE

+0

Gran respuesta, muy completa. Me gusta especificar siempre 'POR OBJETIVO' o 'POR ORIGEN' con la cláusula CUANDO NO COINCIDE, porque es más claro cuando se vuelve a leer en la pista. No tiene que memorizar cuál es el valor predeterminado, y está más cerca del inglés. – Davos

0

En el ejemplo dado respuesta que has hecho

DECLARE @Request Int 

, pero llamándolo en el SQL de la siguiente manera:

SELECT @amount, @requestID 

Otra sería nombrar y llamar a las variables de forma idéntica:

@amount vs. Amount -> @Amount & Amount