SQL Crash Course Ep 2: Creating Tables, Adding and Deleting Data
By: Sam Thurman
Tags: Data, Sql, Data Science, Data Analysis, Database

SQL Crash Course Ep 2: Creating Tables, Adding and Deleting Data

Learn the basics of creating tables, adding rows, and deleting data in SQLite from the console/terminal

Overview

In this installment of SQL Crash Course, we’re going to learn the difference between a SQL database and a SQL table, and how to create them both — we’re going to get a more complete look at SQL and SQLite data types in the process. We’re then going to learn how we can add and delete data from these tables, and how we can manage the tables within a database.

This is episode 2 of our SQL Crash Course series. The last article talked about what SQL is, why it’s useful, and how we can use it to select and filter data from SQL tables. We also touched on SQL data types which is a concept that’s used heavily in the following tutorials. If you’re unfamiliar with these concepts, I suggest you quickly review the previous blog.

SQL Crash Course Ep 1: What Is SQL? How Can I Start Selecting Data? SQL Crash Course Ep 2: Creating Tables, Adding and Deleting Data

NOTE: The following tutorials are for a dialect of SQL called SQLite. The majority of syntax is interchangeable between all the different flavors of SQL, but it’s important to note that there may be slight differences in language if you’re using something like MySQL or PostgreSQL.

Article Structure

Overview

Database vs Table

SQLite Set Up

Creating Tables

Deleting Tables

Adding Data

Deleting Data

Conclusion

Database vs Table

SQL tables are objects within databases. They are two-dimensional structures containing rows and columns that hold data.

In SQL, tables are also required to have something called a primary key, which will be a column or columns at the far left of the table. Also called the unique identifier, primary keys (can be strings or integers) are generated or assigned to new entries as they are added to the table, and they are always different for each entry (hence the nickname ‘unique identifier’). These keys are great for allowing us to easily access a specific record in our table without having to filter based on column values.

SQL databases are a collection of objects such as tables, indices, views (the relationship between tables), and stored procedures (rules and methods). In order to access a table, you have to be connected to its database first. Databases can hold anywhere from one to thousands of tables.

Tables within a database can hold information independently, or they can be linked to other tables using common columns to form a system called a relational database (RDB). Fig 2 shows a relational database containing many tables, all connected to one degree or another.

SQLite Set Up

Before you can do anything with SQL, you need to have some flavor of SQL downloaded on your machine. We will be using SQLite throughout SQL Crash Course. 99% of the basic SQL syntax is interchangeable between different versions of SQL, so don’t worry if you have a different driver installed or are planning on switching to another flavor later. In any case, learning any SQL language will make learning the rest of them a breeze.

If you’re working on a Mac, you actually already have SQLite pre-installed. However, if you are on a different OS or for some reason don’t have SQLite already installed on your Mac, check out this super quick and easy tutorial for instructions on setting up SQLite on your machine (directions for Windows, Linux and Mac). This shouldn’t take longer than 2–3 minutes.

To verify SQLite is installed properly on your machine, simply type sqlite3 in the console. SQLite versions 3.x.x started coming out in 2004 and as such, we access SQLite in the console using the sqlite3 command.

You should get an output similar to the following:

SQLite version 3.29.0 2019-07-10 17:32:03

Enter ".help" for usage hints.

Connected to a transient in-memory database.

Use ".open FILENAME" to reopen on a persistent database.

sqlite>

The last line ( sqlite> ), where your cursor is now, indicates that we are now inside the SQLite CLI (command line interface). This is where we write all of our commands to connect to, pull from, and manipulate different data sources (databases and tables).

We’re done here, for now, so we’re going to exit out by pressing CTRL + D on our keyboard.

Creating a Database

Now that we’ve successfully downloaded SQLite and verified that it’s working properly, we can start creating our very own databases.

First, I suggest creating a new empty directory on your machine for this tutorial and navigating to the inside of it.

When we create a new database in SQLite, a hard copy of that database called a schema is actually stored on our machine. You’ll see this file appear with a .db file extension. This is the file that SQLite will update as we create/delete tables and add/remove data.

We can create a new SQL database in the console with a single line of code.

sqlite3 test.db

That’s it. Pretty simple right?

While simple, the code above does two very important things:

sqlite3 — tells our console to access the SQLite interface.

— tells our console to access the SQLite interface. test.db — tells SQLite to either connect to a current database at the current location called test.db or create a new database and store it’s schema in a file called test.db if no database by that name currently exists here.

In our case, since we don’t already have a database called test at our current location, SQLite creates one for us.

At this point, we should be inside the SQLite interface, this is indicated by sqlite> to the left of your cursor. Press CTRL + D to exit out, and then type ls and press ENTER to get a list of the files at your current location on disk. You should see a new file appear called test.db .

Creating Tables

Databases are no good without tables, so let’s create some now.

General Formula

The general formula for creating a new table in SQLite is as follows:

CREATE TABLE [IF NOT EXISTS] table_name (

[column_1] data_type PRIMARY KEY,

[column_2] data_type NOT NULL,

[column_3] data_type DEFAULT 0

);

There’s a lot going on here so let’s take a look at all the different pieces:

CREATE TABLE [IF NOT EXISTS] table_name(...); — tells SQLite to create a new table within our current database and call it table_name (can be whatever you want). The internal structure of table_name is specified by arguments inside () , and ; tells SQLite that we’re done with our command

— tells SQLite to create a new table within our current database and call it (can be whatever you want). The internal structure of is specified by arguments inside , and tells SQLite that we’re done with our command [column_1],[column_2],[column_3] —names for your new columns, can be whatever you want.

—names for your new columns, can be whatever you want. data_type will be a recognized SQL data type that you choose; only data of the specified type can be stored in each column.

will be a recognized SQL data type that you choose; only data of the specified type can be stored in each column. PRIMARY KEY — is a SQL attribute indicating that column_1 will be the unique identifier for the table. This key will be of data type data_type , and will be generated by SQLite.

— is a SQL attribute indicating that will be the unique identifier for the table. This key will be of data type , and will be generated by SQLite. NOT NULL — is a SQL attribute that requires our specified column to always have a valid value. It’s common for something to go wrong during data collection, resulting in NULL values being produced. By default, these values are allowed in SQL, and appear in our SQL table as NULL . By stating NOT NULL in our column declaration, we are telling our table “don’t permit new rows to be added if they contain NULLs in this column”.

— is a SQL attribute that requires our specified column to always have a valid value. It’s common for something to go wrong during data collection, resulting in NULL values being produced. By default, these values are allowed in SQL, and appear in our SQL table as . By stating in our column declaration, we are telling our table “don’t permit new rows to be added if they contain NULLs in this column”. DEFAULT 0 — The DEFAULT method lets us specify a default value for the column if no other value is specified. In this case, we are setting our default value to 0.

Connect to Database

The first thing we have to do is reopen the SQLite interface and connect to our test.db file (the physical representation of our test database).

Remember, to do this we simply type sqlite3 test.db . We should see sqlite> to the left of our cursor, indicating we’re inside the SQLite interface.

Create Table

Let’s create a new table within test.db called countries . We’ll give this table 3 columns: a primary key column called generated_ID , Country_ID which holds an integer, and Country_Name which will be a string.

sqlite> CREATE TABLE IF NOT EXISTS countries(

...> generated_ID INTEGER PRIMARY KEY,

...> Country_ID INT NOT NULL,

...> Country_Name TEXT NOT NULL

...> );

Make sure to include the semicolon (;) at the end of your command, this is how we tell SQLite we are done writing and we want it to run our command

Let’s take a look at the data types we used:

INTEGER / INT — interchangeable, specifies we only want integers in this column (no floats/decimals).

/ — interchangeable, specifies we only want integers in this column (no floats/decimals). TEXT — specifics that we want text data. Wrapper for VARCHAR, CHAR, other SQL dialect

In other SQL languages, we have to be a little more specific about our data types (length of string, size of integer, etc.), but SQLite makes using data types easy by unifying similar data types under 5 main categories — NULL , INTEGER , REAL , TEXT , BLOB — and implements back-end processes to store these values in the most efficient way. Here’s a great overview of these different data types in SQLite.

NOTE: You can still declare data of any type (ones used in other SQL dialects) in SQLite ( TINYTEXT , BINARY , FLOAT , etc.), the INT , TEXT , etc. wrappers in SQLite are just there to help us simplify the process of declaring data types.

Verify Table Exists

After entering the command above, we should have a new table in our test database called countries . Let’s verify its existence using the .tables command. The .tables command in our SQLite interface will give us back a list of all the tables currently living in test.db .

sqlite> .tables # get list of tables countries # output

We can also get an overview of the structure of a table using the .schema _tableName_ command. .schema … will return a copy of the CREATE statement used to initialize the table, including column names and data types.

sqlite> .schema countries # get schema for countries CREATE TABLE countries( # output

generated_ID INTEGER PRIMARY KEY,

Country_ID INT NOT NULL,

Country_Name TEXT NOT NULL

);

You’ll notice that the IF NOT EXISTS argument is not included in our schema print-out.

Deleting Tables

General Formula

Deleting a table is as simple as one line of code.

DROP TABLE table_name;

The DROP TABLE command followed by a table name will delete that table and all of the information inside it.

Delete a Table

There are any number of reasons you might want to delete a table. You may have spelled a name wrong, declared the wrong data type for a column, simply don’t need it anymore, etc.

To practice DROP TABLE , let’s first create a misspelled table that we don’t need, and then delete it. We’ll call this table clientss .

sqlite> CREATE TABLE clientss(

...> generated_ID INT PRIMARY KEY,

...> Client_Name TEXT NOT NULL,

...> Country_ID INT NOT NULL

...> );

As always, after creating a new table, let’s for check it’s existence.

sqlite> .tables # get list of tables in current database clientss countries # output

We should see our new clientss table along side our previously created countries table. We notice clientss misspelled so now we’ll delete it.

DROP TABLE clientss;

Now if we check our database’s tables, we should only see countries .

sqlite> .tables # get list of tables in current database countries # output

Adding Data

Now that we understand how to add and delete tables, we need to know how to fill these tables in with information.

General Formula

The formula for adding data to a table is pretty simple:

INSERT INTO table_name(column_1, column_2, ...)

VALUES

(..., ..., ...),

(..., ..., ...);

INSERT INTO table_name(column_1, column_2, ...) —this command tells SQLite that we want to add data to the specified tables at the specified column. This can trip people up, you must specify every column of data you wish to add. If you don’t remember every column name, you can just use the .schema _table_ command.

—this command tells SQLite that we want to add data to the specified tables at the specified column. This can trip people up, you specify every column of data you wish to add. If you don’t remember every column name, you can just use the command. VALUES (…,…)… — we use VALUES to indicate that the following information is to be added to the table/columns. Each entry (row) is comma-separated and wrapped in parentheses. Inside the parentheses, we have one value for each column indicated in the INSERT statement, separated by commas.

— we use to indicate that the following information is to be added to the table/columns. Each entry (row) is comma-separated and wrapped in parentheses. Inside the parentheses, we have one value for each column indicated in the statement, separated by commas. ; — of course, we always end our SQL commands with a semicolon.

You can add any number of rows at a time, but make sure you pay attention to your NOT NULL requirements and data types so as to not get errors when adding new entries.

Add Data

Tables hold data, it’s what they do. Let’s add some rows to our empty countries table using our formula from above.

First, let’s check the schema for our table again so we know what values need entered.

sqlite> .schema countries # get schema for countries table CREATE TABLE countries(. # output

generated_ID INTEGER PRIMARY KEY,

Country_ID INT NOT NULL,

Country_Name TEXT NOT NULL

);

Since generated_ID is our generated primary key, the only two columns we need to worry about are Country_ID which is an integer, and Country_Name which is a string. We’re going to make these values up.

sqlite> INSERT INTO countries(Country_ID, Country_Name)

...> VALUES

...> (8001, "United States"),

...> (8002, "Canada"),

...> (8003, "Mexico");

Remember to leave numbers ( INT ) as they are — no quotes — and make sure your TEXT values do have quotes around them — indicating they are strings.

Verify Rows Exist

Again, we don’t get any output so let’s check to verify that our values made it to the countries table.

To do this, we’re going to use a SELECT statement. We covered this in SQL Crash Course Ep 1 so if you need a refresher, check there.

Remember SELECT is how we retrieve data from a table, and since the only rows that should exist in our countries table are the ones we just added, we can use SELECT to pull every row in our table to get a look at our new entries. We can do this in one line with the following command:

sqlite> SELECT * FROM countries; # select all rows from countries 1|8001|United States # output

2|8002|Canada

3|8003|Mexico

Deleting Data

It’s very common for us to want to delete certain data from our tables. Because the range of possibilities for what we might want to delete is so vast (single entry, multiple entries in a row, all entries on a specific date with a specific value, etc.), SQL syntax for removing data has to be very flexible.

General Formula

The syntax for deleting data in SQL looks very similar to a SELECT statement.

DELETE FROM table_name WHERE condition...;

Unlike a SELECT statement, we don’t specify certain columns to access. Rather, we specify a table_name to delete from and a condition that decides which data is to be deleted. This condition , following the WHERE clause, will be identical to the syntax for a SQL SELECT statement. This condition can be as complex and multi-faceted as you need.

Delete Data

Let’s say we no longer need an entry for Mexico in our countries table, as we’ve concluded our contracts with all of our clients there.

Remember that in order to delete data, we need to specify conditions that describe only the entries we wish to delete. Even though these conditions have to be specific, there is often still more than one way to delete any given bit of data.

Since our table is so small, we essentially have 3 uniquely identifying bits of information for our Mexico entry that we can use as conditions to delete by:

Country_Name — Mexico is the only entry in countries with this name

— Mexico is the only entry in with this name Country_ID — we selected this value and set it to be different from our other IDs in the table

— we selected this value and set it to be different from our other IDs in the table generated_ID — which is set as our always unique PRIMARY KEY (this is the easiest way to access a single, unique entry)

Here’s 3 different DELETE statements we could use to remove our Mexico entry, using each of our 3 bits of uniquely identifying information:

Using Country_Name

DELETE FROM countries WHERE Country_Name="Mexico";

Using Country_ID

DELETE FROM countries WHERE Country_ID=8003;

Using generated_ID

DELETE FROM countries WHERE generated_ID=3;

Only use one of these commands to delete your Mexico entry.

Verify Deletion

A DELETE statement that doesn't have any data meeting it’s condition (doesn't delete any data) won’t throw an error, so it’s important to check that our entry has been successfully removed from our table.

We can either do this by pulling all of the data in our table to check if Mexico appears (this is not ideal when our table is very large), or we can use a specific SELECT statement to check for values matching either Mexico’s generated_ID , Country_ID , or Country_Name .

We’re going to use the second method, and write a SELECT statement for all entries where Country_Name is “Mexico.” This should return nothing if we wrote our DELETE statement properly.

sqlite> SELECT * FROM countries WHERE Country_Name="Mexico";

sqlite> # output, new line, should be empty

If you are presented with nothing but your cursor on a new line, everything worked perfect. If you are returned any entries, your condition in either the SELECT or DELETE statement could be incorrect.

Conclusion

That was a long one. Take a break and pat yourself on the back, you did something difficult.

In summary, in this episode of SQL Crash Course we learned about databases and tables. We learned that databases hold lots of different objects, including tables, and that tables hold our raw data in the form of rows/columns/indices. We learned how to create and delete databases and tables, and how to check the state/contents of each — we also learned more about data types in the process. We finished up by learning how to add and delete data from tables, and that there are often many different ways to filter (in SELECT and DELETE ) for the same condition.