Intro to SQL and Relational Databases: Build and Destroy
-
Overview
- Definitions
- Connecting to a database
- Creating a schema with tables
- Seeding a database
- Altering Tables
- Dropping Tables/Databases
-
What is a database?
A database is an organized collection of data. A database will usually have some sort of api to query the data. Using a Structured Query Language (SQL) will allow you to interact with the data in a predictable way. A query in this case is a statement you ask a database. A properly made database will be able to answer a query with all relevent information.
-
Connecting to a database
-
MySQL
MySQL is a popular Relational Database Management System (RDBMS). It runs on most systems, so it can be run directly on your own machine. It is sometimes preferred to run it on a Docker instance running LINUX.
-
MySQL
In order to connect to a MySQL instance, you need to know a few things:
- Host - this is usually a url or ip address for a server
- Port - Port listening for a connection (defaults to 3306)
- Username - The MySQL user you are connecting with
- Password - The password for the user (This could be blank)
-
Installing MySQL on MacOS Catalina and later:
Catalina threw us a whammy!
To install MySQL successfully on Catalina, first make sure no other versions are running on your machine:
$ sudo ps ax | grep mysql
If you see more lines in the response than the one that contains grep mysql
, then you’ll need to locate the mysql
folders and remove them.
To search for them, press ⌘
and the space bar and enter mysqladmin
into the prompt, followed by selecting “Show All In Finder” in the left rail.
-
Installing MySQL on MacOS Catalina and later (continued):
Once all the other versions are removed, reboot your computer and install the DMG package from: https://dev.mysql.com/downloads/mysql/
-
Installing MySQL on MacOS Catalina and later (continued):
Once you have successfully installed the package, add the mysql binary to the .bash_profile
(if bash
is your default terminal):
nano ~/.bash_profile
If zsh
is your default terminal:
nano ~/.zshrc
At the bottom of the file, add the following line:
export PATH="$PATH:/usr/local/mysql/bin"
Quit Terminal, and restart it, opening a new Terminal window. You should now be able to connect to MySQL successfully.
(You can avaid having to restart Terminal by using the following command: source ~/.bash_profile
or source ~/.zshrc
)
-
MySQL
Once installed, you can connect to your MySQL server via the command line:
$ mysql -u root -p
You will be prompted to enter the password:
Enter password:
Once the password is entered correctly, you will be connected, and a MySQL prompt will appear:
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
To disconnect, type exit
.
-
MySQL
Once you have connected, it is advised for security reasons that you create a new user. The current user is the root user which will always have all privileges, and it is insecure to use it for general purposes. To make a new user and give them permissions to do anything (ergo an admin user), you may use the following SQL Script:
CREATE USER new_user@localhost IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON *.* TO new_user@localhost;
This will create a user with username new_user
and password password
. Note if you forget the root password and this password you will not have a way of resetting this.
-
MySQL
- Created user has all the same powers as root user
- Keep track of who is running particular queries
- Possible to create users that can only read data
- Keep everyone’s permissions to minimum… even yours
-
Creating a schema with tables
-
Schemas and Tables
Lets say we are designing a database for our backend developers. They are creating an app for teachers to keep track of their student’s assignments. We’ll also want to keep meta data on the teachers. Their application has Students, Teachers, Labs, and Submissions. Let’s try to go through designing this database
First we’ll need to make a schema. To do this we can run the following script
CREATE SCHEMA zipcode;
(the command CREATE DATABASE
will do the same)
-
Schemas and Tables
What have we just done? We created a SCHEMA
- Created a home for all data related to an application
- Allowed ourselves to manage multiple applications in the same database without worrying about collisions
-
Schemas and Tables: SHOW DATABASES
To display the databases that exist on your server, use the SHOW DATABASES
command:
SHOW DATABASES;
Expected result:
+-----------------------+
| Database |
+-----------------------+
| information_schema |
| db_example |
| mysql |
| performance_schema |
| sys |
| zc_de001 |
| zipcode |
+-----------------------+
7 rows in set (0.00 sec)
-
Schemas and Tables: USE
- Select the database (schema) so that you can run queries and commands against it.
- If no database has been selected, you must specify the schema in each query
USE zipcode;
Expected result:
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
-
Schemas and Tables: CREATE TABLE
- Creates a table.
- Must be done before putting any data in.
- This is where you define what your table will look like.
- Can be modified later by doing an ALTER TABLE.
- Defines the table name, column names, datatypes, and special rules / constraints.
- Also how you link to other tables.
-
Schemas and Tables: CREATE TABLE syntax
CREATE TABLE table_name (
column1 datatype,
column2 datatype,
column3 datatype
);
-
Schemas and Tables: CREATE TABLE example
Teachers have a name and a specialty. We are going to create a table with these fields as well as a unique identifier. To create a a table we use the CREATE TABLE
command. Let’s make the Teacher Table
CREATE TABLE zipcode.teachers
(
id INTEGER PRIMARY KEY NOT NULL AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
specialty ENUM('FRONT END', 'MIDDLE TIER', 'DATA TIER')
);
In this query we create each column followed by the properties of the columns. We are using the INTEGER
, VARCHAR
, and ENUM
data types
-
Schemas and Tables: CREATE TABLE example
Next, let’s make a student table. The students will have a name, and a classroom as well notes from the teachers on a particular student
CREATE TABLE zipcode.students
(
id INTEGER PRIMARY KEY NOT NULL AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
classroom TINYTEXT,
notes TEXT
);
In this query, we create each of these columns and are using INTEGER
, VARCHAR
, TINYTEXT
, and TEXT
.
-
Schemas and Tables: CREATE TABLE example
Next, we’ll need a table that shows the relationship between the assignments and the students (a pivot table)
CREATE TABLE zipcode.assignment_student
(
id INTEGER PRIMARY KEY NOT NULL AUTO_INCREMENT,
student_id INTEGER NOT NULL,
assignment_id INTEGER NOT NULL
);
-
Schemas and Tables: CREATE TABLE example
Lastly we need an assignment table. This should just have the assignment name and a link to the assignment
CREATE TABLE zipcode.assignments
(
id INTEGER PRIMARY KEY NOT NULL AUTO_INCREMENT,
name TINYTEXT NOT NULL,
URL CHAR(255) NOT NULL,
teacher_id INTEGER
);
Here we are creating a table similar to the last two, but making the URL a fixed length CHAR
field and making that unique. Why?
-
Schemas and Tables
Lastly, we’ll create the teacher_meta table. In the meta table, the developers want to keep track of the number of years a teacher has worked here, and the room number of the teacher’s office.
CREATE TABLE zipcode.teacher_meta
(
id INTEGER PRIMARY KEY NOT NULL AUTO_INCREMENT,
room_number TINYINT UNSIGNED,
years TINYINT UNSIGNED
);
Here, we use the TINYINT
column and make those unsigned
-
Schemas and Tables: SHOW TABLES
To display the tables in your chosen database (schema), use the SHOW TABLES
command:
SHOW TABLES;
Expected result:
+--------------------+
| Tables_in_zipcode |
+--------------------+
| assignment_student |
| assignments |
| students |
| teacher_meta |
| teachers |
+--------------------+
5 rows in set (0.00 sec)
-
Schemas and Tables: DESCRIBE
To display the details of a table settings, use the DESCRIBE
command:
describe teachers;
Expected result:
+------------+---------------------------------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+---------------------------------------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| specialty | enum('FRONT END','MIDDLE TIER','DATA TIER') | YES | | NULL | |
| name | varchar(50) | NO | | NULL | |
+------------+---------------------------------------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
-
Schemas and Tables: ALTER TABLE
Now we have tables, but we have learned that teachers are actually going to have a first name and last name, and the developers have said that they want these to be two separate fields. Before we continue, let’s ALTER
this table.
-
Schemas and Tables: ALTER TABLE Syntax
ALTER TABLE table_name
[alter_specification [, alter_specification] ...]
-
Schemas and Tables: ALTER TABLE ADD
ALTER TABLE ADD
statement appends a new column to a table.
In this statement, you must specify the following: - the name of the table in which you want to add the new column - the name of the column, data type, and constraint if applicable
ALTER TABLE table_name
ADD column_name data_type column_constraint;
-
Schemas and Tables: ALTER TABLE ADD
If you want to add multiple columns to a table at once using a single ALTER TABLE statement, specify a comma-separated list of columns that you want to add to a table after the ADD clause:
ALTER TABLE table_name
ADD column_name_1 data_type_1 column_constraint_1,
ADD column_name_2 data_type_2 column_constraint_2,
...,
column_name_n data_type_n column_constraint_n;
-
Schemas and Tables: ALTER TABLE CHANGE
Sometimes, you will need to rename a column and retain its data. For this, you will use CHANGE
clause, specifying the following:
- the name of the table in which you want to rename the column.
- the name of the column that you want to rename and its desired settings.
ALTER TABLE table_name CHANGE old_name new_name data_type column_constraint;
-
Schemas and Tables: ALTER TABLE CHANGE
If you want to change multiple columns in the same statement:
ALTER TABLE table_name
CHANGE old_name new_name data_type column_constraint,
CHANGE old_name2 new_name3 data_type column_constraint,
CHANGE old_name3 new_name3 data_type column_constraint ;
-
Schemas and Tables: ALTER TABLE DROP COLUMN
Sometimes, you need to remove one or more columns from a table. To do this, you use the ALTER TABLE DROP COLUMN
statement. In this statement, you must specify the following:
- the name of the table from which you want to delete the column.
- the name of the column that you want to delete.
ALTER TABLE table_name
DROP COLUMN column_name;
-
Schemas and Tables: ALTER TABLE DROP COLUMN - a note
Sometimes a constraint on the column will require additional steps before dropping it. For example, if the column that you want to delete has a CHECK
constraint, you must delete the constraint first before removing the column.
We’ll more talk about adding and dropping contraints later.
-
Schemas and Tables: ALTER TABLE DROP COLUMN Syntax
To delete multiple columns at once, specify columns that you want to drop as a list of comma-separated columns in the DROP COLUMN
clause:
ALTER TABLE table_name
DROP COLUMN column_name_1, DROP COLUMN column_name_2,...;
Now, back to our updates as requested by the developers.
-
Schemas and Tables: ALTER TABLE example
For our change according to developer request, we are going to ADD
firstname and lastname columns. Then, we will DROP
the name column.
ALTER TABLE zipcode.teachers
ADD firstname VARCHAR(25) NOT NULL,
ADD lastname VARCHAR(25) NOT NULL;
ALTER TABLE zipcode.teachers DROP name;
This will add our new columns to the teachers
table, in the order they were entered, and remove the name
column completely.
-
Schemas and Tables: ALTER TABLE example
After our updates, the developers have requested that we change the firstname and lastname columns to first_name and last_name.
ALTER TABLE teachers CHANGE firstname first_name varchar(255);
This change the names of the columns, while leaving it’s underlying settings, and their content intact in the teachers
table.
-
Seeding a Database
-
Seeding a Database: INSERT
Our database is set up for our devs to use, but they’ve asked us to create some mock data for them to demo their app. To do this we’ll have to INSERT
some data.
Let’s start by inserting a few teachers.
-
Seeding a Database: INSERT
Puts data into a table. Inserts will generally have 3 parts:
- Reference to the table you want to insert into
- The columns you want to fill
- The values to fill those columns with
- Must provide all required values.
- This means columns that specify the following:
NOT NULL
- Do not have a
DEFAULT
- Are not
AUTO_INCREMENT
columns
- This means columns that specify the following:
- If
NULL
values are allowed, those columns can be excluded in theINSERT
.
- Must provide all required values.
Let’s create a teacher, and then that teacher’s meta info.
-
Seeding a Database: INSERT syntax – No column names
- Without specifying columns, you must make sure that every column is accounted for in the insert.
INSERT INTO table VALUES(column1_value, column2_value);
-
Seeding a Database: INSERT example – No column names
INSERT INTO zipcode.teachers
VALUES ('FRONT END', 'John', 'Smith');
-
Seeding a Database: INSERT syntax – With column names
INSERT INTO table(column1_name, column2_name)
VALUES(column1_value, column2_value);
-
Seeding a Database: INSERT example – With column names
INSERT INTO zipcode.teachers (first_name, last_name, specialty)
VALUES ('John', 'Smith', 'FRONT END');
Here we are creating a new row in the teachers table. The first_name is set to John, the last_name is set to Smith, and the specialty is set to FRONT END. Note that the order of the columns we listed will be the order we list the values. If there is a different number of columns and values, then this will throw an error. Also note that since the id on this table is set to auto increment, it will automatically be filled in with the id of 1.
-
Inserts
We now have one teacher in this table and we can add a few more, but instead of running them one by one, we can also just add many at the same time.
INSERT INTO zipcode.teachers (first_name, last_name, specialty)
VALUES ('Tabitha', 'Schultz', 'MIDDLE TIER'),
('Jane', 'Herman', 'DATA TIER');
-
Inserts
With the ability to insert data, we can also start populating the other tables
INSERT INTO zipcode.teacher_meta (teacher_id, years, room_number)
VALUES (1, 3, 2),
(2, 3, 2),
(3, 10, 1);
INSERT INTO zipcode.students (name, classroom, notes)
VALUES ('Linnell McLanachan', '1A', 'Likes Data'),
('Lorianna Henrion', '1A', 'Loves Data'),
('Corena Edgeson', '1A', 'Cannot get enough of data'),
('Archaimbaud Lougheid', '2A', 'Would rather do nothing other than sit down in front of a mountain of data and read through it like a book. SERIOUSLY needs to seek help about this because there is no way it is healthy for this person to like data any more than they do'),
('Dun Pettet', '2A', NULL ),
('Hymie Parrington', '2A', 'Enjoys the Star Wars prequels');
-
Inserts
INSERT INTO zipcode.assignments (name, URL, teacher_id)
VALUES ('Pokemon Lab', 'https://github.com/Zipcoder/PokemonSqlLab', 3),
('Poll App', 'https://github.com/Zipcoder/CR-MacroLabs-Spring-QuickPollApplication', 3),
('Sum or Product', 'https://github.com/Zipcoder/ZCW-MicroLabs-JavaFundamentals-SumOrProduct', 2);
INSERT INTO zipcode.assignment_student (assignment_id, student_id)
VALUES (1, 1), (1, 2), (1,3), (1,4), (1,5), (1,6), (2, 1);
-
Updates
Updating data is very similar to inserting, but we will use an UPDATE
clause instead. For this we will need to specify a table we want to update, then a SET
clause to specify how to change a field or fields.
Our devs inform us that they want a way to increment the number of years each teacher has worked here. Let’s see how we would write that update statement
-
Updates
UPDATE zipcode.teacher_meta
SET years = years+1;
Here we are able to increment the years by setting years = to whatever its own value is, plus one. This works because SQL will go row by row. In each row, the years variable is set to whatever the value is in that particular row.
-
Documentation Links
ALTER TABLE
-