Menú de navegaciónMenú
Categorías

La mejor forma de Aprender Programación online y en español www.campusmvp.es

Cómo consultar una base de datos SQL Server desde NodeJS

Últimamente me ha tocado trabajar con node.js consumiendo datos de la base de datos documental MongoDB y también desde SQL Server. Buscando información he podido probar varios conectores y paquetes que nos facilitan el trabajo a la hora de la conexión y de la creación de consultas.

Para conectarme con SQL Server he utilizado Tedious. Se trata de un paquete que puedes descargar vía npm y que implementa el protocolo TDM. Tedious funciona tanto en servidores Linux como en Windows. El nombre de este paquete hace referencia a que la pronunciación en inglés de TDS es parecida a la de tedious (tedioso en inglés) 😁

Para la creación de consultas utilizo otro paquete llamado json-sql, que me permite crear consultas SQL a partir de objetos JSON (como por ejemplo en MongoDB). Ojo: este paquete se trata de un traductor, en ningún caso es un conector.

Su sintaxis es muy simple. Por ejemplo para realizar una consulta de selección hacemos lo siguiente:

1.- Importamos el paquete:

let jsonSql = require('json-sql');

Nos fijamos que ya estamos creando una instancia de json-sql.

2.- Creamos una función para obtener el objeto que creará la consulta:

createSelectQuery(filter, sort) {
let sql = jsonSql.build({
dialect: 'mssql',
type: 'select',
table: 'Direcciones',
fields: ['Id', 'Cif', 'NombreRazonSocial',
'Direccion', 'CodigoPostal', 'Poblacion',
'Provincia', 'ComunidadAutonoma',
'Pais', 'FechaModificacion'],
condition: filter,
sort: sort
});
return sql;
}

Vamos a desglosar un poco esta función...

Primeramente destacamos el objeto jsonSql, que es el principal de la biblioteca. Posee un método buid al cual le podemos especificar, entre otros,  los siguientes parámetros:

  • El dialecto que vamos a utilizar ('base', 'mssql', 'mysql', 'postgresql' o 'sqlite').
  • El tipo de consulta (en este caso SELECT)
  • La tabla o tablas con las que vamos a trabajar (se pueden hacer joins, agrupaciones...)
  • Los campos que queremos proyectar
  • Los filtros (WHERE)
  • La ordenación
  • ...

En la función anterior, las variables filter y sort asignados a las propiedades condition y sort respectivamente, son documentos JSON. Por ejemplo:

let sql = jsonSql.build({
    table: 'table', 
    condition: {Nombre: 'Miguel'}
    sort: {a: 1, b: -1}
});

En este ejemplo el objeto sql tiene una propiedad query que contiene la consulta SQL resultante, así:

sql.query = 'select * from "table" WHERE Nombre = "Miguel" order by "a" asc, "b" desc';

3.- Una vez tenemos la consulta, vamos a atacar a la base de datos. Vamos a usar promesas para realizar llamadas asíncronas. Existe un paquete llamado bluebird que nos facilita mucho su creación. Veamos cómo usarlo:

3.1.- Importamos el paquete:

const promise = require('bluebird');

3.2.- He creado una función executeQuery para gestionar la conexión con la base de datos y la ejecución de consultas en la que importo las clases SqlConnection y Request:

const SqlConnection = require("tedious").Connection;
const Request = require("tedious").Request;

executeQuery(query) {
        let resultEntity = {
            result: {},
            error: null
        };

        return new promise((resolve, reject) => {
            var connection = new SqlConnection(this.config);

            connection.on('connect', function (err) {
                let request = new Request(query, function (err, rowCount, rows) {
                    if (err) {
                        resultEntity.error = err;
                        reject(resultEntity);
                    } else {
                        resultEntity.result = rows;
                        resolve(resultEntity);
                    }

                    connection.close();
                });
                connection.execSql(request);
            }
           );
        });
    }

En esta función primero creo una entidad resultEntity que será la que se devuelva con el resultado obtenido de la consulta e información en caso de que se produzca algún error. Después está la promise, en la que se establece la conexión creando un objeto de tipo SqlConnection al que se le pasa la configuración en el constructor. Esta configuración tiene el siguiente aspecto:

"config": {
  "server": "servidor",
  "userName": "Usuario",
  "password": "clave",
  "options": {
     "instanceName": "Nombre de la instancia",
     "database": "nombre base de datos",
     "rowCollectionOnRequestCompletion": true,
     "rowCollectionOnDone": true
  }
}

Puedes encontrar más información al respecto de esta configuración en la documentación de Tedious.

A continuación nos subscribimos al evento connect de la conexión y creamos un objeto de tipo request, al  cual le pasamos como primer parámetro la consulta a realizar. Este objeto request va a ser el encargado de gestionar la consulta y devolver los resultados (rows) o si se produce algún error (err).

Se procede a cerrar la conexión:

connection.close();

Y después de la subscripción al evento connect procedemos a ejecutar la consulta mediante el método execSql de la conexión, el cual recibe como parámetro el objeto request que acabamos de crear.

En definitiva lo que realiza esta función es:

  • Crea el objeto a devolver por la función
  • Crea el objeto de conexión
  • Se subscribe al evento connect de la conexión
  • Crea el objeto request para hacer la petición a la base de datos y recibir los resultados
  • Ejecuta la consulta

El objeto recibido devuelve los valores de la consulta así como los metadatos de cada campo solicitado.

¡Espero que os sea de utilidad!

Joaquín Sosa Joaquín Sosa es MCP certificado y trabaja como Consultor de Desarrollo freelance especializado en tecnologías Microsoft en Pasiona. Cuenta con más de 10 años de experiencia en desarrollo y ha trabajado en diferentes plataformas: web, escritorio, y entornos móviles. Interesado en buenas prácticas de desarrollo, arquitecturas y metodologías ágiles. Puedes seguirlo en twitter en @joaquin_sosa Ver todos los posts de Joaquín Sosa

Boletín campusMVP.es

Solo cosas útiles. Una vez al mes.

🚀 Únete a miles de desarrolladores

DATE DE ALTA

x No me interesa | x Ya soy suscriptor

La mejor formación online para desarrolladores como tú

Comentarios (11) -

Gisela Torres
Gisela Torres

Muy bueno Joaquín!

Yo uso el módulo mssql para conectarme a SQL Server desde Node.js ^^ www.returngis.net/.../

¡Saludos!

Responder

Esta realmente preparado node.js para realizar las labores que hasta ahora venia haciendo con  asp ?
-Enviar correo
-Trabajar con archivos (scripting.filesystemobject)
-Generar CSV, TXT
-Compresión de archivos
-Obtener IP
...
O estamos en los albores aun con este lenguaje.
La idea es trabajar con un mismo lenguaje (javascript) desde el front y el back.
Gracias.

Responder

José Manuel Alarcón
José Manuel Alarcón

Hola Martín:

No puedes pensar en Node.js como un sustituto de ASP.NET o PHP, tal cual. Aunque puedes usarlo como tal, la filosofía es diferente. Está más pensado para crear aplicaciones web modernas que se basan en servicios y se combinan en el lado cliente con frameworks como Angular o VUE para consumirlos. También es ideal para crear aplicaciones en tiempo real, basadas en sockets.

Dicho esto: es un framework maduro y capaz, con el que puedes hacer todas esas cosas que mencionas y muchas más, para el que encontrarás paquetes que lo extienden para hacer cualquier cosa. De hecho hay más paquetes para Nodejs en npm que en ningún otro lado.

Una nota respecto a lo de enviar emails: hacer esto desde tu propia aplicación web y tu propio servidor es algo que jamás debieras hacer salvo que controles mucho sobre el tema. El envío de correo en la actualidad es un tema muy complejo en el que, o lo haces perfecto en cuanto a infraestructura, DNSs, cabeceras, firma electrónica del correo, autenticación, etc... o lo más probable es que todo tu correo acabe en spam. Yo no te recomiendo enviar correo desde tu aplicación. Mucho mejor usar servicios como SendGrid o Mailgun, que te garantizan que eso está bien hecho y se entregan. Tienen capas gratuitas muy generosas por lo que el coste no es una disculpa.

Saludos.

Responder

Gerard Janssen
Gerard Janssen

"Yo no te recomiendo enviar correo desde tu aplicación. Mucho mejor usar servicios como SendGrid o Mailgun, que te garantizan que eso está bien hecho y se entregan. Tienen capas gratuitas muy generosas por lo que el coste no es una disculpa."

Mmmm, que suerte haber caído en esta entrada buscando cosas de node.js. Cuando en los proyectos web del trabajo (en PHP, pero bueno), la parte de envío de emails siempre me ha dado muchos problemas. Que si cabeceras, que si bloqueo en salida, que si SSL,etc. Y todo para luego acabar siempre en la carpeta de spam de gmail.

Voy a mirarme esto de externalizar el envío para el proecto propio que estoy haciendo.

Gracias y saludos.

Responder

Una consulta mi sitio web principal es creado en la base de dato mongo db y tengo otro sitio que quiero enlazar a la principal, tiene la base de dato en SQL SERVER. Pregunta; es posible enlazar estos dos, publicar a través de la misma IP pública?

Responder

José Manuel Alarcón
José Manuel Alarcón

Hola:

No sé si te refieres a tener los dos servidores (Mongo y SQL Server) en la misma IP, en cuyo caso la respuesta es que sí (usan puertos diferentes), o que dos sitios webs diferentes se sirvan a través del puerto 80 en un mismo servidor, en cuyo caso la respuesta es no a menos que uses algún tipo de proxy que esté entre ambos y pida a uno u otro según sea necesario.

Ahora bien, en este último caso dos aplicaciones en dos tecnologías diferentes (por ejemplo Node.js y ASP.NET) pueden convivir en un mismo sitio web, por lo que podrías montar ambas aplicaciones bajo el mismo sitio web virtual en IIS y que funcionasen sin problema.

Saludos!

Responder

andres Buitrago
andres Buitrago

Buenas tardes, estoy usando mssql , pero lo estoy implementando con typeScrypt  , sucede que al insentar procesar el result , me  muestra error , porque dice que
Property 'clave' does not exist on type 'IRecordSet<unknown>'.ts(2339)

supongo que es porque el result no es fijo , pero no se si algun conozca alguna manera de procesar el result para trabajar con los datos

Responder

Joaquín Sosa
Joaquín Sosa

Hola Andrés,

puede estar ocurriendo que no estes "tipando" la respuesta (Result) y por eso no reconoce esa propiedad.
Prueba a crear una clase con las propiedades a devolver en el result o bien tiparlo como any o Array<any>.
(Por defecto te estará llegando object[]).

Un saludo,
Joaquín

Responder

CARLOS GARCIA
CARLOS GARCIA

Buenas Noches Joquín, te cuento que en la empresa arranqué el desarrollo de una aplicación utilizando MySQL e implementando el módulo de  "mysql" de nodejs y utilizando "express-mysql-session", en la empresa en tecnología me piden que debo migrar todo a SQL para poder que reciban la aplicación... me puedes orientar de como debería realizar este proceso.

muchas gracias.

Responder

Hola todos, muy buen articulo, les platico, estoy iniciando en programacion y estoy empezando aprender React, me puse como proyecto hacer una conexion a una base de datos, en mi trabajo manejo SQL Server, y traigo la intencion de hacer una aplicacion para manipular los datos (altas,bajas, actualizacion de registros) de la db. Mas adelante traigo la intencion de diseñar una aplicacion con mapas, derivado de la informacion que tengo en mi base de datos, he pensando en Leaflet y Mapbox. Me gustaria que me dieran sus puntos de vista, como siempre agradecido por sus enseñanzas.

Responder

campusMVP
campusMVP

Hola Marco:

Para conectarte con una base de datos tendrás que crear un servicio web en el servidor, y que no puedes conectarte desde el cliente/navegador con React (ni con nada). Para lo de los mapas Leaflet está muy bien. De Mapbox no te podemos decir nada.

Saludos.

Responder

Agregar comentario

Los datos anteriores se utilizarán exclusivamente para permitirte hacer el comentario y, si lo seleccionas, notificarte de nuevos comentarios en este artículo, pero no se procesarán ni se utilizarán para ningún otro propósito. Lee nuestra política de privacidad.