3.2.5: SQL - Express
Database Setup
Our node applications will not set up the Database or the tables. Databases and tables need to be created before our applications run. The code in this section assumes that we have set up Postgres, at this point you should have created a Postgres user and be able to enter the DataBase named after the current Unix username. We can retrieve the current Unix username with the whoami
command in Terminal.
When running the below code, replace <MY_UNIX_USERNAME>
with your Unix username. We will connected to the users database that we developed in a previous section.
pg NPM Library
To use Postgres in Node, we need to install the Postgres client library for node, pg. This enables our application to connect with our database. The command below should be run within an npm initialised directory:
npm install pg
DB Queries in Node
SELECT
The following Node application runs a SQL query on our students
table. What does this code do?
Replace <MY_UNIX_USERNAME>
index.js
const pg = require('pg');
const { Client } = pg;
// set the way we will connect to the server
const pgConnectionConfigs = {
user: '<MY_UNIX_USERNAME>',
host: 'localhost',
database: '<MY_UNIX_USERNAME>',
port: 5432, // Postgres server always runs on this port
};
// create the var we'll use
const client = new Client(pgConnectionConfigs);
// make the connection to the server
client.connect();
// create the query done callback
const whenQueryDone = (error, result) => {
// this error is anything that goes wrong with the query
if (error) {
console.log('error', error);
} else {
// rows key has the data
console.log(result.rows);
}
// close the connection
client.end();
};
// write the SQL query
const sqlQuery = 'SELECT * FROM students';
// run the SQL query
client.query(sqlQuery, whenQueryDone);
client.end()
terminates the connection with the SQL client, which is necessary for our Node script to exit. If we do not terminate the SQL connection, the Node script will hang until the connection is terminated.
Command Line
node index.js
Note
When working in companies you may be asked to mask your database credentials with .env.
INSERT
When we replace the SQL query in index.js
with the following, what does this do?
const sqlQuery =
"INSERT INTO students (first_name, last_name, mobile, gender) VALUES ('Eric', 'Marsh', 874480753, true)";
INSERT with value params
We can give structured data to the query. The syntax is slightly different.
Confusingly, SQL syntax here uses an array to pass in the data: ['Eric', 'Marsh', 874480753, true]
then references those array values in the query, INSERT INTO students(first_name, last_name, mobile, gender) VALUES($1, $2, $3, $4)
but the value $1
references array index 0
. This is because SQL is a [1-indexed language](https://stackoverflow.com/questions/53631015/why-sql-primary-key-index-begin-at-1-and-not-at-0#:~:text=3 Answers&text=Counting in SQL generally starts,1 %28and not 0%29.&text=We don't start counting at zero until we learn programming.), and most other programming languages including JS are 0-indexed.
const inputData = ['Eric', 'Marsh', 874480753, true];
// in this example, $1 is going to be replaced with 'Eric'
const sqlQuery = 'INSERT INTO students (first_name, last_name, mobile, gender VALUES ($1, $2, $3, $4)';
client.query(sqlQuery, inputData, whenQueryDone);
SQL Entity Naming and Casing
Database names should match the relevant code repo name and be in snake case (i.e. lowercase with underscores between words). For example,
ufo_express
.Table names are pluralised snake case. For example,
ufo_sightings
.Column names are singular snake case. For example,
ufo_shape
.We use snake case for SQL because SQL entities are case-insensitive, and - is a special character in some SQL implementations, while _ is not.
Postgres and Express
When developing full stack applications we will need to interface our Postgres database with the Express Application such that we can fire off functions that query the database through API's.
To run the code below you will need to install Express into the same npm initialised directory that you created for the previous code block. Run this command:
npm install express
Alter the current index.js to reflect the code below, changing the value of<MY_UNIX_USERNAME>
.
index.js
const express = require('express');
const pg = require('pg');
// Initialise DB connection
const { Pool } = pg;
const pgConnectionConfigs = {
user: '<MY_UNIX_USERNAME>',
host: 'localhost',
database: '<MY_UNIX_USERNAME>',
port: 5432, // Postgres server always runs on this port by default
};
const pool = new Pool(pgConnectionConfigs);
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
// Code to retireve all rows from the students table
app.get('/', (request, response) => {
console.log('request came in');
const whenDoneWithQuery = (error, result) => {
if (error) {
console.log('Error executing query', error.stack);
response.status(503).send(result.rows);
return;
}
console.log(result.rows[0].name);
response.send(result.rows);
};
// Query using pg.Pool instead of pg.Client
pool.query('SELECT * FROM students', whenDoneWithQuery);
});
// Code to insert a student into the students table
app.post('/', (request, response) => {
console.log('request came in');
console.log(request.body)
let first_name = request.body.first_name;
let last_name = request.body.last_name;
let mobile = request.body.mobile;
let gender = request.body.gender;
const whenDoneWithQuery = (error, result) => {
if (error) {
console.log('Error executing query', error.stack);
response.status(503).send(result.rows);
return;
}
console.log(result.rows);
response.send(result.rows);
};
// Query using pg.Pool instead of pg.Client
pool.query(`INSERT INTO students (first_name, last_name, mobile, gender) VALUES ('${first_name}', '${last_name}', ${mobile}, ${gender})`, whenDoneWithQuery);
});
app.listen(3004);
Note: There is no need to run pool.end
like how we ran client.end
with the pg
Client
class in our Node CLI apps. This is because in server applications we expect the DB connection to persist beyond individual requests.
Command Line
node index.js
Exercise
Develop a put and delete handler within this Express application.
The put request should alter an existing student stored within your tables, you may need to use request parameters here.
The delete request should remove a student from your tables, again, consider using request parameters.
Test your API calls using Thunder Client.