diff --git a/content/sql-part-5/_index.md b/content/sql-part-5/_index.md new file mode 100644 index 00000000..388675b7 --- /dev/null +++ b/content/sql-part-5/_index.md @@ -0,0 +1,42 @@ ++++ +pre = "22. " +chapter = true +title = "SQL Part 5: Schemas and CRUD Operations" +date = 2024-04-17T13:28:48-05:00 +draft = false +weight = 22 ++++ + +## Learning Objectives + +Upon completing all the content in this chapter, you should be able to do the following: + +1. Understand what a schema is. +1. Create new tables and add new records to existing tables. +1. Update existing tables. +1. Remove records from a table and delete tables. + +## Key Terminology + +Here is a list of key terms for this chapter broken down by the page they first appear on. Make note of each term and its definition. + +### Schemas + +1. schema + +### Create + +1. `CREATE` +1. temporary tables + +## Update + +1. `UPDATE` + +## Delete + +1. `DELETE` + +## Content Links + +{{% children %}} diff --git a/content/sql-part-5/exercises/_index.md b/content/sql-part-5/exercises/_index.md new file mode 100644 index 00000000..802af4a6 --- /dev/null +++ b/content/sql-part-5/exercises/_index.md @@ -0,0 +1,24 @@ ++++ +title = "Exercises: Schemas and CRUD Operations" +date = 2021-10-01T09:28:27-05:00 +draft = false +weight = 2 ++++ + +## Getting Started + +Open up the `SQL-Part-5-Exercises.ipynb` notebook in `data-analysis-projects/sql-part-5/exercises`. + +For the exercises and studio in this chapter, you need to connect to the `JunkDB` named after your class. This database serves as a playground for you to experiment with what you learned in this chapter. + +With your new connection configured, click on the junk database in the Object Explorer. Instead of clicking on *Tables*, click on the folder called *Security* and then *Schemas*. You should see a schema with your name on it. When practicing these queries, you will only be able to use your schema. + +The example below shows how you can use the same process of finding the schema named after you to find the `HumanResources` schema in the `AdventureWorks2019` Database. + +![File Tree, Security Folder to schema folder to individual schemas](./pictures/Schemas.png) + +## Submitting Your Work + +When finished make sure to push your changes up to GitHub. + +Copy the link to your GitHub repository and paste it into the submission box in Canvas for **Exercises: SQL Part 5** and click *Submit*. \ No newline at end of file diff --git a/content/sql-part-5/exercises/pictures/Schemas.png b/content/sql-part-5/exercises/pictures/Schemas.png new file mode 100644 index 00000000..b9d8f198 Binary files /dev/null and b/content/sql-part-5/exercises/pictures/Schemas.png differ diff --git a/content/sql-part-5/next-steps.md b/content/sql-part-5/next-steps.md new file mode 100644 index 00000000..bfc22b66 --- /dev/null +++ b/content/sql-part-5/next-steps.md @@ -0,0 +1,12 @@ ++++ +title = "Next Steps" +date = 2021-10-01T09:28:27-05:00 +draft = false +weight = 4 ++++ + +This closes out the section of the course where we just focus on SQL Server. Here are some additional resources on schemas and CRUD oeprations before you dive into the next chapter. + +1. [SQL Shack](https://www.sqlshack.com/crud-operations-in-sql-server/) +1. [Microsoft](https://learn.microsoft.com/en-us/sql/relational-databases/security/authentication-access/create-a-database-schema?view=sql-server-ver16) +1. [SQL Server Tutorial](https://www.sqlservertutorial.net/sql-server-basics/sql-server-primary-key/) diff --git a/content/sql-part-5/reading/_index.md b/content/sql-part-5/reading/_index.md new file mode 100644 index 00000000..0f8ad22c --- /dev/null +++ b/content/sql-part-5/reading/_index.md @@ -0,0 +1,10 @@ ++++ +title = "Reading" +date = 2024-04-17T13:28:48-05:00 +draft = false +weight = 1 ++++ + +## Reading Content + +{{% children %}} diff --git a/content/sql-part-5/reading/create/_index.md b/content/sql-part-5/reading/create/_index.md new file mode 100644 index 00000000..b6d6a7ae --- /dev/null +++ b/content/sql-part-5/reading/create/_index.md @@ -0,0 +1,189 @@ ++++ +title = "Create" +draft = false +weight = 2 ++++ + +Previously, we outlined the four types of operations we can perform with SQL queries as CRUD. We have only done read operations so far with `SELECT` queries. Now we get to focus on operations that create new tables and add new records to existing tables. + +## Creating Tables + +The general syntax to create a new table starts with a `CREATE` statement and includes the names of the columns and their datatypes. + +```sql {linenos=table} +CREATE TABLE schema_name.table_name ( + Column1Name column1datatype, + Column2Name column2datatype, + . + . + . + ColumnNName columnndatatype +); +``` + +When creating new tables, you first want to sketch out what columns the table should have. Once you create your table, adding a column after the fact is not advisable. You really want to make sure that you know what that table needs to have before you run your query to create the table. + +{{% notice blue Note %}} + +Later on in your career, you may learn how to alter a table using the `ALTER TABLE` statement, but for now that is outside the scope of this class. To learn more, check out this article from [Microsoft](https://learn.microsoft.com/en-us/sql/t-sql/statements/alter-table-transact-sql?view=sql-server-ver16). + +{{% /notice %}} + +Let's say that we work for a major grocery store chain and are part of the team evaluating the success of their rewards program. The database is called `FineFoods`, but the tables associated with the rewards program are going to be grouped together in a schema called `rewards`. As the rewards program rolls out, we want to track which in-app coupons were used by consumers in a table called `used_coupons` to determine what kinds of coupons we want to offer later. + +Before we create `used_coupons`, we need to think about what data we want to store and what data type each column should be. To start, let's return to the business issue. The store wants us to analyze what coupons rewards customers used to figure out which coupons should be offered again and when those coupons should be offered. We need to know what the coupon was for, so we need to store the item's name, the manufacturer, the redeemable value of the coupon, and the category the item fell into. We need to know *when* those coupons were used too so we want to store the date when the coupon was used. Finally, we want to give each used coupon a unique identifier so we can easily connect this table to other tables later on. + +With all these factors in mind, here is our initial `CREATE` query to make this table. + +```sql {linenos=table} +CREATE TABLE rewards.used_coupons ( + UsedCouponID int, + ItemCategory varchar(255), + Manufacturer varchar(255), + ItemName varchar(255), + RedeemableValue double, + RedeemedDate date +); +``` + +While this is a good place to start, we want to make `UsedCouponID` a primary key and add a foreign key to the `coupons` table, so we can count how many times a specific coupon was used. Time to refine our query before we run it! + +### Setting Up Primary and Foreign Keys + +We want `UsedCouponID` to be a primary key. Furthermore, to make our lives easier, we want to make the primary key automatically increment. That way, the first item added to the table will automatically be given a `UsedCouponID` of 1, the second one will have a `UsedCouponID` value of 2, and so on. Let's alter the column declaration in the `CREATE` statement above. + +```sql +UsedCouponID int IDENTITY(1,1) PRIMARY KEY +``` + +Here, we use the `IDENTITY(x,y)` keyword to designate that SQL Server needs to auto-increment starting at `x` and increasing by `y`. `IDENTITY(1,1)` means that SQL Server should start with a primary key of 1 and increase by 1. + +Now we can add a foreign key column called `CouponID` that references the primary key column called `CouponID` in a table called `coupons` table. + +```sql +CouponID int FOREIGN KEY REFERENCES coupons(CouponID) +``` + +If we add a primary key and a foreign key to our table, then our `CREATE` statement would now look like: + +```sql {linenos=table} +CREATE TABLE rewards.used_coupons ( + UsedCouponID int IDENTITY(1,1) PRIMARY KEY, + CouponID int FOREIGN KEY REFERENCES coupons(CouponID), + ItemCategory varchar(255), + Manufacturer varchar(255), + ItemName varchar(255), + RedeemableValue double, + RedeemedDate date +); +``` + +### Temporary Tables + +**Temporary tables** or temp tables are often used when you may not have certain permissions on a database but need to run queries in your everyday work. Only you can see the temp table you create in the connection you created it in. You cannot access the temp table from another workspace/window/notebook. When you close the connection the table has been created in, it’s automatically deleted. + +You can make a temporary table by adding a hashtag in front of the table name. If we wanted to make a temporary table for the rewards program for just ice cream coupons, we would run the following query. + +```sql {linenos=table} +CREATE TABLE #IceCreamCoupons ( + IceCreamCouponID int, + ItemName varchar(255) +); +``` + +## Adding Records + +With our table set up, we can add a new record using the `INSERT` statement. When adding a new record, we can use the following general syntax: + +```sql {linenos=table} +-- Inserting a record with values for each column in the table + +INSERT INTO schema_name.table_name +VALUES (Column1, Column2, ..., ColumnN); + +-- Inserting a record with values for some of the columns in the table + +INSERT INTO schema_name.table_name (Column2Name, Column5Name, ...) +VALUES (Column2, Column5, ...); +``` + +If we wanted to add a new coupon for candy to the `used_coupons` table, we would write the following: + +```sql +INSERT INTO rewards.used_coupons (CouponID, ItemCategory, Manufacturer, ItemName, RedeemableValue) +VALUES (276, 'candy', 'Trolli', 'Sour Brite Crawlers', 1.00); +``` + +We do not have to specify the primary key column because we set that column auto-increment so SQL Server will add a value for that column automatically. In the above query, since we do not have a redeemed date for this coupon, that value will remain `NULL` for now. + +## Check Your Understanding + +{{% notice green Question %}} + +Which of the following queries would you use to create a table called recipes, that holds name (up to 25 characters), description (up to 50 characters), and instructions (up to 500 characters). + +1. ``` sql + CREATE TABLE schema_name.recipes( + name VARCHAR(25), + description VARCHAR(50), + instructions VARCHAR(500), + ); + ``` + +1. ```sql + MAKE TABLE schema_name.recipes( + name VARCHAR(25), + description VARCHAR(50), + instructions VARCHAR(500), + ); + ``` + +1. ```sql + CREATE TABLE schema_name.recipes( + name, + description, + instructions, + ); + ``` + +1. ```sql + CREATE TABLE schema_name.recipes( + name (25), + description (50), + instructions (500), + ); + ``` + +{{% /notice %}} + + + +{{% notice green Question %}} + +Which of the following queries would add information into the `Recipes` table below. + +![Recipes table with one row](./pictures/recipesTables1.png) + +1. ```sql + INSERT INTO schema_name.Recipes (name, description, instructions) + VALUES('Pizza', 'To lazy to cook but hungry', 'Call ModPizza and order for delivery'); + ``` + +1. ```sql + ADD ROW schema_name.Recipes (name, description, instructions) + VALUES('Pizza', 'To lazy to cook but hungry', 'Call ModPizza and order for delivery'); + ``` + +1. ```sql + INSERT INTO schema_name.Recipes (2, name, description, instructions) + VALUES('Pizza', 'To lazy to cook but hungry', 'Call ModPizza and order for delivery') + ``` + +1. ```sql + ADD ROW schema_name.Recipes (2, name, description, instructions) + VALUES('Pizza', 'To lazy to cook but hungry', 'Call ModPizza and order for delivery') + ``` + +{{% /notice %}} + + \ No newline at end of file diff --git a/content/sql-part-5/reading/create/pictures/recipesTables1.png b/content/sql-part-5/reading/create/pictures/recipesTables1.png new file mode 100644 index 00000000..9fbfce18 Binary files /dev/null and b/content/sql-part-5/reading/create/pictures/recipesTables1.png differ diff --git a/content/sql-part-5/reading/delete/_index.md b/content/sql-part-5/reading/delete/_index.md new file mode 100644 index 00000000..b8fcd59c --- /dev/null +++ b/content/sql-part-5/reading/delete/_index.md @@ -0,0 +1,66 @@ ++++ +title = "Delete" +draft = false +weight = 4 ++++ + +Finally, we can remove both records and tables as part of the delete in CRUD. Let's dive back into the grocery store rewards program to learn how to do so! Removing any data in SQL Server is a permanent change and the data cannot be recovered so practice is key! + +## Delete a Row + +`DELETE` statements include a `WHERE` clause so that we can specify what condition must be met in the data we want to remove. + +```sql +DELETE FROM schema_name.table_name WHERE condition met; +``` + +In the case of the rewards program, we have learned that clear Pepsi was discontinued and we need to remove the record for used coupons for that product from our table. Clear Pepsi has a `CouponID` of 13, so we would write our query like so: + +```sql +DELETE FROM rewards.used_coupons WHERE CouponID = 13; +``` + +Typically, when you write a query like this, SQL Server will output how many rows were affected. If you want to run a check before you delete records from the table, you could use your aggregate functions to see how many rows *should* be affected and compare the two numbers upon deletion to make sure that all rows were removed. + +## Delete a Table + +If we ever got rid of the app and wanted to remove all records of in-app coupon usage, we could run the following query: + +```sql {linenos=table} +DROP TABLE rewards.used_coupons +``` + +When dropping tables, we want to ensure that we don't have any existing connections to other tables. If `UsedCouponID` is used as a foreign key in another table, we would need to first sever that connection before we can drop a table. + +{{% notice blue Note %}} + +If you are curious on how to get rid of a foreign key referencing a table you want to drop, you should check out this [article](https://www.w3schools.com/sql/sql_ref_drop_constraint.asp) on `DROP CONSTRAINT`. + +{{% /notice %}} + +## Check Your Understanding + +{{% notice green Question %}} + +Write a query to delete any records with a `Description` of Frozen from the `Recipes` table below. + +![Recipes table with four rows](./pictures/recipesTable3.png) + +{{% /notice %}} + +{{% notice green Question %}} + +Write a query to clear all the contents of the `Recipes` table. + +{{% /notice %}} + +{{% notice green Question %}} + +Which of the following queries will delete the entire `Recipes` table? + +1. `DROP TABLE schema_name.Recipes;` +1. `REMOVE TABLE schema_name.Recipes;` +1. `FROM schema_name DROP TABLE Recipes;` +1. `DELETE TABLE schema_name.Recipes;` + +{{% /notice %}} \ No newline at end of file diff --git a/content/sql-part-5/reading/delete/pictures/recipesTable3.png b/content/sql-part-5/reading/delete/pictures/recipesTable3.png new file mode 100644 index 00000000..8852e16e Binary files /dev/null and b/content/sql-part-5/reading/delete/pictures/recipesTable3.png differ diff --git a/content/sql-part-5/reading/schemas/_index.md b/content/sql-part-5/reading/schemas/_index.md new file mode 100644 index 00000000..d5cb3680 --- /dev/null +++ b/content/sql-part-5/reading/schemas/_index.md @@ -0,0 +1,24 @@ ++++ +title = "Schemas" +draft = false +weight = 1 ++++ + +Before we can dive into the queries, we need to talk about schemas. + +A **schema** is a way to group database objects(tables, views, ect) into a logical collection. +Let's look at the `AdventureWorks2019` database in Azure Data Studio. + +In the Object Explorer, if you expand the tables, you will see something like this: + +![File Tree, Tables Folder with Human Resources schemes highlighted](./pictures/TableSchemas.png) + +Notice how the tables are grouped together. The syntax is `schema_name.table_name`. +You wouldn't want someone accidentally deleting a table or being able to view sensitive information. +Schemas allow companies to easily control who has access to specific tables and how they have access. + +Another way to think of schemas is that they are like using folders on your Google Drive. +You can group together like-documents and control who has access by granting different permissions to different people. +At any time you can also change permissions or remove someone from having access. You can also move documents from one folder to another. +Multiple people can work together in each folder. The creator of the folder or document is the owner. +But, you can easily reassign the ownership to another person. The same is true of schemas. diff --git a/content/sql-part-5/reading/schemas/pictures/TableSchemas.png b/content/sql-part-5/reading/schemas/pictures/TableSchemas.png new file mode 100644 index 00000000..b60a5a38 Binary files /dev/null and b/content/sql-part-5/reading/schemas/pictures/TableSchemas.png differ diff --git a/content/sql-part-5/reading/update/_index.md b/content/sql-part-5/reading/update/_index.md new file mode 100644 index 00000000..6b4a4bd4 --- /dev/null +++ b/content/sql-part-5/reading/update/_index.md @@ -0,0 +1,35 @@ ++++ +title = "Update" +draft = false +weight = 3 ++++ + +With our tables made and filled with lots of data, we can update records within a table using this general syntax. + +```sql {linenos=table} +UPDATE schema_name.table_name +SET Column = NewValue +WHERE condition met; +``` + +The `UPDATE` statement allows us to specify what the new value for a column should be as long as a certain condition is met. That's see how this could work with our employer's rewards program. + +Now that we have set up a table for the coupons used by our app consumers, we may want to edit something. We have a record for a coupon for 50 cents off a package of Del Monte corn. Now when the record was created, the `Category` value was set to `'Frozen Foods'`. Upon an audit of our data, we have discovered that the coupon was not for Del Monte *frozen* corn, but for Del Monte *canned* corn. Using an `UPDATE` statement, we can change the value of `Category` to what it should be. + +```sql {linenos=table} +UPDATE rewards.used_coupons +SET Category='canned goods' +WHERE CouponID = 143; +``` + +Now the value of `Category` is changed for all records where the `CouponID` value is 146. + +## ChecK Your Understanding + +{{% notice green Question %}} + +Write a query to update the second recipe's `Instructions` to call Dominos instead in the `Recipes` table below. + +![Recipes table with three rows](./pictures/recipesTable2.png) + +{{% /notice %}} diff --git a/content/sql-part-5/reading/update/pictures/recipesTable2.png b/content/sql-part-5/reading/update/pictures/recipesTable2.png new file mode 100644 index 00000000..cba28365 Binary files /dev/null and b/content/sql-part-5/reading/update/pictures/recipesTable2.png differ diff --git a/content/sql-part-5/studio/_index.md b/content/sql-part-5/studio/_index.md new file mode 100644 index 00000000..f8276b88 --- /dev/null +++ b/content/sql-part-5/studio/_index.md @@ -0,0 +1,16 @@ ++++ +title = "Studio: Schemas and CRUD Operations" +date = 2021-10-01T09:28:27-05:00 +draft = false +weight = 3 ++++ + +## Getting Started + +For this week's studio, open up the `SQL-Part-5-Studio.ipynb` notebook in `data-analysis-projects/sql-part-5/studio`. You will need some starter data as you work which is all in the `data` directory within the `studio` directory. + +## Submitting Your Work + +When finished make sure to push your changes up to GitHub. + +Copy the link to your GitHub repository and paste it into the submission box in Canvas for **Studio: SQL Part 5** and click *Submit*.