2011-10-27 35 views
7

Tengo un proyecto que puede usar SQL Server o MS Access como almacén de datos. En una instrucción SELECT, debo realizar una operación de COALESCE en una sola columna y un único valor, como este:Función COALESCE, IFNULL o NZ() que se puede usar en SQL Server y MS Access

SELECT COALESCE([Amount], 0) FROM PaymentsDue; 

me gustaría escribir una única sentencia de SQL que se ejecutará correctamente en SQL Server y MS Access . La versión de SQL Server que es de interés inmediato es 2008, aunque sería preferible una solución aplicable en todas las versiones.

Hoy más temprano, alguien pudo to show me an SQL trick que me permitió usar una sola instrucción SELECT para lanzar CAST un DATETIME hasta la FECHA. Me preguntaba si alguien tiene un truco similar para realizar una operación COALESCE (por ejemplo, IFNULL o NZ) de una manera que se puede aplicar a ambos SQL Server y MS Access?

Respuesta

6

Esto funciona, pero es torpe:

SELECT Amount 
FROM PaymentsDue 
WHERE Amount IS NOT NULL 
UNION ALL 
SELECT 0 AS Amount 
FROM PaymentsDue 
WHERE Amount IS NULL 

Obviamente, si usted tiene más de una columna, esto llega a ser rápidamente inmanejable.

+1

La parte 'Amount = 0' no funcionará en Access. Debería ser '0 AS cantidad '. –

+0

Fui con una variante de esta solución. Mi necesidad inmediata es realizar un 'INSERT'. . . SELECCIONAR. . .' y simplemente repito la declaración dos veces, una para NULL y otra para las otras filas. –

5

No creo que haya ninguna sintaxis que funcione igual en ambas plataformas.

Nota Nz() solo está disponible cuando se utiliza la interfaz de usuario de Access.

Aquí hay un par de sugerencias que puede ser transformado a COALESCE con bastante facilidad, aunque la repetición de la columna es un dolor:

Muestra 1:

SELECT IIF([Amount] IS NULL, 0, [Amount]) FROM PaymentsDue; 

Muestra 2:

SELECT SWITCH([Amount] IS NULL, 0, TRUE, [Amount]) FROM PaymentsDue; 
0

Y supongo que no desea escribir un analizador que gestionará las traducciones entre Jet SQL y T-SQL ...

Una solución que desarrollamos (sí, tuvimos un problema similar para resolver) es definir algún 'pseudo-metalenguaje' que usamos en nuestra sintaxis meta-SQL, y tenemos un tipo de traductor de este metalenguaje en Jet SQL o T-SQL.

Ejemplo:

myQuery = "SELECT @[email protected]([Amount], 0) FROM PaymentsDue;" 

myQuery = convertFromMeta(myQuery,"T-SQL") 
will give 
    "SELECT COALESCE([Amount], 0) FROM PaymentsDue;" 

myQuery = convertFromMeta(myQuery,"JET-SQL") 
will give 
    "SELECT NZ([Amount], 0) FROM PaymentsDue;" 

La misma estrategia podría usarse para comodines y delimitadores:

myQuery = "SELECT [Amount] FROM PaymentsDue WHERE id_client LIKE @Ca[email protected]@[email protected]@[email protected]" 

myQuery = convertFromMeta(myQuery,"T-SQL") 
will give 
    "SELECT [Amount] FROM PaymentsDue WHERE id_client LIKE 'ABC%'" 

myQuery = convertFromMeta(myQuery,"JET-SQL") 
will give 
    "SELECT [Amount] FROM PaymentsDue WHERE id_client LIKE "ABC%"" 

I konw que no es tan agradable, pero es bastante eficiente y limpia. Los puntos principales son:

  • No estamos traduciendo entre Jet y T-SQL, sino desde una 'meta-sintaxis'. Hace las cosas mucho más fáciles
  • Se debe tener mucho cuidado cuando las funciones no tienen el mismo número de parámetros o cuando los parámetros no se pasan en el mismo orden. Todavía se puede hacer ...
  • Nuestra meta-sintaxis se basa en el hecho de que las cadenas correspondientes (como '@ MyWildCard @' o '@ CarSep @' son específicas de nuestra sintaxis y no pueden utilizarse como valores de datos (De lo contrario, tendríamos que gestionar algunos riesgos de 'metainyección' ...)
+0

¡Tiene razón en que no quiero escribir mi propio analizador! Sin embargo, he pensado en escribir mi propio * generador *, en la línea de lo que sugirió (pero operando en objetos, en lugar de cadenas). En otra parte de mi aplicación, publico DDL para agregar nuevas características a la base de datos que debe ser específica para el motor; que se beneficiaría (y sería relativamente fácil) de usar un generador. Si lo hiciera, podría encapsular mi lógica SELECT en diferentes vistas para cada motor. Pero eso es en el futuro, en este momento estoy buscando un "truco" rápido para manejar este problema en particular. –

3

Cree una función pública personalizada en un módulo.

Public Function COALESCE(InputValue, ValueIfNull) 
    COALESCE = nz(InputValue, ValueIfNull) 
End Function 

Agregar en el manejo de errores, etc., hacer mejoras.

Ahora, usted podría usar la función COALESCE en MS Access y SQL.