From 749454d815c105c5fdff7939303d680074ae1e9a Mon Sep 17 00:00:00 2001 From: Software Shinobi Date: Fri, 14 Mar 2025 16:46:19 -0400 Subject: [PATCH] automated terminal push --- .dockerignore | 15 + .gitignore | 713 ++++++++++ Dockerfile | 3 + Jenkinsfile | 75 + compose.bash | 19 + compose.yaml | 72 + datasets/local-real-estate.sql | 320 +++++ datasets/mega-mart-grocery.sql | 1236 +++++++++++++++++ datasets/monaco-motors-dealership.sql | 381 +++++ datasets/user-readonly-create.sql | 4 + datasets/user-shinobi-create.sql | 4 + docs/Dockerfile | 15 + docs/compose.bash | 19 + docs/compose.yaml | 18 + docs/docs/.recycle/.gemini.md | 419 ++++++ docs/docs/.recycle/sql-101.md | 40 + .../004-basic-syntax.md | 145 ++ .../Introduction-To-Databases/005-select.md | 359 +++++ .../Introduction-To-Databases/006-where.md | 225 +++ .../007-order-and-group-by.md | 143 ++ .../Introduction-To-Databases/008-insert.md | 86 ++ .../Introduction-To-Databases/009-update.md | 106 ++ .../Introduction-To-Databases/010-delete.md | 41 + .../Introduction-To-Databases/011-join.md | 370 +++++ .../012-sql-commnad-categories.md | 121 ++ .../013-sub-queries.md | 112 ++ .../Introduction-To-Databases/014-unions.md | 124 ++ .../015-Keys-in-a-Relational Database.md | 51 + .../016-Logical-operator-keywords.md | 17 + .../017-having-clause_aggregate-functions.md | 186 +++ .../018-essential-mysql-functions.md | 191 +++ .../020-TCL-commands.md | 154 ++ docs/docs/Introduction-To-Databases/index.md | 39 + docs/docs/cover.png | Bin 0 -> 159918 bytes docs/docs/index.md | 77 + docs/docs/schema.md | 138 ++ docs/docs/styling.css | 49 + docs/mkdocs.bash | 21 + docs/mkdocs.yml | 41 + docs/provision.bash | 21 + LICENSE => license.md | 0 readme.md | 77 + 42 files changed, 6247 insertions(+) create mode 100755 .dockerignore create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 Jenkinsfile create mode 100755 compose.bash create mode 100644 compose.yaml create mode 100644 datasets/local-real-estate.sql create mode 100644 datasets/mega-mart-grocery.sql create mode 100644 datasets/monaco-motors-dealership.sql create mode 100644 datasets/user-readonly-create.sql create mode 100644 datasets/user-shinobi-create.sql create mode 100644 docs/Dockerfile create mode 100755 docs/compose.bash create mode 100644 docs/compose.yaml create mode 100644 docs/docs/.recycle/.gemini.md create mode 100644 docs/docs/.recycle/sql-101.md create mode 100644 docs/docs/Introduction-To-Databases/004-basic-syntax.md create mode 100644 docs/docs/Introduction-To-Databases/005-select.md create mode 100644 docs/docs/Introduction-To-Databases/006-where.md create mode 100644 docs/docs/Introduction-To-Databases/007-order-and-group-by.md create mode 100644 docs/docs/Introduction-To-Databases/008-insert.md create mode 100644 docs/docs/Introduction-To-Databases/009-update.md create mode 100644 docs/docs/Introduction-To-Databases/010-delete.md create mode 100644 docs/docs/Introduction-To-Databases/011-join.md create mode 100644 docs/docs/Introduction-To-Databases/012-sql-commnad-categories.md create mode 100644 docs/docs/Introduction-To-Databases/013-sub-queries.md create mode 100644 docs/docs/Introduction-To-Databases/014-unions.md create mode 100644 docs/docs/Introduction-To-Databases/015-Keys-in-a-Relational Database.md create mode 100644 docs/docs/Introduction-To-Databases/016-Logical-operator-keywords.md create mode 100644 docs/docs/Introduction-To-Databases/017-having-clause_aggregate-functions.md create mode 100644 docs/docs/Introduction-To-Databases/018-essential-mysql-functions.md create mode 100644 docs/docs/Introduction-To-Databases/020-TCL-commands.md create mode 100644 docs/docs/Introduction-To-Databases/index.md create mode 100644 docs/docs/cover.png create mode 100644 docs/docs/index.md create mode 100644 docs/docs/schema.md create mode 100644 docs/docs/styling.css create mode 100755 docs/mkdocs.bash create mode 100644 docs/mkdocs.yml create mode 100755 docs/provision.bash rename LICENSE => license.md (100%) create mode 100644 readme.md diff --git a/.dockerignore b/.dockerignore new file mode 100755 index 0000000..e33615a --- /dev/null +++ b/.dockerignore @@ -0,0 +1,15 @@ + +*.md + +*.log + +LICENSE + +.dockerignore + +.git* + +.recycle + +.trash + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7126641 --- /dev/null +++ b/.gitignore @@ -0,0 +1,713 @@ +# ---> Java +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +replay_pid* + +# ---> Node +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp +.cache + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + +# ---> Windows +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# ---> Linux +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +# ---> macOS +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# ---> Eclipse +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.settings/ +.loadpath +.recommenders + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# PyDev specific (Python IDE for Eclipse) +*.pydevproject + +# CDT-specific (C/C++ Development Tooling) +.cproject + +# CDT- autotools +.autotools + +# Java annotation processor (APT) +.factorypath + +# PDT-specific (PHP Development Tools) +.buildpath + +# sbteclipse plugin +.target + +# Tern plugin +.tern-project + +# TeXlipse plugin +.texlipse + +# STS (Spring Tool Suite) +.springBeans + +# Code Recommenders +.recommenders/ + +# Annotation Processing +.apt_generated/ +.apt_generated_test/ + +# Scala IDE specific (Scala & Java development for Eclipse) +.cache-main +.scala_dependencies +.worksheet + +# Uncomment this line if you wish to ignore the project description file. +# Typically, this file would be tracked if it contains build/dependency configurations: +#.project + +# ---> NetBeans +**/nbproject/private/ +**/nbproject/Makefile-*.mk +**/nbproject/Package-*.bash +build/ +nbbuild/ +dist/ +nbdist/ +.nb-gradle/ + +# ---> VisualStudio +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files +*.ncb +*.aps + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +*.sln.iml + +# ---> VisualStudioCode +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..32496e9 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,3 @@ +FROM mariadb + +ADD datasets/ /docker-entrypoint-initdb.d diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..691ebed --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,75 @@ +pipeline { + + agent none + + options { + + disableConcurrentBuilds(abortPrevious: true) + + buildDiscarder(logRotator(numToKeepStr: '1')) + } + + stages { + + stage('docker compose build') { + + agent { + + label "aventador" + + } + + steps { + + dir('.') { + + sh 'docker compose build' + + } + + } + + } + + stage('docker compose push') { + + agent { + + label "aventador" + + } + + steps { + + dir('.') { + + sh 'docker compose push' + + } + + } + + } + + stage('prune') { + + agent { + + label "aventador" + + } + + steps { + + dir('.') { + + sh 'docker system prune -a -f' + + } + + } + + } + +}} + diff --git a/compose.bash b/compose.bash new file mode 100755 index 0000000..b72ea5d --- /dev/null +++ b/compose.bash @@ -0,0 +1,19 @@ +#!/bin/bash + +## + +reset; + +clear; + +## + +set -e; + +set -x; + +## + +docker compose down --remove-orphans + +docker compose up --build -d diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 0000000..7e8f89f --- /dev/null +++ b/compose.yaml @@ -0,0 +1,72 @@ + +services: + + shinobi-academy-database-server: + + container_name: shinobi-academy-database-server + + image: softwareshinobi/shinobi-academy-database-server + + build: + + context: . + + dockerfile: Dockerfile + + restart: unless-stopped + + ports: + + - 3306:3306 + + volumes: + + - /tmp/volumes/academy/database:/var/lib/mysql + + environment: + + MYSQL_ROOT_PASSWORD: aggiepride + + MYSQL_DATABASE: sandbox + + MYSQL_USER: sandbox + + MYSQL_PASSWORD: sandbox + + shinobi-academy-database-admin: + + container_name: shinobi-academy-database-admin + + image: beeyev/phpmyadmin-lightweight + + restart: unless-stopped + + depends_on: + + - shinobi-academy-database-server + + ports: + + - 3380:80 + + environment: + + PMA_HOST: shinobi-academy-database-server + + MYSQL_ROOT_PASSWORD: aggiepride + + shinobi-academy-database-docs: + + container_name: shinobi-academy-database-docs + + image: softwareshinobi/shinobi-academy-database-docs + + build: + + context: docs + + dockerfile: Dockerfile + + ports: + + - 3388:80 diff --git a/datasets/local-real-estate.sql b/datasets/local-real-estate.sql new file mode 100644 index 0000000..10d7648 --- /dev/null +++ b/datasets/local-real-estate.sql @@ -0,0 +1,320 @@ +CREATE DATABASE `LOCAL_REAL_ESTATE` DEFAULT CHARACTER SET utf8mb4; + +USE `LOCAL_REAL_ESTATE`; + +/* create tables of attributes */ +CREATE TABLE Property( + address VARCHAR(50) NOT NULL, + ownerName VARCHAR(30), + price INT, + PRIMARY KEY(address) +); + +CREATE TABLE House( + address VARCHAR(50) NOT NULL, + ownerName VARCHAR(30), + price INT, + bedrooms INT, + bathrooms INT, + size INT, + FOREIGN KEY(address) REFERENCES Property(address) +); + +CREATE TABLE BusinessProperty( + address VARCHAR(50) NOT NULL, + ownerName VARCHAR(30), + price INT, + type CHAR(20), + size INT, + FOREIGN KEY(address) REFERENCES Property(address) +); + +CREATE TABLE Firm( + id INT NOT NULL, + name VARCHAR(30), + address VARCHAR(50), + PRIMARY KEY(id) +); + +CREATE TABLE Agent( + agentId INT NOT NULL, + name VARCHAR(30), + phone CHAR(12), + firmId INT NOT NULL, + dateStarted DATE, + PRIMARY KEY(agentId), + FOREIGN KEY(firmId) REFERENCES Firm(id) +); + +CREATE TABLE Listing( + address VARCHAR(50), + agentId INT, + mlsNumber INT PRIMARY KEY, + dataListed DATE, + FOREIGN KEY(agentId) REFERENCES Agent(agentId), + FOREIGN KEY(address) REFERENCES Property(address) +); + +CREATE TABLE Buyer( + id INT NOT NULL, + name VARCHAR(30), + phone CHAR(12), + propertyType CHAR(20), + bedrooms INT, + bathrooms INT, + businessPropertyType CHAR(20), + minimumPreferredPrice INT, + maximumPreferredPrice INT, + PRIMARY KEY(id) +); + +CREATE TABLE Work_With( + buyerId INT, + agentId INT, + FOREIGN KEY(buyerId) REFERENCES Buyer(id), + FOREIGN KEY(agentId) REFERENCES Agent(agentId) +); + +/* create an assertion */ +/* +CREATE ASSERTION PROPERTY_AGENT_PROJECTION CHECK + (NOT EXISTS + (SELECT L1.address + FROM Listings L1, Listings L2 + WHERE L1.address = L2.address AND L1.agentId != L2.agentId + ) + ); +*/ +/* insert records to each tables, each table has at least 5 records */ +/* 10 records into Property */ +INSERT INTO Property +VALUES('2350 Gibson Road', 'John Smith', 235000); + +INSERT INTO Property +VALUES('197 Watson Street', 'Raymond Chou', 789000); + +INSERT INTO Property +VALUES('2525 Pottsdamer Street', 'Jim Lee', 100500); + +INSERT INTO Property +VALUES('193 Love BLVD', 'Kim Abudal', 930000); + +INSERT INTO Property +VALUES('647 Maston Road', 'Robert Clue', 135000); + +INSERT INTO Property +VALUES('1350 Navada Street', 'Jack Green', 674090); + +INSERT INTO Property +VALUES('256 Florida Street', 'Michael Kohen', 179280); + +INSERT INTO Property +VALUES('1717 Kansas Street', 'Leah Mars', 345000); + +INSERT INTO Property +VALUES('2613 Academic Way', 'Marry Song', 997050); + +INSERT INTO Property +VALUES('179 Tinker Road', 'Leon Kant', 90000); + +/* 5 records into House */ +INSERT INTO House +VALUES('2350 Gibson Road', 'John Smith', 235000, 3, 2, 196); + +INSERT INTO House +VALUES('197 Watson Street', 'Raymond Chou', 789000, 2, 4, 203); + +INSERT INTO House +VALUES('2525 Pottsdamer Street', 'Jim Lee', 100500, 2, 3, 180); + +INSERT INTO House +VALUES('193 Love BLVD', 'Kim Abudal', 930000, 3, 2, 401); + +INSERT INTO House +VALUES('647 Maston Road', 'Robert Clue', 135000, 3, 2, 102); + +/* 5 records into BusinessProperty */ +INSERT INTO BusinessProperty +VALUES('1350 Navada Street', 'Jack Green', 674090, 'office space', 467); + +INSERT INTO BusinessProperty +VALUES('256 Florida Street', 'Michael Kohen', 179280, 'gas station', 245); + +INSERT INTO BusinessProperty +VALUES('1717 Kansas Street', 'Leah Mars', 345000, 'office space', 356); + +INSERT INTO BusinessProperty +VALUES('2613 Academic Way', 'Marry Song', 997050, 'office space', 670); + +INSERT INTO BusinessProperty +VALUES('179 Tinker Road', 'Leon Kant', 90000, 'store front', 128); + +/* 5 records into Firm */ +INSERT INTO Firm +VALUES(135210, 'Goldman Sash', '799 Georgia Way'); + +INSERT INTO Firm +VALUES(146277, 'Holloway', '124 Texas Street'); + +INSERT INTO Firm +VALUES(165034, 'Good Target', '135 California Street'); + +INSERT INTO Firm +VALUES(230754, 'Cozy Home', '277 Beach Road'); + +INSERT INTO Firm +VALUES(210211, 'Fast Searcher', '1010 Alas Road'); + +/* 10 records into Agent */ +INSERT INTO Agent +VALUES(100, 'Leet Kim', '135145636', 210211, '2012-01-23'); + +INSERT INTO Agent +VALUES(112, 'Jim Alpha', '171135636', 210211, '2012-03-26'); + +INSERT INTO Agent +VALUES(123, 'George Grey', '176321636', 135210, '2015-02-23'); + +INSERT INTO Agent +VALUES(145, 'Sarah Core', '135145909', 135210, '2016-07-03'); + +INSERT INTO Agent +VALUES(168, 'Livia Watson', '137145638', 146277, '2014-01-17'); + +INSERT INTO Agent +VALUES(189, 'Nik Ray', '135873630', 146277, '2014-01-28'); + +INSERT INTO Agent +VALUES(201, 'Cris Paul', '136141236', 165034, '2016-05-23'); + +INSERT INTO Agent +VALUES(223, 'Lena Clay', '137145123', 165034, '2014-08-19'); + +INSERT INTO Agent +VALUES(267, 'Kevin Nil', '190145636', 230754, '2011-07-20'); + +INSERT INTO Agent +VALUES(310, 'Hugh Grant', '132145639', 230754, '2012-12-31'); + +/* 10 records into Listing */ +INSERT INTO Listing +VALUES('2350 Gibson Road', 100, 1212, '2013-02-04'); + +INSERT INTO Listing +VALUES('197 Watson Street', 112, 1500, '2013-05-06'); + +INSERT INTO Listing +VALUES('2525 Pottsdamer Street', 123, 1617, '2016-12-04'); + +INSERT INTO Listing +VALUES('193 Love BLVD', 145, 1718, '2016-02-09'); + +INSERT INTO Listing +VALUES('647 Maston Road', 168, 1900, '2014-12-19'); + +INSERT INTO Listing +VALUES('1350 Navada Street', 189, 2101, '2015-06-06'); + +INSERT INTO Listing +VALUES('256 Florida Street', 201, 2305, '2017-05-25'); + +INSERT INTO Listing +VALUES('1717 Kansas Street', 223, 2500, '2014-12-04'); + +INSERT INTO Listing +VALUES('2613 Academic Way', 267, 2790, '2013-10-01'); + +INSERT INTO Listing +VALUES('179 Tinker Road', 310, 3001, '2015-09-05'); + +/* 6 records into Buyer */ +INSERT INTO Buyer +VALUES(799, 'John Nay', '125345790', 'house', 3, 2, 'not applied', 100000, 635000); + +INSERT INTO Buyer +VALUES(801, 'Retina Grey', '146345790', 'house', 3, 2, 'not applied', 100000, 400000); + +INSERT INTO Buyer +VALUES(813, 'Reg Neal', '189345791', 'house', 2, 3, 'not applied', 300000, 635000); + +INSERT INTO Buyer +VALUES(845, 'Gena Sarah', '789345790', 'house', 3, 2, 'not applied', 200000, 960000); + +INSERT INTO Buyer +VALUES(875, 'Bill Clay', '888345798', 'not applied', 0, 0, 'office space', 100000, 900000); + +INSERT INTO Buyer +VALUES(999, 'Hilton Clag', '999345792', 'not applied', 0, 0, 'office space', 300000, 790000); + +/* 6 records into Works_With */ +INSERT INTO Work_With +VALUES(799, 100); + +INSERT INTO Work_With +VALUES(801, 145); + +INSERT INTO Work_With +VALUES(813, 123); + +INSERT INTO Work_With +VALUES(845, 168); + +INSERT INTO Work_With +VALUES(875, 189); + +INSERT INTO Work_With +VALUES(999, 223); + +/* queries */ +/* 1st query */ +SELECT Listing.address +FROM Listing, House +WHERE Listing.address = House.address; + +/* 2nd query */ +SELECT Listing.address, Listing.mlsNumber +FROM Listing, House +WHERE Listing.address = House.address; + +/* 3rd query */ +SELECT Listing.address +FROM Listing, House +WHERE Listing.address = House.address AND House.bedrooms = 3 AND House.bathrooms = 2; + +/* 4th query */ +SELECT address, price +FROM House +WHERE bedrooms = 3 AND bathrooms = 2 AND price >= 100000 AND price <= 250000 +ORDER BY price DESC; + +/* 5th query */ +SELECT address, price +FROM BusinessProperty +WHERE type = 'office space' +ORDER BY price DESC; + +/* 6th query */ +SELECT agentId, Agent.name, phone, Firm.name, dateStarted +FROM Agent, Firm +WHERE Agent.firmId = Firm.id; + +/* 7th query, agentId is indicated as 201 here */ +SELECT Property.* +FROM Property, Listing +WHERE Property.address = Listing.address AND Listing.agentId = 201; + +/* 8th query */ +SELECT Agent.name AS Agent_Name, Buyer.name AS Buyer_Name +FROM Agent, Buyer, Work_With +WHERE Agent.agentId = Work_With.agentId AND Buyer.id = Work_With.buyerId; + +/* 9th query, suppose the buyer's Id is 799 in our case */ +SELECT House.* +FROM House, Buyer +WHERE Buyer.id = 799 AND + Buyer.bedrooms = House.bedrooms AND + Buyer.bathrooms = House.bathrooms AND + Buyer.minimumPreferredPrice <= House.price AND + Buyer.maximumPreferredPrice >= House.price; + +/* the end of program */ diff --git a/datasets/mega-mart-grocery.sql b/datasets/mega-mart-grocery.sql new file mode 100644 index 0000000..67dd202 --- /dev/null +++ b/datasets/mega-mart-grocery.sql @@ -0,0 +1,1236 @@ +-- +-- Database: `MEGAMART` +-- +CREATE DATABASE IF NOT EXISTS `MEGA_MART_GROCERY` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_uca1400_ai_ci; +USE `MEGA_MART_GROCERY`; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `Categories` +-- + +CREATE TABLE `Categories` ( + `CategoryID` int(11) NOT NULL, + `CategoryName` varchar(25) DEFAULT NULL, + `Description` varchar(255) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci; + +-- +-- Dumping data for table `Categories` +-- + +INSERT INTO `Categories` (`CategoryID`, `CategoryName`, `Description`) VALUES +(1, 'Beverages', 'Soft drinks, coffees, teas, beers, and ales'), +(2, 'Condiments', 'Sweet and savory sauces, relishes, spreads, and seasonings'), +(3, 'Confections', 'Desserts, candies, and sweet breads'), +(4, 'Dairy Products', 'Cheeses'), +(5, 'Grains/Cereals', 'Breads, crackers, pasta, and cereal'), +(6, 'Meat/Poultry', 'Prepared meats'), +(7, 'Produce', 'Dried fruit and bean curd'), +(8, 'Seafood', 'Seaweed and fish'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `Customers` +-- + +CREATE TABLE `Customers` ( + `CustomerID` int(11) NOT NULL, + `CustomerName` varchar(50) DEFAULT NULL, + `ContactName` varchar(50) DEFAULT NULL, + `Address` varchar(50) DEFAULT NULL, + `City` varchar(20) DEFAULT NULL, + `PostalCode` varchar(10) DEFAULT NULL, + `Country` varchar(15) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci; + +-- +-- Dumping data for table `Customers` +-- + +INSERT INTO `Customers` (`CustomerID`, `CustomerName`, `ContactName`, `Address`, `City`, `PostalCode`, `Country`) VALUES +(1, 'Alfreds Futterkiste', 'Maria Anders', 'Obere Str. 57', 'Berlin', '12209', 'Germany'), +(2, 'Ana Trujillo Emparedados y helados', 'Ana Trujillo', 'Avda. de la Constitución 2222', 'México D.F.', '5021', 'Mexico'), +(3, 'Antonio Moreno Taquería', 'Antonio Moreno', 'Mataderos 2312', 'México D.F.', '5023', 'Mexico'), +(4, 'Around the Horn', 'Thomas Hardy', '120 Hanover Sq.', 'London', 'WA1 1DP', 'UK'), +(5, 'Berglunds snabbköp', 'Christina Berglund', 'Berguvsvägen 8', 'Luleå', 'S-958 22', 'Sweden'), +(6, 'Blauer See Delikatessen', 'Hanna Moos', 'Forsterstr. 57', 'Mannheim', '68306', 'Germany'), +(7, 'Blondel père et fils', 'Frédérique Citeaux', '24, place Kléber', 'Strasbourg', '67000', 'France'), +(8, 'Bólido Comidas preparadas', 'Martín Sommer', 'C/ Araquil, 67', 'Madrid', '28023', 'Spain'), +(9, 'Bon app\'\'', 'Laurence Lebihans', '12, rue des Bouchers', 'Marseille', '13008', 'France'), +(10, 'Bottom-Dollar Marketse', 'Elizabeth Lincoln', '23 Tsawassen Blvd.', 'Tsawassen', 'T2F 8M4', 'Canada'), +(11, 'B\'\'s Beverages', 'Victoria Ashworth', 'Fauntleroy Circus', 'London', 'EC2 5NT', 'UK'), +(12, 'Cactus Comidas para llevar', 'Patricio Simpson', 'Cerrito 333', 'Buenos Aires', '1010', 'Argentina'), +(13, 'Centro comercial Moctezuma', 'Francisco Chang', 'Sierras de Granada 9993', 'México D.F.', '5022', 'Mexico'), +(14, 'Chop-suey Chinese', 'Yang Wang', 'Hauptstr. 29', 'Bern', '3012', 'Switzerland'), +(15, 'Comércio Mineiro', 'Pedro Afonso', 'Av. dos Lusíadas, 23', 'São Paulo', '05432-043', 'Brazil'), +(16, 'Consolidated Holdings', 'Elizabeth Brown', 'Berkeley Gardens 12 Brewery', 'London', 'WX1 6LT', 'UK'), +(17, 'Drachenblut Delikatessend', 'Sven Ottlieb', 'Walserweg 21', 'Aachen', '52066', 'Germany'), +(18, 'Du monde entier', 'Janine Labrune', '67, rue des Cinquante Otages', 'Nantes', '44000', 'France'), +(19, 'Eastern Connection', 'Ann Devon', '35 King George', 'London', 'WX3 6FW', 'UK'), +(20, 'Ernst Handel', 'Roland Mendel', 'Kirchgasse 6', 'Graz', '8010', 'Austria'), +(21, 'Familia Arquibaldo', 'Aria Cruz', 'Rua Orós, 92', 'São Paulo', '05442-030', 'Brazil'), +(22, 'FISSA Fabrica Inter. Salchichas S.A.', 'Diego Roel', 'C/ Moralzarzal, 86', 'Madrid', '28034', 'Spain'), +(23, 'Folies gourmandes', 'Martine Rancé', '184, chaussée de Tournai', 'Lille', '59000', 'France'), +(24, 'Folk och fä HB', 'Maria Larsson', 'Åkergatan 24', 'Bräcke', 'S-844 67', 'Sweden'), +(25, 'Frankenversand', 'Peter Franken', 'Berliner Platz 43', 'München', '80805', 'Germany'), +(26, 'France restauration', 'Carine Schmitt', '54, rue Royale', 'Nantes', '44000', 'France'), +(27, 'Franchi S.p.A.', 'Paolo Accorti', 'Via Monte Bianco 34', 'Torino', '10100', 'Italy'), +(28, 'Furia Bacalhau e Frutos do Mar', 'Lino Rodriguez', 'Jardim das rosas n. 32', 'Lisboa', '1675', 'Portugal'), +(29, 'Galería del gastrónomo', 'Eduardo Saavedra', 'Rambla de Cataluña, 23', 'Barcelona', '8022', 'Spain'), +(30, 'Godos Cocina Típica', 'José Pedro Freyre', 'C/ Romero, 33', 'Sevilla', '41101', 'Spain'), +(31, 'Gourmet Lanchonetes', 'André Fonseca', 'Av. Brasil, 442', 'Campinas', '04876-786', 'Brazil'), +(32, 'Great Lakes Food Market', 'Howard Snyder', '2732 Baker Blvd.', 'Eugene', '97403', 'USA'), +(33, 'GROSELLA-Restaurante', 'Manuel Pereira', '5ª Ave. Los Palos Grandes', 'Caracas', '1081', 'Venezuela'), +(34, 'Hanari Carnes', 'Mario Pontes', 'Rua do Paço, 67', 'Rio de Janeiro', '05454-876', 'Brazil'), +(35, 'HILARIÓN-Abastos', 'Carlos Hernández', 'Carrera 22 con Ave. Carlos Soublette #8-35', 'San Cristóbal', '5022', 'Venezuela'), +(36, 'Hungry Coyote Import Store', 'Yoshi Latimer', 'City Center Plaza 516 Main St.', 'Elgin', '97827', 'USA'), +(37, 'Hungry Owl All-Night Grocers', 'Patricia McKenna', '8 Johnstown Road', 'Cork', '', 'Ireland'), +(38, 'Island Trading', 'Helen Bennett', 'Garden House Crowther Way', 'Cowes', 'PO31 7PJ', 'UK'), +(39, 'Königlich Essen', 'Philip Cramer', 'Maubelstr. 90', 'Brandenburg', '14776', 'Germany'), +(40, 'La corne d\'\'abondance', 'Daniel Tonini', '67, avenue de l\'\'Europe', 'Versailles', '78000', 'France'), +(41, 'La maison d\'\'Asie', 'Annette Roulet', '1 rue Alsace-Lorraine', 'Toulouse', '31000', 'France'), +(42, 'Laughing Bacchus Wine Cellars', 'Yoshi Tannamuri', '1900 Oak St.', 'Vancouver', 'V3F 2K1', 'Canada'), +(43, 'Lazy K Kountry Store', 'John Steel', '12 Orchestra Terrace', 'Walla Walla', '99362', 'USA'), +(44, 'Lehmanns Marktstand', 'Renate Messner', 'Magazinweg 7', 'Frankfurt a.M.', '60528', 'Germany'), +(45, 'Let\'\'s Stop N Shop', 'Jaime Yorres', '87 Polk St. Suite 5', 'San Francisco', '94117', 'USA'), +(46, 'LILA-Supermercado', 'Carlos González', 'Carrera 52 con Ave. Bolívar #65-98 Llano Largo', 'Barquisimeto', '3508', 'Venezuela'), +(47, 'LINO-Delicateses', 'Felipe Izquierdo', 'Ave. 5 de Mayo Porlamar', 'I. de Margarita', '4980', 'Venezuela'), +(48, 'Lonesome Pine Restaurant', 'Fran Wilson', '89 Chiaroscuro Rd.', 'Portland', '97219', 'USA'), +(49, 'Magazzini Alimentari Riuniti', 'Giovanni Rovelli', 'Via Ludovico il Moro 22', 'Bergamo', '24100', 'Italy'), +(50, 'Maison Dewey', 'Catherine Dewey', 'Rue Joseph-Bens 532', 'Bruxelles', 'B-1180', 'Belgium'), +(51, 'Mère Paillarde', 'Jean Fresnière', '43 rue St. Laurent', 'Montréal', 'H1J 1C3', 'Canada'), +(52, 'Morgenstern Gesundkost', 'Alexander Feuer', 'Heerstr. 22', 'Leipzig', '4179', 'Germany'), +(53, 'North/South', 'Simon Crowther', 'South House 300 Queensbridge', 'London', 'SW7 1RZ', 'UK'), +(54, 'Océano Atlántico Ltda.', 'Yvonne Moncada', 'Ing. Gustavo Moncada 8585 Piso 20-A', 'Buenos Aires', '1010', 'Argentina'), +(55, 'Old World Delicatessen', 'Rene Phillips', '2743 Bering St.', 'Anchorage', '99508', 'USA'), +(56, 'Ottilies Käseladen', 'Henriette Pfalzheim', 'Mehrheimerstr. 369', 'Köln', '50739', 'Germany'), +(57, 'Paris spécialités', 'Marie Bertrand', '265, boulevard Charonne', 'Paris', '75012', 'France'), +(58, 'Pericles Comidas clásicas', 'Guillermo Fernández', 'Calle Dr. Jorge Cash 321', 'México D.F.', '5033', 'Mexico'), +(59, 'Piccolo und mehr', 'Georg Pipps', 'Geislweg 14', 'Salzburg', '5020', 'Austria'), +(60, 'Princesa Isabel Vinhoss', 'Isabel de Castro', 'Estrada da saúde n. 58', 'Lisboa', '1756', 'Portugal'), +(61, 'Que Delícia', 'Bernardo Batista', 'Rua da Panificadora, 12', 'Rio de Janeiro', '02389-673', 'Brazil'), +(62, 'Queen Cozinha', 'Lúcia Carvalho', 'Alameda dos Canàrios, 891', 'São Paulo', '05487-020', 'Brazil'), +(63, 'QUICK-Stop', 'Horst Kloss', 'Taucherstraße 10', 'Cunewalde', '1307', 'Germany'), +(64, 'Rancho grande', 'Sergio Gutiérrez', 'Av. del Libertador 900', 'Buenos Aires', '1010', 'Argentina'), +(65, 'Rattlesnake Canyon Grocery', 'Paula Wilson', '2817 Milton Dr.', 'Albuquerque', '87110', 'USA'), +(66, 'Reggiani Caseifici', 'Maurizio Moroni', 'Strada Provinciale 124', 'Reggio Emilia', '42100', 'Italy'), +(67, 'Ricardo Adocicados', 'Janete Limeira', 'Av. Copacabana, 267', 'Rio de Janeiro', '02389-890', 'Brazil'), +(68, 'Richter Supermarkt', 'Michael Holz', 'Grenzacherweg 237', 'Genève', '1203', 'Switzerland'), +(69, 'Romero y tomillo', 'Alejandra Camino', 'Gran Vía, 1', 'Madrid', '28001', 'Spain'), +(70, 'Santé Gourmet', 'Jonas Bergulfsen', 'Erling Skakkes gate 78', 'Stavern', '4110', 'Norway'), +(71, 'Save-a-lot Markets', 'Jose Pavarotti', '187 Suffolk Ln.', 'Boise', '83720', 'USA'), +(72, 'Seven Seas Imports', 'Hari Kumar', '90 Wadhurst Rd.', 'London', 'OX15 4NB', 'UK'), +(73, 'Simons bistro', 'Jytte Petersen', 'Vinbæltet 34', 'København', '1734', 'Denmark'), +(74, 'Spécialités du monde', 'Dominique Perrier', '25, rue Lauriston', 'Paris', '75016', 'France'), +(75, 'Split Rail Beer & Ale', 'Art Braunschweiger', 'P.O. Box 555', 'Lander', '82520', 'USA'), +(76, 'Suprêmes délices', 'Pascale Cartrain', 'Boulevard Tirou, 255', 'Charleroi', 'B-6000', 'Belgium'), +(77, 'The Big Cheese', 'Liz Nixon', '89 Jefferson Way Suite 2', 'Portland', '97201', 'USA'), +(78, 'The Cracker Box', 'Liu Wong', '55 Grizzly Peak Rd.', 'Butte', '59801', 'USA'), +(79, 'Toms Spezialitäten', 'Karin Josephs', 'Luisenstr. 48', 'Münster', '44087', 'Germany'), +(80, 'Tortuga Restaurante', 'Miguel Angel Paolino', 'Avda. Azteca 123', 'México D.F.', '5033', 'Mexico'), +(81, 'Tradição Hipermercados', 'Anabela Domingues', 'Av. Inês de Castro, 414', 'São Paulo', '05634-030', 'Brazil'), +(82, 'Trail\'\'s Head Gourmet Provisioners', 'Helvetius Nagy', '722 DaVinci Blvd.', 'Kirkland', '98034', 'USA'), +(83, 'Vaffeljernet', 'Palle Ibsen', 'Smagsløget 45', 'Århus', '8200', 'Denmark'), +(84, 'Victuailles en stock', 'Mary Saveley', '2, rue du Commerce', 'Lyon', '69004', 'France'), +(85, 'Vins et alcools Chevalier', 'Paul Henriot', '59 rue de l\'\'Abbaye', 'Reims', '51100', 'France'), +(86, 'Die Wandernde Kuh', 'Rita Müller', 'Adenauerallee 900', 'Stuttgart', '70563', 'Germany'), +(87, 'Wartian Herkku', 'Pirkko Koskitalo', 'Torikatu 38', 'Oulu', '90110', 'Finland'), +(88, 'Wellington Importadora', 'Paula Parente', 'Rua do Mercado, 12', 'Resende', '08737-363', 'Brazil'), +(89, 'White Clover Markets', 'Karl Jablonski', '305 - 14th Ave. S. Suite 3B', 'Seattle', '98128', 'USA'), +(90, 'Wilman Kala', 'Matti Karttunen', 'Keskuskatu 45', 'Helsinki', '21240', 'Finland'), +(91, 'Wolski', 'Zbyszek', 'ul. Filtrowa 68', 'Walla', '01-012', 'Poland'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `Employees` +-- + +CREATE TABLE `Employees` ( + `EmployeeID` int(11) NOT NULL, + `LastName` varchar(15) DEFAULT NULL, + `FirstName` varchar(15) DEFAULT NULL, + `BirthDate` datetime DEFAULT NULL, + `Photo` varchar(25) DEFAULT NULL, + `Notes` varchar(1024) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci; + +-- +-- Dumping data for table `Employees` +-- + +INSERT INTO `Employees` (`EmployeeID`, `LastName`, `FirstName`, `BirthDate`, `Photo`, `Notes`) VALUES +(1, 'Davolio', 'Nancy', '1968-12-08 00:00:00', 'EmpID1.pic', 'Education includes a BA in psychology from Colorado State University. She also completed (The Art of the Cold Call). Nancy is a member of \'Toastmasters International\'.'), +(2, 'Fuller', 'Andrew', '1952-02-19 00:00:00', 'EmpID2.pic', 'Andrew received his BTS commercial and a Ph.D. in international marketing from the University of Dallas. He is fluent in French and Italian and reads German. He joined the company as a sales representative, was promoted to sales manager and was then named vice president of sales. Andrew is a member of the Sales Management Roundtable, the Seattle Chamber of Commerce, and the Pacific Rim Importers Association.'), +(3, 'Leverling', 'Janet', '1963-08-30 00:00:00', 'EmpID3.pic', 'Janet has a BS degree in chemistry from Boston College). She has also completed a certificate program in food retailing management. Janet was hired as a sales associate and was promoted to sales representative.'), +(4, 'Peacock', 'Margaret', '1958-09-19 00:00:00', 'EmpID4.pic', 'Margaret holds a BA in English literature from Concordia College and an MA from the American Institute of Culinary Arts. She was temporarily assigned to the London office before returning to her permanent post in Seattle.'), +(5, 'Buchanan', 'Steven', '1955-03-04 00:00:00', 'EmpID5.pic', 'Steven Buchanan graduated from St. Andrews University, Scotland, with a BSC degree. Upon joining the company as a sales representative, he spent 6 months in an orientation program at the Seattle office and then returned to his permanent post in London, where he was promoted to sales manager. Mr. Buchanan has completed the courses \'Successful Telemarketing\' and \'International Sales Management\'. He is fluent in French.'), +(6, 'Suyama', 'Michael', '1963-07-02 00:00:00', 'EmpID6.pic', 'Michael is a graduate of Sussex University (MA, economics) and the University of California at Los Angeles (MBA, marketing). He has also taken the courses \'Multi-Cultural Selling\' and \'Time Management for the Sales Professional\'. He is fluent in Japanese and can read and write French, Portuguese, and Spanish.'), +(7, 'King', 'Robert', '1960-05-29 00:00:00', 'EmpID7.pic', 'Robert King served in the Peace Corps and traveled extensively before completing his degree in English at the University of Michigan and then joining the company. After completing a course entitled \'Selling in Europe\', he was transferred to the London office.'), +(8, 'Callahan', 'Laura', '1958-01-09 00:00:00', 'EmpID8.pic', 'Laura received a BA in psychology from the University of Washington. She has also completed a course in business French. She reads and writes French.'), +(9, 'Dodsworth', 'Anne', '1969-07-02 00:00:00', 'EmpID9.pic', 'Anne has a BA degree in English from St. Lawrence College. She is fluent in French and German.'), +(10, 'West', 'Adam', '1928-09-19 00:00:00', 'EmpID10.pic', 'An old chum.'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `OrderDetails` +-- + +CREATE TABLE `OrderDetails` ( + `OrderDetailID` int(11) NOT NULL, + `OrderID` int(11) DEFAULT NULL, + `ProductID` int(11) DEFAULT NULL, + `Quantity` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci; + +-- +-- Dumping data for table `OrderDetails` +-- + +INSERT INTO `OrderDetails` (`OrderDetailID`, `OrderID`, `ProductID`, `Quantity`) VALUES +(1, 10248, 11, 12), +(2, 10248, 42, 10), +(3, 10248, 72, 5), +(4, 10249, 14, 9), +(5, 10249, 51, 40), +(6, 10250, 41, 10), +(7, 10250, 51, 35), +(8, 10250, 65, 15), +(9, 10251, 22, 6), +(10, 10251, 57, 15), +(11, 10251, 65, 20), +(12, 10252, 20, 40), +(13, 10252, 33, 25), +(14, 10252, 60, 40), +(15, 10253, 31, 20), +(16, 10253, 39, 42), +(17, 10253, 49, 40), +(18, 10254, 24, 15), +(19, 10254, 55, 21), +(20, 10254, 74, 21), +(21, 10255, 2, 20), +(22, 10255, 16, 35), +(23, 10255, 36, 25), +(24, 10255, 59, 30), +(25, 10256, 53, 15), +(26, 10256, 77, 12), +(27, 10257, 27, 25), +(28, 10257, 39, 6), +(29, 10257, 77, 15), +(30, 10258, 2, 50), +(31, 10258, 5, 65), +(32, 10258, 32, 6), +(33, 10259, 21, 10), +(34, 10259, 37, 1), +(35, 10260, 41, 16), +(36, 10260, 57, 50), +(37, 10260, 62, 15), +(38, 10260, 70, 21), +(39, 10261, 21, 20), +(40, 10261, 35, 20), +(41, 10262, 5, 12), +(42, 10262, 7, 15), +(43, 10262, 56, 2), +(44, 10263, 16, 60), +(45, 10263, 24, 28), +(46, 10263, 30, 60), +(47, 10263, 74, 36), +(48, 10264, 2, 35), +(49, 10264, 41, 25), +(50, 10265, 17, 30), +(51, 10265, 70, 20), +(52, 10266, 12, 12), +(53, 10267, 40, 50), +(54, 10267, 59, 70), +(55, 10267, 76, 15), +(56, 10268, 29, 10), +(57, 10268, 72, 4), +(58, 10269, 33, 60), +(59, 10269, 72, 20), +(60, 10270, 36, 30), +(61, 10270, 43, 25), +(62, 10271, 33, 24), +(63, 10272, 20, 6), +(64, 10272, 31, 40), +(65, 10272, 72, 24), +(66, 10273, 10, 24), +(67, 10273, 31, 15), +(68, 10273, 33, 20), +(69, 10273, 40, 60), +(70, 10273, 76, 33), +(71, 10274, 71, 20), +(72, 10274, 72, 7), +(73, 10275, 24, 12), +(74, 10275, 59, 6), +(75, 10276, 10, 15), +(76, 10276, 13, 10), +(77, 10277, 28, 20), +(78, 10277, 62, 12), +(79, 10278, 44, 16), +(80, 10278, 59, 15), +(81, 10278, 63, 8), +(82, 10278, 73, 25), +(83, 10279, 17, 15), +(84, 10280, 24, 12), +(85, 10280, 55, 20), +(86, 10280, 75, 30), +(87, 10281, 19, 1), +(88, 10281, 24, 6), +(89, 10281, 35, 4), +(90, 10282, 30, 6), +(91, 10282, 57, 2), +(92, 10283, 15, 20), +(93, 10283, 19, 18), +(94, 10283, 60, 35), +(95, 10283, 72, 3), +(96, 10284, 27, 15), +(97, 10284, 44, 21), +(98, 10284, 60, 20), +(99, 10284, 67, 5), +(100, 10285, 1, 45), +(101, 10285, 40, 40), +(102, 10285, 53, 36), +(103, 10286, 35, 100), +(104, 10286, 62, 40), +(105, 10287, 16, 40), +(106, 10287, 34, 20), +(107, 10287, 46, 15), +(108, 10288, 54, 10), +(109, 10288, 68, 3), +(110, 10289, 3, 30), +(111, 10289, 64, 9), +(112, 10290, 5, 20), +(113, 10290, 29, 15), +(114, 10290, 49, 15), +(115, 10290, 77, 10), +(116, 10291, 13, 20), +(117, 10291, 44, 24), +(118, 10291, 51, 2), +(119, 10292, 20, 20), +(120, 10293, 18, 12), +(121, 10293, 24, 10), +(122, 10293, 63, 5), +(123, 10293, 75, 6), +(124, 10294, 1, 18), +(125, 10294, 17, 15), +(126, 10294, 43, 15), +(127, 10294, 60, 21), +(128, 10294, 75, 6), +(129, 10295, 56, 4), +(130, 10296, 11, 12), +(131, 10296, 16, 30), +(132, 10296, 69, 15), +(133, 10297, 39, 60), +(134, 10297, 72, 20), +(135, 10298, 2, 40), +(136, 10298, 36, 40), +(137, 10298, 59, 30), +(138, 10298, 62, 15), +(139, 10299, 19, 15), +(140, 10299, 70, 20), +(141, 10300, 66, 30), +(142, 10300, 68, 20), +(143, 10301, 40, 10), +(144, 10301, 56, 20), +(145, 10302, 17, 40), +(146, 10302, 28, 28), +(147, 10302, 43, 12), +(148, 10303, 40, 40), +(149, 10303, 65, 30), +(150, 10303, 68, 15), +(151, 10304, 49, 30), +(152, 10304, 59, 10), +(153, 10304, 71, 2), +(154, 10305, 18, 25), +(155, 10305, 29, 25), +(156, 10305, 39, 30), +(157, 10306, 30, 10), +(158, 10306, 53, 10), +(159, 10306, 54, 5), +(160, 10307, 62, 10), +(161, 10307, 68, 3), +(162, 10308, 69, 1), +(163, 10308, 70, 5), +(164, 10309, 4, 20), +(165, 10309, 6, 30), +(166, 10309, 42, 2), +(167, 10309, 43, 20), +(168, 10309, 71, 3), +(169, 10310, 16, 10), +(170, 10310, 62, 5), +(171, 10311, 42, 6), +(172, 10311, 69, 7), +(173, 10312, 28, 4), +(174, 10312, 43, 24), +(175, 10312, 53, 20), +(176, 10312, 75, 10), +(177, 10313, 36, 12), +(178, 10314, 32, 40), +(179, 10314, 58, 30), +(180, 10314, 62, 25), +(181, 10315, 34, 14), +(182, 10315, 70, 30), +(183, 10316, 41, 10), +(184, 10316, 62, 70), +(185, 10317, 1, 20), +(186, 10318, 41, 20), +(187, 10318, 76, 6), +(188, 10319, 17, 8), +(189, 10319, 28, 14), +(190, 10319, 76, 30), +(191, 10320, 71, 30), +(192, 10321, 35, 10), +(193, 10322, 52, 20), +(194, 10323, 15, 5), +(195, 10323, 25, 4), +(196, 10323, 39, 4), +(197, 10324, 16, 21), +(198, 10324, 35, 70), +(199, 10324, 46, 30), +(200, 10324, 59, 40), +(201, 10324, 63, 80), +(202, 10325, 6, 6), +(203, 10325, 13, 12), +(204, 10325, 14, 9), +(205, 10325, 31, 4), +(206, 10325, 72, 40), +(207, 10326, 4, 24), +(208, 10326, 57, 16), +(209, 10326, 75, 50), +(210, 10327, 2, 25), +(211, 10327, 11, 50), +(212, 10327, 30, 35), +(213, 10327, 58, 30), +(214, 10328, 59, 9), +(215, 10328, 65, 40), +(216, 10328, 68, 10), +(217, 10329, 19, 10), +(218, 10329, 30, 8), +(219, 10329, 38, 20), +(220, 10329, 56, 12), +(221, 10330, 26, 50), +(222, 10330, 72, 25), +(223, 10331, 54, 15), +(224, 10332, 18, 40), +(225, 10332, 42, 10), +(226, 10332, 47, 16), +(227, 10333, 14, 10), +(228, 10333, 21, 10), +(229, 10333, 71, 40), +(230, 10334, 52, 8), +(231, 10334, 68, 10), +(232, 10335, 2, 7), +(233, 10335, 31, 25), +(234, 10335, 32, 6), +(235, 10335, 51, 48), +(236, 10336, 4, 18), +(237, 10337, 23, 40), +(238, 10337, 26, 24), +(239, 10337, 36, 20), +(240, 10337, 37, 28), +(241, 10337, 72, 25), +(242, 10338, 17, 20), +(243, 10338, 30, 15), +(244, 10339, 4, 10), +(245, 10339, 17, 70), +(246, 10339, 62, 28), +(247, 10340, 18, 20), +(248, 10340, 41, 12), +(249, 10340, 43, 40), +(250, 10341, 33, 8), +(251, 10341, 59, 9), +(252, 10342, 2, 24), +(253, 10342, 31, 56), +(254, 10342, 36, 40), +(255, 10342, 55, 40), +(256, 10343, 64, 50), +(257, 10343, 68, 4), +(258, 10343, 76, 15), +(259, 10344, 4, 35), +(260, 10344, 8, 70), +(261, 10345, 8, 70), +(262, 10345, 19, 80), +(263, 10345, 42, 9), +(264, 10346, 17, 36), +(265, 10346, 56, 20), +(266, 10347, 25, 10), +(267, 10347, 39, 50), +(268, 10347, 40, 4), +(269, 10347, 75, 6), +(270, 10348, 1, 15), +(271, 10348, 23, 25), +(272, 10349, 54, 24), +(273, 10350, 50, 15), +(274, 10350, 69, 18), +(275, 10351, 38, 20), +(276, 10351, 41, 13), +(277, 10351, 44, 77), +(278, 10351, 65, 10), +(279, 10352, 24, 10), +(280, 10352, 54, 20), +(281, 10353, 11, 12), +(282, 10353, 38, 50), +(283, 10354, 1, 12), +(284, 10354, 29, 4), +(285, 10355, 24, 25), +(286, 10355, 57, 25), +(287, 10356, 31, 30), +(288, 10356, 55, 12), +(289, 10356, 69, 20), +(290, 10357, 10, 30), +(291, 10357, 26, 16), +(292, 10357, 60, 8), +(293, 10358, 24, 10), +(294, 10358, 34, 10), +(295, 10358, 36, 20), +(296, 10359, 16, 56), +(297, 10359, 31, 70), +(298, 10359, 60, 80), +(299, 10360, 28, 30), +(300, 10360, 29, 35), +(301, 10360, 38, 10), +(302, 10360, 49, 35), +(303, 10360, 54, 28), +(304, 10361, 39, 54), +(305, 10361, 60, 55), +(306, 10362, 25, 50), +(307, 10362, 51, 20), +(308, 10362, 54, 24), +(309, 10363, 31, 20), +(310, 10363, 75, 12), +(311, 10363, 76, 12), +(312, 10364, 69, 30), +(313, 10364, 71, 5), +(314, 10365, 11, 24), +(315, 10366, 65, 5), +(316, 10366, 77, 5), +(317, 10367, 34, 36), +(318, 10367, 54, 18), +(319, 10367, 65, 15), +(320, 10367, 77, 7), +(321, 10368, 21, 5), +(322, 10368, 28, 13), +(323, 10368, 57, 25), +(324, 10368, 64, 35), +(325, 10369, 29, 20), +(326, 10369, 56, 18), +(327, 10370, 1, 15), +(328, 10370, 64, 30), +(329, 10370, 74, 20), +(330, 10371, 36, 6), +(331, 10372, 20, 12), +(332, 10372, 38, 40), +(333, 10372, 60, 70), +(334, 10372, 72, 42), +(335, 10373, 58, 80), +(336, 10373, 71, 50), +(337, 10374, 31, 30), +(338, 10374, 58, 15), +(339, 10375, 14, 15), +(340, 10375, 54, 10), +(341, 10376, 31, 42), +(342, 10377, 28, 20), +(343, 10377, 39, 20), +(344, 10378, 71, 6), +(345, 10379, 41, 8), +(346, 10379, 63, 16), +(347, 10379, 65, 20), +(348, 10380, 30, 18), +(349, 10380, 53, 20), +(350, 10380, 60, 6), +(351, 10380, 70, 30), +(352, 10381, 74, 14), +(353, 10382, 5, 32), +(354, 10382, 18, 9), +(355, 10382, 29, 14), +(356, 10382, 33, 60), +(357, 10382, 74, 50), +(358, 10383, 13, 20), +(359, 10383, 50, 15), +(360, 10383, 56, 20), +(361, 10384, 20, 28), +(362, 10384, 60, 15), +(363, 10385, 7, 10), +(364, 10385, 60, 20), +(365, 10385, 68, 8), +(366, 10386, 24, 15), +(367, 10386, 34, 10), +(368, 10387, 24, 15), +(369, 10387, 28, 6), +(370, 10387, 59, 12), +(371, 10387, 71, 15), +(372, 10388, 45, 15), +(373, 10388, 52, 20), +(374, 10388, 53, 40), +(375, 10389, 10, 16), +(376, 10389, 55, 15), +(377, 10389, 62, 20), +(378, 10389, 70, 30), +(379, 10390, 31, 60), +(380, 10390, 35, 40), +(381, 10390, 46, 45), +(382, 10390, 72, 24), +(383, 10391, 13, 18), +(384, 10392, 69, 50), +(385, 10393, 2, 25), +(386, 10393, 14, 42), +(387, 10393, 25, 7), +(388, 10393, 26, 70), +(389, 10393, 31, 32), +(390, 10394, 13, 10), +(391, 10394, 62, 10), +(392, 10395, 46, 28), +(393, 10395, 53, 70), +(394, 10395, 69, 8), +(395, 10396, 23, 40), +(396, 10396, 71, 60), +(397, 10396, 72, 21), +(398, 10397, 21, 10), +(399, 10397, 51, 18), +(400, 10398, 35, 30), +(401, 10398, 55, 120), +(402, 10399, 68, 60), +(403, 10399, 71, 30), +(404, 10399, 76, 35), +(405, 10399, 77, 14), +(406, 10400, 29, 21), +(407, 10400, 35, 35), +(408, 10400, 49, 30), +(409, 10401, 30, 18), +(410, 10401, 56, 70), +(411, 10401, 65, 20), +(412, 10401, 71, 60), +(413, 10402, 23, 60), +(414, 10402, 63, 65), +(415, 10403, 16, 21), +(416, 10403, 48, 70), +(417, 10404, 26, 30), +(418, 10404, 42, 40), +(419, 10404, 49, 30), +(420, 10405, 3, 50), +(421, 10406, 1, 10), +(422, 10406, 21, 30), +(423, 10406, 28, 42), +(424, 10406, 36, 5), +(425, 10406, 40, 2), +(426, 10407, 11, 30), +(427, 10407, 69, 15), +(428, 10407, 71, 15), +(429, 10408, 37, 10), +(430, 10408, 54, 6), +(431, 10408, 62, 35), +(432, 10409, 14, 12), +(433, 10409, 21, 12), +(434, 10410, 33, 49), +(435, 10410, 59, 16), +(436, 10411, 41, 25), +(437, 10411, 44, 40), +(438, 10411, 59, 9), +(439, 10412, 14, 20), +(440, 10413, 1, 24), +(441, 10413, 62, 40), +(442, 10413, 76, 14), +(443, 10414, 19, 18), +(444, 10414, 33, 50), +(445, 10415, 17, 2), +(446, 10415, 33, 20), +(447, 10416, 19, 20), +(448, 10416, 53, 10), +(449, 10416, 57, 20), +(450, 10417, 38, 50), +(451, 10417, 46, 2), +(452, 10417, 68, 36), +(453, 10417, 77, 35), +(454, 10418, 2, 60), +(455, 10418, 47, 55), +(456, 10418, 61, 16), +(457, 10418, 74, 15), +(458, 10419, 60, 60), +(459, 10419, 69, 20), +(460, 10420, 9, 20), +(461, 10420, 13, 2), +(462, 10420, 70, 8), +(463, 10420, 73, 20), +(464, 10421, 19, 4), +(465, 10421, 26, 30), +(466, 10421, 53, 15), +(467, 10421, 77, 10), +(468, 10422, 26, 2), +(469, 10423, 31, 14), +(470, 10423, 59, 20), +(471, 10424, 35, 60), +(472, 10424, 38, 49), +(473, 10424, 68, 30), +(474, 10425, 55, 10), +(475, 10425, 76, 20), +(476, 10426, 56, 5), +(477, 10426, 64, 7), +(478, 10427, 14, 35), +(479, 10428, 46, 20), +(480, 10429, 50, 40), +(481, 10429, 63, 35), +(482, 10430, 17, 45), +(483, 10430, 21, 50), +(484, 10430, 56, 30), +(485, 10430, 59, 70), +(486, 10431, 17, 50), +(487, 10431, 40, 50), +(488, 10431, 47, 30), +(489, 10432, 26, 10), +(490, 10432, 54, 40), +(491, 10433, 56, 28), +(492, 10434, 11, 6), +(493, 10434, 76, 18), +(494, 10435, 2, 10), +(495, 10435, 22, 12), +(496, 10435, 72, 10), +(497, 10436, 46, 5), +(498, 10436, 56, 40), +(499, 10436, 64, 30), +(500, 10436, 75, 24), +(501, 10437, 53, 15), +(502, 10438, 19, 15), +(503, 10438, 34, 20), +(504, 10438, 57, 15), +(505, 10439, 12, 15), +(506, 10439, 16, 16), +(507, 10439, 64, 6), +(508, 10439, 74, 30), +(509, 10440, 2, 45), +(510, 10440, 16, 49), +(511, 10440, 29, 24), +(512, 10440, 61, 90), +(513, 10441, 27, 50), +(514, 10442, 11, 30), +(515, 10442, 54, 80), +(516, 10442, 66, 60), +(517, 10443, 11, 6), +(518, 10443, 28, 12); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `Orders` +-- + +CREATE TABLE `Orders` ( + `OrderID` int(11) NOT NULL, + `CustomerID` int(11) DEFAULT NULL, + `EmployeeID` int(11) DEFAULT NULL, + `OrderDate` datetime DEFAULT NULL, + `ShipperID` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci; + +-- +-- Dumping data for table `Orders` +-- + +INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `ShipperID`) VALUES +(10248, 90, 5, '1996-07-04 00:00:00', 3), +(10249, 81, 6, '1996-07-05 00:00:00', 1), +(10250, 34, 4, '1996-07-08 00:00:00', 2), +(10251, 84, 3, '1996-07-08 00:00:00', 1), +(10252, 76, 4, '1996-07-09 00:00:00', 2), +(10253, 34, 3, '1996-07-10 00:00:00', 2), +(10254, 14, 5, '1996-07-11 00:00:00', 2), +(10255, 68, 9, '1996-07-12 00:00:00', 3), +(10256, 88, 3, '1996-07-15 00:00:00', 2), +(10257, 35, 4, '1996-07-16 00:00:00', 3), +(10258, 20, 1, '1996-07-17 00:00:00', 1), +(10259, 13, 4, '1996-07-18 00:00:00', 3), +(10260, 55, 4, '1996-07-19 00:00:00', 1), +(10261, 61, 4, '1996-07-19 00:00:00', 2), +(10262, 65, 8, '1996-07-22 00:00:00', 3), +(10263, 20, 9, '1996-07-23 00:00:00', 3), +(10264, 24, 6, '1996-07-24 00:00:00', 3), +(10265, 7, 2, '1996-07-25 00:00:00', 1), +(10266, 87, 3, '1996-07-26 00:00:00', 3), +(10267, 25, 4, '1996-07-29 00:00:00', 1), +(10268, 33, 8, '1996-07-30 00:00:00', 3), +(10269, 89, 5, '1996-07-31 00:00:00', 1), +(10270, 87, 1, '1996-08-01 00:00:00', 1), +(10271, 75, 6, '1996-08-01 00:00:00', 2), +(10272, 65, 6, '1996-08-02 00:00:00', 2), +(10273, 63, 3, '1996-08-05 00:00:00', 3), +(10274, 85, 6, '1996-08-06 00:00:00', 1), +(10275, 49, 1, '1996-08-07 00:00:00', 1), +(10276, 80, 8, '1996-08-08 00:00:00', 3), +(10277, 52, 2, '1996-08-09 00:00:00', 3), +(10278, 5, 8, '1996-08-12 00:00:00', 2), +(10279, 44, 8, '1996-08-13 00:00:00', 2), +(10280, 5, 2, '1996-08-14 00:00:00', 1), +(10281, 69, 4, '1996-08-14 00:00:00', 1), +(10282, 69, 4, '1996-08-15 00:00:00', 1), +(10283, 46, 3, '1996-08-16 00:00:00', 3), +(10284, 44, 4, '1996-08-19 00:00:00', 1), +(10285, 63, 1, '1996-08-20 00:00:00', 2), +(10286, 63, 8, '1996-08-21 00:00:00', 3), +(10287, 67, 8, '1996-08-22 00:00:00', 3), +(10288, 66, 4, '1996-08-23 00:00:00', 1), +(10289, 11, 7, '1996-08-26 00:00:00', 3), +(10290, 15, 8, '1996-08-27 00:00:00', 1), +(10291, 61, 6, '1996-08-27 00:00:00', 2), +(10292, 81, 1, '1996-08-28 00:00:00', 2), +(10293, 80, 1, '1996-08-29 00:00:00', 3), +(10294, 65, 4, '1996-08-30 00:00:00', 2), +(10295, 85, 2, '1996-09-02 00:00:00', 2), +(10296, 46, 6, '1996-09-03 00:00:00', 1), +(10297, 7, 5, '1996-09-04 00:00:00', 2), +(10298, 37, 6, '1996-09-05 00:00:00', 2), +(10299, 67, 4, '1996-09-06 00:00:00', 2), +(10300, 49, 2, '1996-09-09 00:00:00', 2), +(10301, 86, 8, '1996-09-09 00:00:00', 2), +(10302, 76, 4, '1996-09-10 00:00:00', 2), +(10303, 30, 7, '1996-09-11 00:00:00', 2), +(10304, 80, 1, '1996-09-12 00:00:00', 2), +(10305, 55, 8, '1996-09-13 00:00:00', 3), +(10306, 69, 1, '1996-09-16 00:00:00', 3), +(10307, 48, 2, '1996-09-17 00:00:00', 2), +(10308, 2, 7, '1996-09-18 00:00:00', 3), +(10309, 37, 3, '1996-09-19 00:00:00', 1), +(10310, 77, 8, '1996-09-20 00:00:00', 2), +(10311, 18, 1, '1996-09-20 00:00:00', 3), +(10312, 86, 2, '1996-09-23 00:00:00', 2), +(10313, 63, 2, '1996-09-24 00:00:00', 2), +(10314, 65, 1, '1996-09-25 00:00:00', 2), +(10315, 38, 4, '1996-09-26 00:00:00', 2), +(10316, 65, 1, '1996-09-27 00:00:00', 3), +(10317, 48, 6, '1996-09-30 00:00:00', 1), +(10318, 38, 8, '1996-10-01 00:00:00', 2), +(10319, 80, 7, '1996-10-02 00:00:00', 3), +(10320, 87, 5, '1996-10-03 00:00:00', 3), +(10321, 38, 3, '1996-10-03 00:00:00', 2), +(10322, 58, 7, '1996-10-04 00:00:00', 3), +(10323, 39, 4, '1996-10-07 00:00:00', 1), +(10324, 71, 9, '1996-10-08 00:00:00', 1), +(10325, 39, 1, '1996-10-09 00:00:00', 3), +(10326, 8, 4, '1996-10-10 00:00:00', 2), +(10327, 24, 2, '1996-10-11 00:00:00', 1), +(10328, 28, 4, '1996-10-14 00:00:00', 3), +(10329, 75, 4, '1996-10-15 00:00:00', 2), +(10330, 46, 3, '1996-10-16 00:00:00', 1), +(10331, 9, 9, '1996-10-16 00:00:00', 1), +(10332, 51, 3, '1996-10-17 00:00:00', 2), +(10333, 87, 5, '1996-10-18 00:00:00', 3), +(10334, 84, 8, '1996-10-21 00:00:00', 2), +(10335, 37, 7, '1996-10-22 00:00:00', 2), +(10336, 60, 7, '1996-10-23 00:00:00', 2), +(10337, 25, 4, '1996-10-24 00:00:00', 3), +(10338, 55, 4, '1996-10-25 00:00:00', 3), +(10339, 51, 2, '1996-10-28 00:00:00', 2), +(10340, 9, 1, '1996-10-29 00:00:00', 3), +(10341, 73, 7, '1996-10-29 00:00:00', 3), +(10342, 25, 4, '1996-10-30 00:00:00', 2), +(10343, 44, 4, '1996-10-31 00:00:00', 1), +(10344, 89, 4, '1996-11-01 00:00:00', 2), +(10345, 63, 2, '1996-11-04 00:00:00', 2), +(10346, 65, 3, '1996-11-05 00:00:00', 3), +(10347, 21, 4, '1996-11-06 00:00:00', 3), +(10348, 86, 4, '1996-11-07 00:00:00', 2), +(10349, 75, 7, '1996-11-08 00:00:00', 1), +(10350, 41, 6, '1996-11-11 00:00:00', 2), +(10351, 20, 1, '1996-11-11 00:00:00', 1), +(10352, 28, 3, '1996-11-12 00:00:00', 3), +(10353, 59, 7, '1996-11-13 00:00:00', 3), +(10354, 58, 8, '1996-11-14 00:00:00', 3), +(10355, 4, 6, '1996-11-15 00:00:00', 1), +(10356, 86, 6, '1996-11-18 00:00:00', 2), +(10357, 46, 1, '1996-11-19 00:00:00', 3), +(10358, 41, 5, '1996-11-20 00:00:00', 1), +(10359, 72, 5, '1996-11-21 00:00:00', 3), +(10360, 7, 4, '1996-11-22 00:00:00', 3), +(10361, 63, 1, '1996-11-22 00:00:00', 2), +(10362, 9, 3, '1996-11-25 00:00:00', 1), +(10363, 17, 4, '1996-11-26 00:00:00', 3), +(10364, 19, 1, '1996-11-26 00:00:00', 1), +(10365, 3, 3, '1996-11-27 00:00:00', 2), +(10366, 29, 8, '1996-11-28 00:00:00', 2), +(10367, 83, 7, '1996-11-28 00:00:00', 3), +(10368, 20, 2, '1996-11-29 00:00:00', 2), +(10369, 75, 8, '1996-12-02 00:00:00', 2), +(10370, 14, 6, '1996-12-03 00:00:00', 2), +(10371, 41, 1, '1996-12-03 00:00:00', 1), +(10372, 62, 5, '1996-12-04 00:00:00', 2), +(10373, 37, 4, '1996-12-05 00:00:00', 3), +(10374, 91, 1, '1996-12-05 00:00:00', 3), +(10375, 36, 3, '1996-12-06 00:00:00', 2), +(10376, 51, 1, '1996-12-09 00:00:00', 2), +(10377, 72, 1, '1996-12-09 00:00:00', 3), +(10378, 24, 5, '1996-12-10 00:00:00', 3), +(10379, 61, 2, '1996-12-11 00:00:00', 1), +(10380, 37, 8, '1996-12-12 00:00:00', 3), +(10381, 46, 3, '1996-12-12 00:00:00', 3), +(10382, 20, 4, '1996-12-13 00:00:00', 1), +(10383, 4, 8, '1996-12-16 00:00:00', 3), +(10384, 5, 3, '1996-12-16 00:00:00', 3), +(10385, 75, 1, '1996-12-17 00:00:00', 2), +(10386, 21, 9, '1996-12-18 00:00:00', 3), +(10387, 70, 1, '1996-12-18 00:00:00', 2), +(10388, 72, 2, '1996-12-19 00:00:00', 1), +(10389, 10, 4, '1996-12-20 00:00:00', 2), +(10390, 20, 6, '1996-12-23 00:00:00', 1), +(10391, 17, 3, '1996-12-23 00:00:00', 3), +(10392, 59, 2, '1996-12-24 00:00:00', 3), +(10393, 71, 1, '1996-12-25 00:00:00', 3), +(10394, 36, 1, '1996-12-25 00:00:00', 3), +(10395, 35, 6, '1996-12-26 00:00:00', 1), +(10396, 25, 1, '1996-12-27 00:00:00', 3), +(10397, 60, 5, '1996-12-27 00:00:00', 1), +(10398, 71, 2, '1996-12-30 00:00:00', 3), +(10399, 83, 8, '1996-12-31 00:00:00', 3), +(10400, 19, 1, '1997-01-01 00:00:00', 3), +(10401, 65, 1, '1997-01-01 00:00:00', 1), +(10402, 20, 8, '1997-01-02 00:00:00', 2), +(10403, 20, 4, '1997-01-03 00:00:00', 3), +(10404, 49, 2, '1997-01-03 00:00:00', 1), +(10405, 47, 1, '1997-01-06 00:00:00', 1), +(10406, 62, 7, '1997-01-07 00:00:00', 1), +(10407, 56, 2, '1997-01-07 00:00:00', 2), +(10408, 23, 8, '1997-01-08 00:00:00', 1), +(10409, 54, 3, '1997-01-09 00:00:00', 1), +(10410, 10, 3, '1997-01-10 00:00:00', 3), +(10411, 10, 9, '1997-01-10 00:00:00', 3), +(10412, 87, 8, '1997-01-13 00:00:00', 2), +(10413, 41, 3, '1997-01-14 00:00:00', 2), +(10414, 21, 2, '1997-01-14 00:00:00', 3), +(10415, 36, 3, '1997-01-15 00:00:00', 1), +(10416, 87, 8, '1997-01-16 00:00:00', 3), +(10417, 73, 4, '1997-01-16 00:00:00', 3), +(10418, 63, 4, '1997-01-17 00:00:00', 1), +(10419, 68, 4, '1997-01-20 00:00:00', 2), +(10420, 88, 3, '1997-01-21 00:00:00', 1), +(10421, 61, 8, '1997-01-21 00:00:00', 1), +(10422, 27, 2, '1997-01-22 00:00:00', 1), +(10423, 31, 6, '1997-01-23 00:00:00', 3), +(10424, 51, 7, '1997-01-23 00:00:00', 2), +(10425, 41, 6, '1997-01-24 00:00:00', 2), +(10426, 29, 4, '1997-01-27 00:00:00', 1), +(10427, 59, 4, '1997-01-27 00:00:00', 2), +(10428, 66, 7, '1997-01-28 00:00:00', 1), +(10429, 37, 3, '1997-01-29 00:00:00', 2), +(10430, 20, 4, '1997-01-30 00:00:00', 1), +(10431, 10, 4, '1997-01-30 00:00:00', 2), +(10432, 75, 3, '1997-01-31 00:00:00', 2), +(10433, 60, 3, '1997-02-03 00:00:00', 3), +(10434, 24, 3, '1997-02-03 00:00:00', 2), +(10435, 16, 8, '1997-02-04 00:00:00', 2), +(10436, 7, 3, '1997-02-05 00:00:00', 2), +(10437, 87, 8, '1997-02-05 00:00:00', 1), +(10438, 79, 3, '1997-02-06 00:00:00', 2), +(10439, 51, 6, '1997-02-07 00:00:00', 3), +(10440, 71, 4, '1997-02-10 00:00:00', 2), +(10441, 55, 3, '1997-02-10 00:00:00', 2), +(10442, 20, 3, '1997-02-11 00:00:00', 2), +(10443, 66, 8, '1997-02-12 00:00:00', 1); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `Products` +-- + +CREATE TABLE `Products` ( + `ProductID` int(11) NOT NULL, + `ProductName` varchar(50) DEFAULT NULL, + `SupplierID` int(11) DEFAULT NULL, + `CategoryID` int(11) DEFAULT NULL, + `Unit` varchar(25) DEFAULT NULL, + `Price` decimal(10,0) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci; + +-- +-- Dumping data for table `Products` +-- + +INSERT INTO `Products` (`ProductID`, `ProductName`, `SupplierID`, `CategoryID`, `Unit`, `Price`) VALUES +(1, 'Chais', 1, 1, '10 boxes x 20 bags', 18), +(2, 'Chang', 1, 1, '24 - 12 oz bottles', 19), +(3, 'Aniseed Syrup', 1, 2, '12 - 550 ml bottles', 10), +(4, 'Chef Anton\'s Cajun Seasoning', 2, 2, '48 - 6 oz jars', 22), +(5, 'Chef Anton\'s Gumbo Mix', 2, 2, '36 boxes', 21), +(6, 'Grandma\'s Boysenberry Spread', 3, 2, '12 - 8 oz jars', 25), +(7, 'Uncle Bob\'s Organic Dried Pears', 3, 7, '12 - 1 lb pkgs.', 30), +(8, 'Northwoods Cranberry Sauce', 3, 2, '12 - 12 oz jars', 40), +(9, 'Mishi Kobe Niku', 4, 6, '18 - 500 g pkgs.', 97), +(10, 'Ikura', 4, 8, '12 - 200 ml jars', 31), +(11, 'Queso Cabrales', 5, 4, '1 kg pkg.', 21), +(12, 'Queso Manchego La Pastora', 5, 4, '10 - 500 g pkgs.', 38), +(13, 'Konbu', 6, 8, '2 kg box', 6), +(14, 'Tofu', 6, 7, '40 - 100 g pkgs.', 23), +(15, 'Genen Shouyu', 6, 2, '24 - 250 ml bottles', 16), +(16, 'Pavlova', 7, 3, '32 - 500 g boxes', 17), +(17, 'Alice Mutton', 7, 6, '20 - 1 kg tins', 39), +(18, 'Carnarvon Tigers', 7, 8, '16 kg pkg.', 63), +(19, 'Teatime Chocolate Biscuits', 8, 3, '10 boxes x 12 pieces', 9), +(20, 'Sir Rodney\'s Marmalade', 8, 3, '30 gift boxes', 81), +(21, 'Sir Rodney\'s Scones', 8, 3, '24 pkgs. x 4 pieces', 10), +(22, 'Gustaf\'s Knäckebröd', 9, 5, '24 - 500 g pkgs.', 21), +(23, 'Tunnbröd', 9, 5, '12 - 250 g pkgs.', 9), +(24, 'Guaraná Fantástica', 10, 1, '12 - 355 ml cans', 5), +(25, 'NuNuCa Nuß-Nougat-Creme', 11, 3, '20 - 450 g glasses', 14), +(26, 'Gumbär Gummibärchen', 11, 3, '100 - 250 g bags', 31), +(27, 'Schoggi Schokolade', 11, 3, '100 - 100 g pieces', 44), +(28, 'Rössle Sauerkraut', 12, 7, '25 - 825 g cans', 46), +(29, 'Thüringer Rostbratwurst', 12, 6, '50 bags x 30 sausgs.', 124), +(30, 'Nord-Ost Matjeshering', 13, 8, '10 - 200 g glasses', 26), +(31, 'Gorgonzola Telino', 14, 4, '12 - 100 g pkgs', 13), +(32, 'Mascarpone Fabioli', 14, 4, '24 - 200 g pkgs.', 32), +(33, 'Geitost', 15, 4, '500 g', 3), +(34, 'Sasquatch Ale', 16, 1, '24 - 12 oz bottles', 14), +(35, 'Steeleye Stout', 16, 1, '24 - 12 oz bottles', 18), +(36, 'Inlagd Sill', 17, 8, '24 - 250 g jars', 19), +(37, 'Gravad lax', 17, 8, '12 - 500 g pkgs.', 26), +(38, 'Côte de Blaye', 18, 1, '12 - 75 cl bottles', 264), +(39, 'Chartreuse verte', 18, 1, '750 cc per bottle', 18), +(40, 'Boston Crab Meat', 19, 8, '24 - 4 oz tins', 18), +(41, 'Jack\'s New England Clam Chowder', 19, 8, '12 - 12 oz cans', 10), +(42, 'Singaporean Hokkien Fried Mee', 20, 5, '32 - 1 kg pkgs.', 14), +(43, 'Ipoh Coffee', 20, 1, '16 - 500 g tins', 46), +(44, 'Gula Malacca', 20, 2, '20 - 2 kg bags', 19), +(45, 'Røgede sild', 21, 8, '1k pkg.', 10), +(46, 'Spegesild', 21, 8, '4 - 450 g glasses', 12), +(47, 'Zaanse koeken', 22, 3, '10 - 4 oz boxes', 10), +(48, 'Chocolade', 22, 3, '10 pkgs.', 13), +(49, 'Maxilaku', 23, 3, '24 - 50 g pkgs.', 20), +(50, 'Valkoinen suklaa', 23, 3, '12 - 100 g bars', 16), +(51, 'Manjimup Dried Apples', 24, 7, '50 - 300 g pkgs.', 53), +(52, 'Filo Mix', 24, 5, '16 - 2 kg boxes', 7), +(53, 'Perth Pasties', 24, 6, '48 pieces', 33), +(54, 'Tourtière', 25, 6, '16 pies', 7), +(55, 'Pâté chinois', 25, 6, '24 boxes x 2 pies', 24), +(56, 'Gnocchi di nonna Alice', 26, 5, '24 - 250 g pkgs.', 38), +(57, 'Ravioli Angelo', 26, 5, '24 - 250 g pkgs.', 20), +(58, 'Escargots de Bourgogne', 27, 8, '24 pieces', 13), +(59, 'Raclette Courdavault', 28, 4, '5 kg pkg.', 55), +(60, 'Camembert Pierrot', 28, 4, '15 - 300 g rounds', 34), +(61, 'Sirop d\'érable', 29, 2, '24 - 500 ml bottles', 29), +(62, 'Tarte au sucre', 29, 3, '48 pies', 49), +(63, 'Vegie-spread', 7, 2, '15 - 625 g jars', 44), +(64, 'Wimmers gute Semmelknödel', 12, 5, '20 bags x 4 pieces', 33), +(65, 'Louisiana Fiery Hot Pepper Sauce', 2, 2, '32 - 8 oz bottles', 21), +(66, 'Louisiana Hot Spiced Okra', 2, 2, '24 - 8 oz jars', 17), +(67, 'Laughing Lumberjack Lager', 16, 1, '24 - 12 oz bottles', 14), +(68, 'Scottish Longbreads', 8, 3, '10 boxes x 8 pieces', 13), +(69, 'Gudbrandsdalsost', 15, 4, '10 kg pkg.', 36), +(70, 'Outback Lager', 7, 1, '24 - 355 ml bottles', 15), +(71, 'Fløtemysost', 15, 4, '10 - 500 g pkgs.', 22), +(72, 'Mozzarella di Giovanni', 14, 4, '24 - 200 g pkgs.', 35), +(73, 'Röd Kaviar', 17, 8, '24 - 150 g jars', 15), +(74, 'Longlife Tofu', 4, 7, '5 kg pkg.', 10), +(75, 'Rhönbräu Klosterbier', 12, 1, '24 - 0.5 l bottles', 8), +(76, 'Lakkalikööri', 23, 1, '500 ml', 18), +(77, 'Original Frankfurter grüne Soße', 12, 2, '12 boxes', 13); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `Shippers` +-- + +CREATE TABLE `Shippers` ( + `ShipperID` int(11) NOT NULL, + `ShipperName` varchar(25) DEFAULT NULL, + `Phone` varchar(15) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci; + +-- +-- Dumping data for table `Shippers` +-- + +INSERT INTO `Shippers` (`ShipperID`, `ShipperName`, `Phone`) VALUES +(1, 'Speedy Express', '(503) 555-9831'), +(2, 'United Package', '(503) 555-3199'), +(3, 'Federal Shipping', '(503) 555-9931'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `Suppliers` +-- + +CREATE TABLE `Suppliers` ( + `SupplierID` int(11) NOT NULL, + `SupplierName` varchar(50) DEFAULT NULL, + `ContactName` varchar(50) DEFAULT NULL, + `Address` varchar(50) DEFAULT NULL, + `City` varchar(20) DEFAULT NULL, + `PostalCode` varchar(10) DEFAULT NULL, + `Country` varchar(15) DEFAULT NULL, + `Phone` varchar(15) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci; + +-- +-- Dumping data for table `Suppliers` +-- + +INSERT INTO `Suppliers` (`SupplierID`, `SupplierName`, `ContactName`, `Address`, `City`, `PostalCode`, `Country`, `Phone`) VALUES +(1, 'Exotic Liquid', 'Charlotte Cooper', '49 Gilbert St.', 'Londona', 'EC1 4SD', 'UK', '(171) 555-2222'), +(2, 'New Orleans Cajun Delights', 'Shelley Burke', 'P.O. Box 78934', 'New Orleans', '70117', 'USA', '(100) 555-4822'), +(3, 'Grandma Kelly\'s Homestead', 'Regina Murphy', '707 Oxford Rd.', 'Ann Arbor', '48104', 'USA', '(313) 555-5735'), +(4, 'Tokyo Traders', 'Yoshi Nagase', '9-8 Sekimai Musashino-shi', 'Tokyo', '100', 'Japan', '(03) 3555-5011'), +(5, 'Cooperativa de Quesos \'Las Cabras\'', 'Antonio del Valle Saavedra', 'Calle del Rosal 4', 'Oviedo', '33007', 'Spain', '(98) 598 76 54'), +(6, 'Mayumi\'s', 'Mayumi Ohno', '92 Setsuko Chuo-ku', 'Osaka', '545', 'Japan', '(06) 431-7877'), +(7, 'Pavlova, Ltd.', 'Ian Devling', '74 Rose St. Moonie Ponds', 'Melbourne', '3058', 'Australia', '(03) 444-2343'), +(8, 'Specialty Biscuits, Ltd.', 'Peter Wilson', '29 King\'s Way', 'Manchester', 'M14 GSD', 'UK', '(161) 555-4448'), +(9, 'PB Knäckebröd AB', 'Lars Peterson', 'Kaloadagatan 13', 'Göteborg', 'S-345 67', 'Sweden', '031-987 65 43'), +(10, 'Refrescos Americanas LTDA', 'Carlos Diaz', 'Av. das Americanas 12.890', 'São Paulo', '5442', 'Brazil', '(11) 555 4640'), +(11, 'Heli Süßwaren GmbH & Co. KG', 'Petra Winkler', 'Tiergartenstraße 5', 'Berlin', '10785', 'Germany', '(010) 9984510'), +(12, 'Plutzer Lebensmittelgroßmärkte AG', 'Martin Bein', 'Bogenallee 51', 'Frankfurt', '60439', 'Germany', '(069) 992755'), +(13, 'Nord-Ost-Fisch Handelsgesellschaft mbH', 'Sven Petersen', 'Frahmredder 112a', 'Cuxhaven', '27478', 'Germany', '(04721) 8713'), +(14, 'Formaggi Fortini s.r.l.', 'Elio Rossi', 'Viale Dante, 75', 'Ravenna', '48100', 'Italy', '(0544) 60323'), +(15, 'Norske Meierier', 'Beate Vileid', 'Hatlevegen 5', 'Sandvika', '1320', 'Norway', '(0)2-953010'), +(16, 'Bigfoot Breweries', 'Cheryl Saylor', '3400 - 8th Avenue Suite 210', 'Bend', '97101', 'USA', '(503) 555-9931'), +(17, 'Svensk Sjöföda AB', 'Michael Björn', 'Brovallavägen 231', 'Stockholm', 'S-123 45', 'Sweden', '08-123 45 67'), +(18, 'Aux joyeux ecclésiastiques', 'Guylène Nodier', '203, Rue des Francs-Bourgeois', 'Paris', '75004', 'France', '(1) 03.83.00.68'), +(19, 'New England Seafood Cannery', 'Robb Merchant', 'Order Processing Dept. 2100 Paul Revere Blvd.', 'Boston', '2134', 'USA', '(617) 555-3267'), +(20, 'Leka Trading', 'Chandra Leka', '471 Serangoon Loop, Suite #402', 'Singapore', '512', 'Singapore', '555-8787'), +(21, 'Lyngbysild', 'Niels Petersen', 'Lyngbysild Fiskebakken 10', 'Lyngby', '2800', 'Denmark', '43844108'), +(22, 'Zaanse Snoepfabriek', 'Dirk Luchte', 'Verkoop Rijnweg 22', 'Zaandam', '9999 ZZ', 'Netherlands', '(12345) 1212'), +(23, 'Karkki Oy', 'Anne Heikkonen', 'Valtakatu 12', 'Lappeenranta', '53120', 'Finland', '(953) 10956'), +(24, 'G\'day, Mate', 'Wendy Mackenzie', '170 Prince Edward Parade Hunter\'s Hill', 'Sydney', '2042', 'Australia', '(02) 555-5914'), +(25, 'Ma Maison', 'Jean-Guy Lauzon', '2960 Rue St. Laurent', 'Montréal', 'H1J 1C3', 'Canada', '(514) 555-9022'), +(26, 'Pasta Buttini s.r.l.', 'Giovanni Giudici', 'Via dei Gelsomini, 153', 'Salerno', '84100', 'Italy', '(089) 6547665'), +(27, 'Escargots Nouveaux', 'Marie Delamare', '22, rue H. Voiron', 'Montceau', '71300', 'France', '85.57.00.07'), +(28, 'Gai pâturage', 'Eliane Noz', 'Bat. B 3, rue des Alpes', 'Annecy', '74000', 'France', '38.76.98.06'), +(29, 'Forêts d\'érables', 'Chantal Goulet', '148 rue Chasseur', 'Ste-Hyacinthe', 'J2S 7S8', 'Canada', '(514) 555-2955'); + +-- +-- Indexes for dumped tables +-- + +-- +-- Indexes for table `Categories` +-- +ALTER TABLE `Categories` + ADD PRIMARY KEY (`CategoryID`); + +-- +-- Indexes for table `Customers` +-- +ALTER TABLE `Customers` + ADD PRIMARY KEY (`CustomerID`); + +-- +-- Indexes for table `Employees` +-- +ALTER TABLE `Employees` + ADD PRIMARY KEY (`EmployeeID`); + +-- +-- Indexes for table `OrderDetails` +-- +ALTER TABLE `OrderDetails` + ADD PRIMARY KEY (`OrderDetailID`), + ADD KEY `OrderID` (`OrderID`), + ADD KEY `ProductID` (`ProductID`); + +-- +-- Indexes for table `Orders` +-- +ALTER TABLE `Orders` + ADD PRIMARY KEY (`OrderID`), + ADD KEY `EmployeeID` (`EmployeeID`), + ADD KEY `CustomerID` (`CustomerID`), + ADD KEY `ShipperID` (`ShipperID`); + +-- +-- Indexes for table `Products` +-- +ALTER TABLE `Products` + ADD PRIMARY KEY (`ProductID`), + ADD KEY `CategoryID` (`CategoryID`), + ADD KEY `SupplierID` (`SupplierID`); + +-- +-- Indexes for table `Shippers` +-- +ALTER TABLE `Shippers` + ADD PRIMARY KEY (`ShipperID`); + +-- +-- Indexes for table `Suppliers` +-- +ALTER TABLE `Suppliers` + ADD PRIMARY KEY (`SupplierID`); + +-- +-- AUTO_INCREMENT for dumped tables +-- + +-- +-- AUTO_INCREMENT for table `Categories` +-- +ALTER TABLE `Categories` + MODIFY `CategoryID` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=9; + +-- +-- AUTO_INCREMENT for table `Customers` +-- +ALTER TABLE `Customers` + MODIFY `CustomerID` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=92; + +-- +-- AUTO_INCREMENT for table `Employees` +-- +ALTER TABLE `Employees` + MODIFY `EmployeeID` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=11; + +-- +-- AUTO_INCREMENT for table `OrderDetails` +-- +ALTER TABLE `OrderDetails` + MODIFY `OrderDetailID` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=519; + +-- +-- AUTO_INCREMENT for table `Orders` +-- +ALTER TABLE `Orders` + MODIFY `OrderID` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=10444; + +-- +-- AUTO_INCREMENT for table `Products` +-- +ALTER TABLE `Products` + MODIFY `ProductID` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=78; + +-- +-- AUTO_INCREMENT for table `Shippers` +-- +ALTER TABLE `Shippers` + MODIFY `ShipperID` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4; + +-- +-- AUTO_INCREMENT for table `Suppliers` +-- +ALTER TABLE `Suppliers` + MODIFY `SupplierID` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=30; + +-- +-- Constraints for dumped tables +-- + +-- +-- Constraints for table `OrderDetails` +-- +ALTER TABLE `OrderDetails` + ADD CONSTRAINT `OrderDetails_ibfk_1` FOREIGN KEY (`OrderID`) REFERENCES `Orders` (`OrderID`), + ADD CONSTRAINT `OrderDetails_ibfk_2` FOREIGN KEY (`ProductID`) REFERENCES `Products` (`ProductID`); + +-- +-- Constraints for table `Orders` +-- +ALTER TABLE `Orders` + ADD CONSTRAINT `Orders_ibfk_1` FOREIGN KEY (`EmployeeID`) REFERENCES `Employees` (`EmployeeID`), + ADD CONSTRAINT `Orders_ibfk_2` FOREIGN KEY (`CustomerID`) REFERENCES `Customers` (`CustomerID`), + ADD CONSTRAINT `Orders_ibfk_3` FOREIGN KEY (`ShipperID`) REFERENCES `Shippers` (`ShipperID`); + +-- +-- Constraints for table `Products` +-- +ALTER TABLE `Products` + ADD CONSTRAINT `Products_ibfk_1` FOREIGN KEY (`CategoryID`) REFERENCES `Categories` (`CategoryID`), + ADD CONSTRAINT `Products_ibfk_2` FOREIGN KEY (`SupplierID`) REFERENCES `Suppliers` (`SupplierID`); diff --git a/datasets/monaco-motors-dealership.sql b/datasets/monaco-motors-dealership.sql new file mode 100644 index 0000000..314a1d3 --- /dev/null +++ b/datasets/monaco-motors-dealership.sql @@ -0,0 +1,381 @@ + +-- +-- Database: `MONACO_MOTORS` +-- +CREATE DATABASE IF NOT EXISTS `MONACO_MOTORS` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_uca1400_ai_ci; + +USE `MONACO_MOTORS`; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `Customer` +-- + +CREATE TABLE `Customer` ( + `CustomerID` char(8) NOT NULL, + `AgentID` char(8) NOT NULL, + `CustFirstName` varchar(15) NOT NULL, + `CustLastName` varchar(15) NOT NULL, + `PhoneNumber` varchar(12) NOT NULL, + `Email` varchar(40) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci; + +-- +-- Dumping data for table `Customer` +-- + +INSERT INTO `Customer` (`CustomerID`, `AgentID`, `CustFirstName`, `CustLastName`, `PhoneNumber`, `Email`) VALUES +('24863197', '89324037', 'Mark', 'Hunt', '3347852143', 'markymark@gmail.com'), +('25463157', '85476932', 'Carly', 'Myers', '7897896325', 'carlyy478@gmail.com'), +('45682178', '85264532', 'John', 'Miller', '3568421479', 'johnboy@hotmail.com'), +('46525896', '32433468', 'Madison', 'Hart', '7892553001', 'lilmaddy@gmail.com'), +('52147932', '78932145', 'Megan', 'Sellers', '3345893321', 'megmeg@hotmail.com'), +('53247962', '85693248', 'Shelly', 'Jones', '4568423698', 'shellyjones@gmail.com'), +('63222478', '45879632', 'Connor', 'Kirk', '3346953214', 'kirkkconnor@yahoo.com'), +('64786233', '89324037', 'Logan', 'Hutchinson', '3345896789', 'loganhutch@yahoo.com'), +('74859612', '45879632', 'Barbara', 'Brown', '3348529654', 'bigbarb400@hotmail.com'), +('78527962', '54279634', 'Andrew', 'Jackson', '3345301438', 'andyjack@gmail.com'), +('78962583', '85693248', 'Morgan', 'Stanley', '4562314862', 'morgstan78@yahoo.com'), +('86321478', '85476932', 'Bill', 'Clark', '7892256541', 'bclrk@hotmail.com'), +('88895214', '74125852', 'William', 'Martin', '6502287512', 'willmart@gmail.com'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `Deal` +-- + +CREATE TABLE `Deal` ( + `DealID` char(5) NOT NULL, + `VehicleID` char(3) NOT NULL, + `AgentID` char(8) NOT NULL, + `CustomerID` char(8) NOT NULL, + `InsuranceID` char(5) DEFAULT NULL, + `DealDate` date NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci; + +-- +-- Dumping data for table `Deal` +-- + +INSERT INTO `Deal` (`DealID`, `VehicleID`, `AgentID`, `CustomerID`, `InsuranceID`, `DealDate`) VALUES +('21115', '123', '32433468', '46525896', '78222', '2023-03-27'), +('25839', '328', '78932145', '52147932', '21444', '2024-04-18'), +('33658', '216', '74125852', '88895214', '26687', '2023-04-24'), +('45523', '377', '45879632', '63222478', '11478', '2023-04-01'), +('48624', '486', '54279634', '78527962', NULL, '2023-11-08'), +('48876', '729', '85693248', '53247962', NULL, '2024-04-16'), +('55896', '554', '45879632', '74859612', '44589', '2024-02-01'), +('58221', '456', '85264532', '45682178', '22268', '2023-02-11'), +('77885', '416', '85476932', '86321478', NULL, '2024-02-21'), +('95632', '265', '89324037', '24863197', '56482', '2023-01-17'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `Dealership` +-- + +CREATE TABLE `Dealership` ( + `DealershipID` char(5) NOT NULL, + `DistributorID` char(8) NOT NULL, + `RegionID` char(3) NOT NULL, + `RegionZIP` char(5) NOT NULL, + `DealershipName` varchar(40) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci; + +-- +-- Dumping data for table `Dealership` +-- + +INSERT INTO `Dealership` (`DealershipID`, `DistributorID`, `RegionID`, `RegionZIP`, `DealershipName`) VALUES +('32569', '45632479', '578', '58203', 'Winged Lion Motors'), +('47823', '12347896', '334', '36081', 'Scuderia Speed'), +('59823', '45324895', '578', '58203', 'Velocity Auto Haus'), +('78962', '36589217', '334', '36081', 'Tridente Motors'), +('85632', '36521789', '356', '36079', 'Galleria Motors'), +('96523', '25863217', '356', '36079', 'Royal Stallion Motors'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `Distributor` +-- + +CREATE TABLE `Distributor` ( + `DistributorID` char(8) NOT NULL, + `DistributorName` varchar(40) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci; + +-- +-- Dumping data for table `Distributor` +-- + +INSERT INTO `Distributor` (`DistributorID`, `DistributorName`) VALUES +('12347896', 'Pfaff Reserve'), +('25863217', 'EuroCar'), +('36521789', 'Redline European'), +('36589217', 'Romans International'), +('45324895', 'European Exotic Center'), +('45632479', 'James Edition'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `Insurance` +-- + +CREATE TABLE `Insurance` ( + `InsuranceID` char(5) NOT NULL, + `PolicyType` varchar(15) NOT NULL, + `RenewalDate` date NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci; + +-- +-- Dumping data for table `Insurance` +-- + +INSERT INTO `Insurance` (`InsuranceID`, `PolicyType`, `RenewalDate`) VALUES +('11478', 'Full Coverage', '2024-04-01'), +('21444', 'Full Coverage', '2020-04-18'), +('22268', 'Liability', '2024-02-11'), +('26687', 'Liability', '2024-04-24'), +('44589', 'Full Coverage', '2020-02-01'), +('56482', 'Full Coverage', '2024-01-17'), +('78222', 'Full Coverage', '2024-03-27'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `Manager` +-- + +CREATE TABLE `Manager` ( + `ManagerID` char(8) NOT NULL, + `DealershipID` char(5) NOT NULL, + `DistributorID` char(8) NOT NULL, + `MngrFirstName` varchar(15) NOT NULL, + `MngrLastName` varchar(15) NOT NULL, + `MngrSalary` decimal(8,2) NOT NULL, + `MngrBonus` decimal(8,2) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci; + +-- +-- Dumping data for table `Manager` +-- + +INSERT INTO `Manager` (`ManagerID`, `DealershipID`, `DistributorID`, `MngrFirstName`, `MngrLastName`, `MngrSalary`, `MngrBonus`) VALUES +('12345678', '59823', '45324895', 'John', 'Boling', 87900.00, 5100.23), +('14458973', '96523', '25863217', 'Henry', 'Miller', 79025.99, 5200.60), +('32556978', '78962', '36589217', 'Rachel', 'Smith', 81500.10, 2400.00), +('45896324', '32569', '45632479', 'Sally', 'Mae', 75000.99, 4250.50), +('52689974', '85632', '36521789', 'Lamar', 'Jackson', 91250.10, NULL), +('58894123', '47823', '12347896', 'Kevin', 'Rogers', 71250.00, 8450.00); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `Region` +-- + +CREATE TABLE `Region` ( + `RegionID` char(3) NOT NULL, + `RegionZIP` char(5) NOT NULL, + `RegionName` varchar(15) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci; + +-- +-- Dumping data for table `Region` +-- + +INSERT INTO `Region` (`RegionID`, `RegionZIP`, `RegionName`) VALUES +('334', '36081', 'EMEA'), +('356', '36079', 'APJ'), +('578', '58203', 'AMS'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `Sales_Agent` +-- + +CREATE TABLE `Sales_Agent` ( + `AgentID` char(8) NOT NULL, + `ManagerID` char(8) NOT NULL, + `DealershipID` char(5) NOT NULL, + `AgentFirstName` varchar(15) NOT NULL, + `AgentLastName` varchar(15) NOT NULL, + `AgentSalary` decimal(9,2) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci; + +-- +-- Dumping data for table `Sales_Agent` +-- + +INSERT INTO `Sales_Agent` (`AgentID`, `ManagerID`, `DealershipID`, `AgentFirstName`, `AgentLastName`, `AgentSalary`) VALUES +('28547962', '52689974', '85632', 'Jack', 'Hublot', 61258.00), +('32433468', '52689974', '85632', 'Jennifer', 'Martin', 57950.99), +('45698234', '12345678', '59823', 'Jordan', 'Myers', 43450.00), +('45879632', '32556978', '78962', 'Stacy', 'Diaz', 47600.50), +('54279634', '32556978', '78962', 'Marshall', 'Reese', 57180.00), +('74125852', '58894123', '47823', 'Allison', 'Garner', 54800.00), +('78932145', '14458973', '96523', 'Jasper', 'Sparks', 48650.99), +('79621463', '45896324', '32569', 'Hubert', 'Davis', 52081.32), +('85264532', '58894123', '47823', 'Paul', 'Werner', 51850.50), +('85476932', '14458973', '96523', 'Mitchell', 'Fields', 42600.00), +('85693248', '12345678', '59823', 'Alex', 'Smith', 47520.59), +('89324037', '45896324', '32569', 'Benjamin', 'Gonzales', 49250.90); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `Vehicle` +-- + +CREATE TABLE `Vehicle` ( + `VehicleID` char(3) NOT NULL, + `DealershipID` char(5) NOT NULL, + `DistributorID` char(8) NOT NULL, + `Make` varchar(40) NOT NULL, + `Model` varchar(40) NOT NULL, + `BodyType` varchar(40) NOT NULL, + `ModelYear` int(11) NOT NULL, + `Price` decimal(9,2) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci; + +-- +-- Dumping data for table `Vehicle` +-- + +INSERT INTO `Vehicle` (`VehicleID`, `DealershipID`, `DistributorID`, `Make`, `Model`, `BodyType`, `ModelYear`, `Price`) VALUES +('123', '85632', '36521789', 'Lamborghini', 'Aventador', 'Coupe', 2024, 421145.00), +('216', '47823', '12347896', 'Ferrari', 'Roma', 'Coupe', 2024, 220340.00), +('265', '32569', '45632479', 'Pagani', 'Huayra BC', 'Coupe', 2024, 2800000.00), +('328', '96523', '25863217', 'Bugatti', 'Chiron Super Sport 300+', 'Coupe', 2024, 5790000.00), +('349', '85632', '36521789', 'Lamborghini', 'Huracan STO', 'Coupe', 2024, 327835.00), +('377', '78962', '36589217', 'Maserati', 'MC20 Cielo', 'Spyder', 2024, 281000.00), +('416', '96523', '25863217', 'Rolls-Royce', 'Cullinan Black Badge', 'SUV', 2024, 388000.00), +('456', '47823', '12347896', 'Ferrari', 'SF90 Stradale', 'Coupe', 2024, 516000.00), +('486', '78962', '36589217', 'McLaren', 'Artura', 'Coupe', 2024, 185500.00), +('532', '59823', '45324895', 'Aston Martin', 'DBS', 'Coupe', 2024, 336000.00), +('554', '78962', '36589217', 'McLaren', 'GT', 'Coupe', 2024, 210000.00), +('729', '59823', '45324895', 'Bentley', 'Continental GT Speed', 'Coupe', 2024, 335000.00); + +-- +-- Indexes for dumped tables +-- + +-- +-- Indexes for table `Customer` +-- +ALTER TABLE `Customer` + ADD PRIMARY KEY (`CustomerID`), + ADD KEY `AgentID` (`AgentID`); + +-- +-- Indexes for table `Deal` +-- +ALTER TABLE `Deal` + ADD PRIMARY KEY (`DealID`), + ADD KEY `VehicleID` (`VehicleID`), + ADD KEY `AgentID` (`AgentID`), + ADD KEY `CustomerID` (`CustomerID`), + ADD KEY `InsuranceID` (`InsuranceID`); + +-- +-- Indexes for table `Dealership` +-- +ALTER TABLE `Dealership` + ADD PRIMARY KEY (`DealershipID`), + ADD KEY `DistributorID` (`DistributorID`), + ADD KEY `RegionID` (`RegionID`,`RegionZIP`); + +-- +-- Indexes for table `Distributor` +-- +ALTER TABLE `Distributor` + ADD PRIMARY KEY (`DistributorID`); + +-- +-- Indexes for table `Insurance` +-- +ALTER TABLE `Insurance` + ADD PRIMARY KEY (`InsuranceID`); + +-- +-- Indexes for table `Manager` +-- +ALTER TABLE `Manager` + ADD PRIMARY KEY (`ManagerID`), + ADD KEY `DealershipID` (`DealershipID`), + ADD KEY `DistributorID` (`DistributorID`); + +-- +-- Indexes for table `Region` +-- +ALTER TABLE `Region` + ADD PRIMARY KEY (`RegionID`,`RegionZIP`); + +-- +-- Indexes for table `Sales_Agent` +-- +ALTER TABLE `Sales_Agent` + ADD PRIMARY KEY (`AgentID`), + ADD KEY `ManagerID` (`ManagerID`), + ADD KEY `DealershipID` (`DealershipID`); + +-- +-- Indexes for table `Vehicle` +-- +ALTER TABLE `Vehicle` + ADD PRIMARY KEY (`VehicleID`), + ADD KEY `DealershipID` (`DealershipID`), + ADD KEY `DistributorID` (`DistributorID`); + +-- +-- Constraints for dumped tables +-- + +-- +-- Constraints for table `Customer` +-- +ALTER TABLE `Customer` + ADD CONSTRAINT `Customer_ibfk_1` FOREIGN KEY (`AgentID`) REFERENCES `Sales_Agent` (`AgentID`); + +-- +-- Constraints for table `Deal` +-- +ALTER TABLE `Deal` + ADD CONSTRAINT `Deal_ibfk_1` FOREIGN KEY (`VehicleID`) REFERENCES `Vehicle` (`VehicleID`), + ADD CONSTRAINT `Deal_ibfk_2` FOREIGN KEY (`AgentID`) REFERENCES `Sales_Agent` (`AgentID`), + ADD CONSTRAINT `Deal_ibfk_3` FOREIGN KEY (`CustomerID`) REFERENCES `Customer` (`CustomerID`), + ADD CONSTRAINT `Deal_ibfk_4` FOREIGN KEY (`InsuranceID`) REFERENCES `Insurance` (`InsuranceID`); + +-- +-- Constraints for table `Dealership` +-- +ALTER TABLE `Dealership` + ADD CONSTRAINT `Dealership_ibfk_1` FOREIGN KEY (`DistributorID`) REFERENCES `Distributor` (`DistributorID`), + ADD CONSTRAINT `Dealership_ibfk_2` FOREIGN KEY (`RegionID`,`RegionZIP`) REFERENCES `Region` (`RegionID`, `RegionZIP`); + +-- +-- Constraints for table `Manager` +-- +ALTER TABLE `Manager` + ADD CONSTRAINT `Manager_ibfk_1` FOREIGN KEY (`DealershipID`) REFERENCES `Dealership` (`DealershipID`), + ADD CONSTRAINT `Manager_ibfk_2` FOREIGN KEY (`DistributorID`) REFERENCES `Distributor` (`DistributorID`); + +-- +-- Constraints for table `Sales_Agent` +-- +ALTER TABLE `Sales_Agent` + ADD CONSTRAINT `Sales_Agent_ibfk_1` FOREIGN KEY (`ManagerID`) REFERENCES `Manager` (`ManagerID`), + ADD CONSTRAINT `Sales_Agent_ibfk_2` FOREIGN KEY (`DealershipID`) REFERENCES `Dealership` (`DealershipID`); + +-- +-- Constraints for table `Vehicle` +-- +ALTER TABLE `Vehicle` + ADD CONSTRAINT `Vehicle_ibfk_1` FOREIGN KEY (`DealershipID`) REFERENCES `Dealership` (`DealershipID`), + ADD CONSTRAINT `Vehicle_ibfk_2` FOREIGN KEY (`DistributorID`) REFERENCES `Distributor` (`DistributorID`); diff --git a/datasets/user-readonly-create.sql b/datasets/user-readonly-create.sql new file mode 100644 index 0000000..3f05e21 --- /dev/null +++ b/datasets/user-readonly-create.sql @@ -0,0 +1,4 @@ + +CREATE USER 'readonly'@'%' IDENTIFIED BY 'readonly'; + +GRANT SELECT, SHOW VIEW ON *.* TO 'readonly'@'%' REQUIRE NONE WITH MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0; diff --git a/datasets/user-shinobi-create.sql b/datasets/user-shinobi-create.sql new file mode 100644 index 0000000..191075c --- /dev/null +++ b/datasets/user-shinobi-create.sql @@ -0,0 +1,4 @@ + +CREATE USER 'shinobi'@'%' IDENTIFIED BY 'shinobi'; + +GRANT SELECT ON MONACO_MOTORS.* TO 'shinobi'@'%' IDENTIFIED BY 'shinobi'; diff --git a/docs/Dockerfile b/docs/Dockerfile new file mode 100644 index 0000000..a40ebfe --- /dev/null +++ b/docs/Dockerfile @@ -0,0 +1,15 @@ +FROM titom73/mkdocs AS MKDOCS_BUILD + +RUN pip install markupsafe==2.0.1 + +RUN pip install mkdocs-blog-plugin + +WORKDIR /docs + +COPY . . + +RUN mkdocs build + +FROM mengzyou/bbhttpd:1.35 + +COPY --from=MKDOCS_BUILD --chown=www:www /docs/site /home/www/html diff --git a/docs/compose.bash b/docs/compose.bash new file mode 100755 index 0000000..b72ea5d --- /dev/null +++ b/docs/compose.bash @@ -0,0 +1,19 @@ +#!/bin/bash + +## + +reset; + +clear; + +## + +set -e; + +set -x; + +## + +docker compose down --remove-orphans + +docker compose up --build -d diff --git a/docs/compose.yaml b/docs/compose.yaml new file mode 100644 index 0000000..980989f --- /dev/null +++ b/docs/compose.yaml @@ -0,0 +1,18 @@ + +services: + + shinobi-academy-database-docs: + + container_name: shinobi-academy-database-docs + + image: softwareshinobi/shinobi-academy-database-docs + + build: + + context: . + + dockerfile: Dockerfile + + ports: + + - 8080:80 diff --git a/docs/docs/.recycle/.gemini.md b/docs/docs/.recycle/.gemini.md new file mode 100644 index 0000000..9c66620 --- /dev/null +++ b/docs/docs/.recycle/.gemini.md @@ -0,0 +1,419 @@ + +## Monaco Motors Schema + +The schema defines the structure of the database, including tables, columns, data types, and relationships between tables. Here's a breakdown of the tables and their relationships: + +* **Customer:** Primary table for customer information. It has a foreign key referencing the Sales_Agent table (AgentID). + +* **Deal:** Stores information about vehicle sales. It has foreign keys referencing Customer, Sales_Agent, Vehicle, and Insurance tables (CustomerID, AgentID, VehicleID, InsuranceID). + +* **Dealership:** Information about dealerships. It has foreign keys referencing Distributor and Region tables (DistributorID, RegionID, RegionZIP). + +* **Distributor:** Information about car distributors. + +* **Insurance:** Details about insurance policies offered. + +* **Manager:** Information about dealership managers. It has foreign keys referencing +Dealership and Distributor tables (DealershipID, DistributorID). + +* **Region:** Geographic regions where dealerships are located. It's a composite primary key with RegionID and RegionZIP. + +* **Sales_Agent:** Information about sales agents employed by dealerships. It has foreign keys referencing Manager and Dealership tables (ManagerID, DealershipID). + +* **Vehicle:** Information about vehicles in the dealership's inventory. It has foreign keys referencing Dealership and Distributor tables (DealershipID, DistributorID). + + + +# gemini + +server / databases.softwareshinobi.digital + +user / shinobi + +user / shinobi + +schema / monaco-motors-dealership + + +-- +-- Database: `MONACO_MOTORS` +-- +CREATE DATABASE IF NOT EXISTS `MONACO_MOTORS` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_uca1400_ai_ci; + +USE `MONACO_MOTORS`; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `Customer` +-- + +CREATE TABLE `Customer` ( + `CustomerID` char(8) NOT NULL, + `AgentID` char(8) NOT NULL, + `CustFirstName` varchar(15) NOT NULL, + `CustLastName` varchar(15) NOT NULL, + `PhoneNumber` varchar(12) NOT NULL, + `Email` varchar(40) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci; + +-- +-- Dumping data for table `Customer` +-- + +INSERT INTO `Customer` (`CustomerID`, `AgentID`, `CustFirstName`, `CustLastName`, `PhoneNumber`, `Email`) VALUES +('24863197', '89324037', 'Mark', 'Hunt', '3347852143', 'markymark@gmail.com'), +('25463157', '85476932', 'Carly', 'Myers', '7897896325', 'carlyy478@gmail.com'), +('45682178', '85264532', 'John', 'Miller', '3568421479', 'johnboy@hotmail.com'), +('46525896', '32433468', 'Madison', 'Hart', '7892553001', 'lilmaddy@gmail.com'), +('52147932', '78932145', 'Megan', 'Sellers', '3345893321', 'megmeg@hotmail.com'), +('53247962', '85693248', 'Shelly', 'Jones', '4568423698', 'shellyjones@gmail.com'), +('63222478', '45879632', 'Connor', 'Kirk', '3346953214', 'kirkkconnor@yahoo.com'), +('64786233', '89324037', 'Logan', 'Hutchinson', '3345896789', 'loganhutch@yahoo.com'), +('74859612', '45879632', 'Barbara', 'Brown', '3348529654', 'bigbarb400@hotmail.com'), +('78527962', '54279634', 'Andrew', 'Jackson', '3345301438', 'andyjack@gmail.com'), +('78962583', '85693248', 'Morgan', 'Stanley', '4562314862', 'morgstan78@yahoo.com'), +('86321478', '85476932', 'Bill', 'Clark', '7892256541', 'bclrk@hotmail.com'), +('88895214', '74125852', 'William', 'Martin', '6502287512', 'willmart@gmail.com'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `Deal` +-- + +CREATE TABLE `Deal` ( + `DealID` char(5) NOT NULL, + `VehicleID` char(3) NOT NULL, + `AgentID` char(8) NOT NULL, + `CustomerID` char(8) NOT NULL, + `InsuranceID` char(5) DEFAULT NULL, + `DealDate` date NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci; + +-- +-- Dumping data for table `Deal` +-- + +INSERT INTO `Deal` (`DealID`, `VehicleID`, `AgentID`, `CustomerID`, `InsuranceID`, `DealDate`) VALUES +('21115', '123', '32433468', '46525896', '78222', '2023-03-27'), +('25839', '328', '78932145', '52147932', '21444', '2024-04-18'), +('33658', '216', '74125852', '88895214', '26687', '2023-04-24'), +('45523', '377', '45879632', '63222478', '11478', '2023-04-01'), +('48624', '486', '54279634', '78527962', NULL, '2023-11-08'), +('48876', '729', '85693248', '53247962', NULL, '2024-04-16'), +('55896', '554', '45879632', '74859612', '44589', '2024-02-01'), +('58221', '456', '85264532', '45682178', '22268', '2023-02-11'), +('77885', '416', '85476932', '86321478', NULL, '2024-02-21'), +('95632', '265', '89324037', '24863197', '56482', '2023-01-17'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `Dealership` +-- + +CREATE TABLE `Dealership` ( + `DealershipID` char(5) NOT NULL, + `DistributorID` char(8) NOT NULL, + `RegionID` char(3) NOT NULL, + `RegionZIP` char(5) NOT NULL, + `DealershipName` varchar(40) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci; + +-- +-- Dumping data for table `Dealership` +-- + +INSERT INTO `Dealership` (`DealershipID`, `DistributorID`, `RegionID`, `RegionZIP`, `DealershipName`) VALUES +('32569', '45632479', '578', '58203', 'Winged Lion Motors'), +('47823', '12347896', '334', '36081', 'Scuderia Speed'), +('59823', '45324895', '578', '58203', 'Velocity Auto Haus'), +('78962', '36589217', '334', '36081', 'Tridente Motors'), +('85632', '36521789', '356', '36079', 'Galleria Motors'), +('96523', '25863217', '356', '36079', 'Royal Stallion Motors'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `Distributor` +-- + +CREATE TABLE `Distributor` ( + `DistributorID` char(8) NOT NULL, + `DistributorName` varchar(40) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci; + +-- +-- Dumping data for table `Distributor` +-- + +INSERT INTO `Distributor` (`DistributorID`, `DistributorName`) VALUES +('12347896', 'Pfaff Reserve'), +('25863217', 'EuroCar'), +('36521789', 'Redline European'), +('36589217', 'Romans International'), +('45324895', 'European Exotic Center'), +('45632479', 'James Edition'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `Insurance` +-- + +CREATE TABLE `Insurance` ( + `InsuranceID` char(5) NOT NULL, + `PolicyType` varchar(15) NOT NULL, + `RenewalDate` date NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci; + +-- +-- Dumping data for table `Insurance` +-- + +INSERT INTO `Insurance` (`InsuranceID`, `PolicyType`, `RenewalDate`) VALUES +('11478', 'Full Coverage', '2024-04-01'), +('21444', 'Full Coverage', '2020-04-18'), +('22268', 'Liability', '2024-02-11'), +('26687', 'Liability', '2024-04-24'), +('44589', 'Full Coverage', '2020-02-01'), +('56482', 'Full Coverage', '2024-01-17'), +('78222', 'Full Coverage', '2024-03-27'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `Manager` +-- + +CREATE TABLE `Manager` ( + `ManagerID` char(8) NOT NULL, + `DealershipID` char(5) NOT NULL, + `DistributorID` char(8) NOT NULL, + `MngrFirstName` varchar(15) NOT NULL, + `MngrLastName` varchar(15) NOT NULL, + `MngrSalary` decimal(8,2) NOT NULL, + `MngrBonus` decimal(8,2) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci; + +-- +-- Dumping data for table `Manager` +-- + +INSERT INTO `Manager` (`ManagerID`, `DealershipID`, `DistributorID`, `MngrFirstName`, `MngrLastName`, `MngrSalary`, `MngrBonus`) VALUES +('12345678', '59823', '45324895', 'John', 'Boling', 87900.00, 5100.23), +('14458973', '96523', '25863217', 'Henry', 'Miller', 79025.99, 5200.60), +('32556978', '78962', '36589217', 'Rachel', 'Smith', 81500.10, 2400.00), +('45896324', '32569', '45632479', 'Sally', 'Mae', 75000.99, 4250.50), +('52689974', '85632', '36521789', 'Lamar', 'Jackson', 91250.10, NULL), +('58894123', '47823', '12347896', 'Kevin', 'Rogers', 71250.00, 8450.00); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `Region` +-- + +CREATE TABLE `Region` ( + `RegionID` char(3) NOT NULL, + `RegionZIP` char(5) NOT NULL, + `RegionName` varchar(15) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci; + +-- +-- Dumping data for table `Region` +-- + +INSERT INTO `Region` (`RegionID`, `RegionZIP`, `RegionName`) VALUES +('334', '36081', 'EMEA'), +('356', '36079', 'APJ'), +('578', '58203', 'AMS'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `Sales_Agent` +-- + +CREATE TABLE `Sales_Agent` ( + `AgentID` char(8) NOT NULL, + `ManagerID` char(8) NOT NULL, + `DealershipID` char(5) NOT NULL, + `AgentFirstName` varchar(15) NOT NULL, + `AgentLastName` varchar(15) NOT NULL, + `AgentSalary` decimal(9,2) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci; + +-- +-- Dumping data for table `Sales_Agent` +-- + +INSERT INTO `Sales_Agent` (`AgentID`, `ManagerID`, `DealershipID`, `AgentFirstName`, `AgentLastName`, `AgentSalary`) VALUES +('28547962', '52689974', '85632', 'Jack', 'Hublot', 61258.00), +('32433468', '52689974', '85632', 'Jennifer', 'Martin', 57950.99), +('45698234', '12345678', '59823', 'Jordan', 'Myers', 43450.00), +('45879632', '32556978', '78962', 'Stacy', 'Diaz', 47600.50), +('54279634', '32556978', '78962', 'Marshall', 'Reese', 57180.00), +('74125852', '58894123', '47823', 'Allison', 'Garner', 54800.00), +('78932145', '14458973', '96523', 'Jasper', 'Sparks', 48650.99), +('79621463', '45896324', '32569', 'Hubert', 'Davis', 52081.32), +('85264532', '58894123', '47823', 'Paul', 'Werner', 51850.50), +('85476932', '14458973', '96523', 'Mitchell', 'Fields', 42600.00), +('85693248', '12345678', '59823', 'Alex', 'Smith', 47520.59), +('89324037', '45896324', '32569', 'Benjamin', 'Gonzales', 49250.90); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `Vehicle` +-- + +CREATE TABLE `Vehicle` ( + `VehicleID` char(3) NOT NULL, + `DealershipID` char(5) NOT NULL, + `DistributorID` char(8) NOT NULL, + `Make` varchar(40) NOT NULL, + `Model` varchar(40) NOT NULL, + `BodyType` varchar(40) NOT NULL, + `ModelYear` int(11) NOT NULL, + `Price` decimal(9,2) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci; + +-- +-- Dumping data for table `Vehicle` +-- + +INSERT INTO `Vehicle` (`VehicleID`, `DealershipID`, `DistributorID`, `Make`, `Model`, `BodyType`, `ModelYear`, `Price`) VALUES +('123', '85632', '36521789', 'Lamborghini', 'Aventador', 'Coupe', 2024, 421145.00), +('216', '47823', '12347896', 'Ferrari', 'Roma', 'Coupe', 2024, 220340.00), +('265', '32569', '45632479', 'Pagani', 'Huayra BC', 'Coupe', 2024, 2800000.00), +('328', '96523', '25863217', 'Bugatti', 'Chiron Super Sport 300+', 'Coupe', 2024, 5790000.00), +('349', '85632', '36521789', 'Lamborghini', 'Huracan STO', 'Coupe', 2024, 327835.00), +('377', '78962', '36589217', 'Maserati', 'MC20 Cielo', 'Spyder', 2024, 281000.00), +('416', '96523', '25863217', 'Rolls-Royce', 'Cullinan Black Badge', 'SUV', 2024, 388000.00), +('456', '47823', '12347896', 'Ferrari', 'SF90 Stradale', 'Coupe', 2024, 516000.00), +('486', '78962', '36589217', 'McLaren', 'Artura', 'Coupe', 2024, 185500.00), +('532', '59823', '45324895', 'Aston Martin', 'DBS', 'Coupe', 2024, 336000.00), +('554', '78962', '36589217', 'McLaren', 'GT', 'Coupe', 2024, 210000.00), +('729', '59823', '45324895', 'Bentley', 'Continental GT Speed', 'Coupe', 2024, 335000.00); + +-- +-- Indexes for dumped tables +-- + +-- +-- Indexes for table `Customer` +-- +ALTER TABLE `Customer` + ADD PRIMARY KEY (`CustomerID`), + ADD KEY `AgentID` (`AgentID`); + +-- +-- Indexes for table `Deal` +-- +ALTER TABLE `Deal` + ADD PRIMARY KEY (`DealID`), + ADD KEY `VehicleID` (`VehicleID`), + ADD KEY `AgentID` (`AgentID`), + ADD KEY `CustomerID` (`CustomerID`), + ADD KEY `InsuranceID` (`InsuranceID`); + +-- +-- Indexes for table `Dealership` +-- +ALTER TABLE `Dealership` + ADD PRIMARY KEY (`DealershipID`), + ADD KEY `DistributorID` (`DistributorID`), + ADD KEY `RegionID` (`RegionID`,`RegionZIP`); + +-- +-- Indexes for table `Distributor` +-- +ALTER TABLE `Distributor` + ADD PRIMARY KEY (`DistributorID`); + +-- +-- Indexes for table `Insurance` +-- +ALTER TABLE `Insurance` + ADD PRIMARY KEY (`InsuranceID`); + +-- +-- Indexes for table `Manager` +-- +ALTER TABLE `Manager` + ADD PRIMARY KEY (`ManagerID`), + ADD KEY `DealershipID` (`DealershipID`), + ADD KEY `DistributorID` (`DistributorID`); + +-- +-- Indexes for table `Region` +-- +ALTER TABLE `Region` + ADD PRIMARY KEY (`RegionID`,`RegionZIP`); + +-- +-- Indexes for table `Sales_Agent` +-- +ALTER TABLE `Sales_Agent` + ADD PRIMARY KEY (`AgentID`), + ADD KEY `ManagerID` (`ManagerID`), + ADD KEY `DealershipID` (`DealershipID`); + +-- +-- Indexes for table `Vehicle` +-- +ALTER TABLE `Vehicle` + ADD PRIMARY KEY (`VehicleID`), + ADD KEY `DealershipID` (`DealershipID`), + ADD KEY `DistributorID` (`DistributorID`); + +-- +-- Constraints for dumped tables +-- + +-- +-- Constraints for table `Customer` +-- +ALTER TABLE `Customer` + ADD CONSTRAINT `Customer_ibfk_1` FOREIGN KEY (`AgentID`) REFERENCES `Sales_Agent` (`AgentID`); + +-- +-- Constraints for table `Deal` +-- +ALTER TABLE `Deal` + ADD CONSTRAINT `Deal_ibfk_1` FOREIGN KEY (`VehicleID`) REFERENCES `Vehicle` (`VehicleID`), + ADD CONSTRAINT `Deal_ibfk_2` FOREIGN KEY (`AgentID`) REFERENCES `Sales_Agent` (`AgentID`), + ADD CONSTRAINT `Deal_ibfk_3` FOREIGN KEY (`CustomerID`) REFERENCES `Customer` (`CustomerID`), + ADD CONSTRAINT `Deal_ibfk_4` FOREIGN KEY (`InsuranceID`) REFERENCES `Insurance` (`InsuranceID`); + +-- +-- Constraints for table `Dealership` +-- +ALTER TABLE `Dealership` + ADD CONSTRAINT `Dealership_ibfk_1` FOREIGN KEY (`DistributorID`) REFERENCES `Distributor` (`DistributorID`), + ADD CONSTRAINT `Dealership_ibfk_2` FOREIGN KEY (`RegionID`,`RegionZIP`) REFERENCES `Region` (`RegionID`, `RegionZIP`); + +-- +-- Constraints for table `Manager` +-- +ALTER TABLE `Manager` + ADD CONSTRAINT `Manager_ibfk_1` FOREIGN KEY (`DealershipID`) REFERENCES `Dealership` (`DealershipID`), + ADD CONSTRAINT `Manager_ibfk_2` FOREIGN KEY (`DistributorID`) REFERENCES `Distributor` (`DistributorID`); + +-- +-- Constraints for table `Sales_Agent` +-- +ALTER TABLE `Sales_Agent` + ADD CONSTRAINT `Sales_Agent_ibfk_1` FOREIGN KEY (`ManagerID`) REFERENCES `Manager` (`ManagerID`), + ADD CONSTRAINT `Sales_Agent_ibfk_2` FOREIGN KEY (`DealershipID`) REFERENCES `Dealership` (`DealershipID`); + +-- +-- Constraints for table `Vehicle` +-- +ALTER TABLE `Vehicle` + ADD CONSTRAINT `Vehicle_ibfk_1` FOREIGN KEY (`DealershipID`) REFERENCES `Dealership` (`DealershipID`), + ADD CONSTRAINT `Vehicle_ibfk_2` FOREIGN KEY (`DistributorID`) REFERENCES `Distributor` (`DistributorID`); + +this is a public mariadb database. practice your SQL skills and data analysis skills on my data. explain the database. and the schema. and the data tht th students. explain how to connect using your favorite browser. diff --git a/docs/docs/.recycle/sql-101.md b/docs/docs/.recycle/sql-101.md new file mode 100644 index 0000000..2c5fe56 --- /dev/null +++ b/docs/docs/.recycle/sql-101.md @@ -0,0 +1,40 @@ +# SQL 101 + +**Dive into the World of Exotic Cars: A Data Analyst's Playground** + +**Unleash the Power of SQL** + +Imagine having a database filled with data on high-end luxury cars, from sleek sports cars to opulent SUVs. This Monaco Motors Dealership database is your playground to practice SQL queries and data analysis techniques. + +**What Can You Do with This Data?** + +As a budding data analyst, you can: + +* **Extract Insights:** Use SQL to query the database and extract valuable insights. For example, you could identify the top-selling car models, analyze customer demographics, or track sales trends over time. +* **Build Data Models:** Create data models to represent the relationships between different entities in the database. This will help you visualize the data and understand its structure. +* **Data Visualization:** Use data visualization tools like Tableau or Power BI to create stunning charts and graphs that bring your data to life. You could visualize sales figures, customer preferences, or inventory levels. +* **Predictive Analytics:** Explore predictive modeling techniques to forecast future sales, identify potential customers, or optimize inventory management. + +**Practical SQL Examples:** + +Here are some practical SQL queries to get you started: + +* **Find all Ferrari models:** + ```sql + SELECT * FROM Vehicle WHERE Make = 'Ferrari'; + ``` +* **Calculate the average price of Lamborghini cars:** + ```sql + SELECT AVG(Price) FROM Vehicle WHERE Make = 'Lamborghini'; + ``` +* **Identify the top 5 best-selling car models:** + ```sql + SELECT TOP 5 VehicleID, COUNT(*) AS SalesCount + FROM Deal + GROUP BY VehicleID + ORDER BY SalesCount DESC; + ``` + +**Start Your Data Analysis Journey Today** + +By working with this real-world dataset, you can develop your SQL skills, learn data analysis techniques, and gain valuable experience. So, dive into the data and unlock the secrets of the Monaco Motors Dealership! diff --git a/docs/docs/Introduction-To-Databases/004-basic-syntax.md b/docs/docs/Introduction-To-Databases/004-basic-syntax.md new file mode 100644 index 0000000..5cff378 --- /dev/null +++ b/docs/docs/Introduction-To-Databases/004-basic-syntax.md @@ -0,0 +1,145 @@ +# Basic Syntax + +In this chapter, we will go over the basic SQL syntax. + +SQL statements are basically the 'commands' that you run against a specific database. Through the SQL statements, you are telling MySQL what you want it to do, for example, if you wanted to get the `username` of all of your users stored in the `users` table, you would run the following SQL statement: + +```sql +SELECT username FROM users; +``` + +Rundown of the statement: + +* `SELECT`: First, we specify the `SELECT` keyword, which indicates that we want to select some data from the database. Other popular keywords are: `INSERT`, `UPDATE` and `DELETE`. +* `username`: Then we specify which column we want to select. +* `FROM users`: After that, we specify the table that we want to select the data from using the `FROM` keyword. +* The semicolon `;` is highly recommended to put at the end. Standard SQL syntax requires it, but some "Database Management Systems' (DBMS)" are tolerant about it, but it's not worth the risk. + +If you run the above statement, you will get no results as the new `users` table that we've just created is empty. + +> As a good practice, all SQL keywords should be with uppercase, however, it would work just fine if you use lower case as well. + +Let's go ahead and cover the basic operations next. + +## INSERT + +To add data to your database, you would use the `INSERT` statement. + +Let's use the table that we created in the last chapter and insert 1 user into our `users` table: + +```sql +INSERT INTO users (username, email, active) +VALUES ('bobby', 'bobby@bobbyiliev.com', true); +``` + +Rundown of the insert statement: + +* `INSERT INTO`: first, we specify the `INSERT INTO` keyword, which tells MySQL that we want to insert data a table. +* `users (username, email, active)`: then, we specify the table name `users` and the columns that we want to insert data into. +* `VALUES`: then, we specify the values that we want to insert in. The order of attributes is the same as in `users (...)`. + +## SELECT + +Once we've inserted that user, let's go ahead and retrieve the information. + +To retrieve information from your database, you could use the `SELECT` statement: + +```sql +SELECT * FROM users; +``` + +Output: + +``` ++----+----------+-------+----------+--------+---------------+ +| id | username | about | birthday | active | email | ++----+----------+-------+----------+--------+---------------+ +| 1 | bobby | NULL | NULL | 1 | bobby@b...com | ++----+----------+-------+----------+--------+---------------+ +``` + +We specify `*` right after the `SELECT` keyword, this means that we want to get all of the columns from the `users` table. + +If we wanted to retrieve only the `username` and the `email` columns instead, we would change the statement to: + +```sql +SELECT username, email FROM users; +``` + +This will return all of the users, but as of the time being we have only 1: + +``` ++----------+----------------------+ +| username | email | ++----------+----------------------+ +| bobby | bobby@bobbyiliev.com | ++----------+----------------------+ +``` + +## UPDATE + +In order to modify data in your database, you could use the `UPDATE` statement. + +The syntax would look like this: + +```sql +UPDATE users SET username='bobbyiliev' WHERE id=1; +``` + +Rundown of the statement: + +* `UPDATE users`: First, we specify the `UPDATE` keyword followed by the table that we want to update. +* `SET username='bobbyiliev'`: Then we specify the columns that we want to update and the new value that we want to set. +* `WHERE id=1`: Finally, by using the `WHERE` clause, we specify which user should be updated. In our case it is the user with ID 1. + +> NOTE: If we don't specify a `WHERE` clause, all of the entries inside the `users` table would be updated, and all users would have the `username` set to `bobbyiliev`. You need to be careful when you use the `UPDATE` statement without a `WHERE` clause, as every single row will be updated. + +We are going to cover `WHERE` more in-depth in the next few chapters. + +## DELETE + +As the name suggests, the `DELETE` statement would remove data from your database. + +The syntax is as follows: + +```sql +DELETE FROM users WHERE id=1; +``` + +Similar to the `UPDATE` statement, if you don't specify a `WHERE` clause, all of the entries from the table will be affected, meaning that all of your users will be deleted. + +## Comments + +In case that you are writing a larger SQL script, it might be helpful to add some comments so that later on, when you come back to the script, you would know what each line does. + +As with all programming languages, you can add comments in SQL as well. + +There are two types of comments: + +* Inline comments: + +To do so, you just need to add `--` before the text that you want to comment out: + +```sql +SELECT * FROM users; -- Get all users +``` + +* Multiple-line comments: + +Similar to some other programming languages in order to comment multiple lines, you could wrap the text in `/*` `*/` as follows: + +```sql +/* +Get all of the users +from your database +*/ +SELECT * FROM users; +``` + +You could write that in a `.sql` file and then run it later on, or execute the few lines directly. + +## Conclusion + +Those were some of the most common basic SQL statements. + +In the next chapters, we are going to go over each of the above statements more in-depth. diff --git a/docs/docs/Introduction-To-Databases/005-select.md b/docs/docs/Introduction-To-Databases/005-select.md new file mode 100644 index 0000000..40b377e --- /dev/null +++ b/docs/docs/Introduction-To-Databases/005-select.md @@ -0,0 +1,359 @@ +# SELECT + +As we briefly covered in the previous chapter, the `SELECT` statement allows us to retrieve data from single or multiple tables on the database. In this chapter, we will be performing the query on a single table. + +It corresponds to the projection operation of Relational Algebra. + +You can use `SELECT` to get all of your users or a list of users that match a certain criteria. + +Before we dive into the `SELECT` statement let's quickly create a database: + +```sql +CREATE DATABASE sql_demo; +``` + +Switch to that database: + +```sql +USE sql_demo; +``` + +Create a new users table: + +```sql +CREATE TABLE users +( + id INT PRIMARY KEY AUTO_INCREMENT, + username VARCHAR(255) NOT NULL, + about TEXT, + email VARCHAR(255), + birthday DATE, + active BOOL +); +``` + +Insert some data that we could work with: + +```sql +INSERT INTO users + ( username, email, active ) +VALUES + ('bobby', 'b@devdojo.com', true), + ('devdojo', 'd@devdojo.com', false), + ('tony', 't@devdojo.com', true); +``` + +Output: + +``` +Query OK, 3 rows affected (0.00 sec) +Records: 3 Duplicates: 0 Warnings: 0 +``` + +We are going to learn more about the `INSERT` statement in the following chapters. + +## SELECT all columns + +Now that we've got some data in the `users` table, let's go ahead and retrieve all of the entries from that table: + +```sql +SELECT * FROM users; +``` + +Rundown of the statement: + +* `SELECT`: First, we specify the action that we want to execute, in our case, we want to select or get some data from the database. +* `*`: The star here indicates that we want to get all of the columns associated with the table that we are selecting from. +* `FROM`: The from statement tells MySQL which table we want to select the data from. You need to keep in mind that you can select from multiple tables, but this is a bit more advanced, and we are going to cover this in the next few chapters. +* `users`: This is the table name that we want to select the data from. + +This will return all of the entries in the `users` table along with all of the columns: + +``` ++----+----------+-------+----------+--------+---------------+ +| id | username | about | birthday | active | email | ++----+----------+-------+----------+--------+---------------+ +| 1 | bobby | NULL | NULL | 1 | b@devdojo.com | +| 2 | devdojo | NULL | NULL | 0 | d@devdojo.com | +| 3 | tony | NULL | NULL | 1 | t@devdojo.com | ++----+----------+-------+----------+--------+---------------+ +3 rows in set (0.00 sec) +``` + +As you can see, we get a list of the 3 users that we've just created, including all of the columns in that table. In some cases, the table might have a lot of columns, and you might not want to see all of them. For example, we have the `about` and `birthday` columns that are all `NULL` at the moment. So let's see how we could limit that and get only a list of specific columns. + +## Pattern matching +SQL pattern matching let's you to search for patterns if you don't know the exact word or phrase you are looking for. To do this, we use so-called wildcard characters to match a pattern together with LIKE and ILIKE operators. + +Two of the most common wildcard characters are `_` and `%`. + +`_` matches any single character and `%` matches an arbitrary number of characters. + +Let's see an example how you would look for a `username` ending with `y`: + +```sql +SELECT * FROM users WHERE username LIKE '%y'; +``` + +Output: +``` ++----+----------+-------+----------+--------+---------------+ +| id | username | about | birthday | active | email | ++----+----------+-------+----------+--------+---------------+ +| 1 | bobby | NULL | NULL | 1 | b@devdojo.com | +| 3 | tony | NULL | NULL | 1 | t@devdojo.com | ++----+----------+-------+----------+--------+---------------+ +``` +As you can see above, we used `%` to match any number of characters preceding the character `y`. + +If we know the exact number of characters we want to match, we can use `_`. Each `_` represents a single character. + +So, if we want to look up an username that has `e` as its second character, we would do something like this: + +```sql +SELECT * FROM users WHERE username LIKE '_e%'; +``` + +Output: +``` ++----+----------+-------+----------+--------+---------------+ +| id | username | about | birthday | active | email | ++----+----------+-------+----------+--------+---------------+ +| 2 | devdojo | NULL | NULL | 0 | d@devdojo.com | ++----+----------+-------+----------+--------+---------------+ +``` + +Please, keep in mind that `LIKE` operator is case sensitive, meaning it won't mach capital letters with lowercase letters and vice versa. If you wish to ignore capitalization, use `ILIKE` operator instead. + + +## Formatting + +As we mentioned in the previous chapters, each SQL statement needs to end with a semi-colon: `;`. Alternatively, rather than using a semi-colon, you could use the `\G` characters which would format the output in a list rather than a table. + +The syntax is absolutely the same but you just change the `;` with `\G`: + +```sql +SELECT * FROM users \G +``` + +The output will be formatted like this: + +``` +*************************** 1. row *************************** + id: 1 +username: bobby + about: NULL +birthday: NULL + active: 1 + email: b@devdojo.com +*************************** 2. row *************************** + id: 2 +username: devdojo + about: NULL +birthday: NULL + active: 0 + email: d@devdojo.com +... +``` + +This is very handy whenever your table consists of a large number of columns and they can't fit on the screen, which makes it very hard to read the result set. + +## SELECT specific columns only + +You could limit this to a specific set of columns. Let's say that you only needed the `username` and the `active` columns. In this case, you would change the `*` symbol with the columns that you want to select divided by a comma: + +```sql +SELECT username,active FROM users; +``` + +Output: + +``` ++----------+--------+ +| username | active | ++----------+--------+ +| bobby | 1 | +| devdojo | 0 | +| tony | 1 | ++----------+--------+ +``` + +As you can see, we are getting back only the 2 columns that we've specified in the `SELECT` statement. + +> **NOTE:** _SQL names are case insensitive. For example, username ≡ USERNAME ≡ userName._ + +## SELECT with no FROM Clause + +In a SQL statement, a column can be a literal with no `FROM` clause. + +```sql +SELECT 'Sunil' as username; +``` + +Output: + +``` ++----------+ +| username | ++----------+ +| Sunil | ++----------+ +``` + +## SELECT with Arithmetic Operations + +The select clause can contain arithmetic expressions involving the operation +, –, *, and /. + +```sql +SELECT username, active*5 as new_active FROM users; +``` + +Output: + +``` ++----------+------------+ +| username | new_active | ++----------+------------+ +| bobby | 5 | +| devdojo | 0 | +| tony | 5 | ++----------+------------+ +``` + +## LIMIT + +The `LIMIT` clause is very handy in case that you want to limit the number of results that you get back. For example, at the moment, we have 3 users in our database, but let's say that you only wanted to get 1 entry back when you run the `SELECT` statement. + +This can be achieved by adding the `LIMIT` clause at the end of your statement, followed by the number of entries that you want to get. For example, let's say that we wanted to get only 1 entry back. We would run the following query: + +```sql +SELECT * FROM users LIMIT 1; +``` + +Output: + +``` ++----+----------+-------+----------+--------+---------------+ +| id | username | about | birthday | active | email | ++----+----------+-------+----------+--------+---------------+ +| 2 | bobby | NULL | NULL | 1 | b@devdojo.com | ++----+----------+-------+----------+--------+---------------+ +``` + +If you wanted to get 2 entries, you would change `LIMIT 2` and so on. + +## COUNT + +In case that you wanted to get only the number of entries in a specific column, you could use the `COUNT` function. This is a function that I personally use very often. + +The syntax is the following: + +```sql +SELECT COUNT(*) FROM users; +``` + +Output: + +``` ++----------+ +| COUNT(*) | ++----------+ +| 3 | ++----------+ +``` + +## MIN, MAX, AVG, and SUM + +Another useful set of functions similar to `COUNT` that would make your life easier are: + +* `MIN`: This would give you the smallest value of a specific column. For example, if you had an online shop and you wanted to get the lowest price, you would use the `MIN` function. In our case, if we wanted to get the lowest user ID, we would run the following: + +```sql +SELECT MIN(id) FROM users; +``` + +This would return `1` as the lowest user ID that we have is 1. + +* `MAX`: Just like `MIN`, but it would return the highest value: + +```sql +SELECT MAX(id) FROM users; +``` + +In our case, this would be `3` as we have only 3 users, and the highest value of the `id` column is 3. + +* `AVG`: As the name suggests, it would sum up all of the values of a specific column and return the average value. As we have 3 users with ids 1, 2, and 3, the average would be 6 divided by 3 users which is 2. + +```sql +SELECT AVG(id) FROM users; +``` + +* `SUM`: This function takes all of the values from the specified column and sums them up: + +```sql +SELECT SUM(id) FROM users; +``` + +## DISTINCT + +In some cases, you might have duplicate entries in a table, and in order to get only the unique values, you could use `DISTINCT`. + +To better demonstrate this, let's run the insert statement one more time so that we could duplicate the existing users and have 6 users in the users table: + +```sql +INSERT INTO users + ( username, email, active ) +VALUES + ('bobby', 'b@devdojo.com', true), + ('devdojo', 'd@devdojo.com', false), + ('tony', 't@devdojo.com', true); +``` + +Now, if you run `SELECT COUNT(*) FROM users;` you would get `6` back. + +Let's also select all users and show only the `username` column: + +```sql +SELECT username FROM users; +``` + +Output: + +``` ++----------+ +| username | ++----------+ +| bobby | +| devdojo | +| tony | +| bobby | +| devdojo | +| tony | ++----------+ +``` + +As you can see, each name is present multiple times in the list. We have `bobby`, `devdjo` and `tony` showing up twice. + +If we wanted to show only the unique `usernames`, we could add the `DISTINCT` keyword to our select statement: + +```sql +SELECT DISTINCT username FROM users; +``` + +Output: + +``` ++----------+ +| username | ++----------+ +| bobby | +| devdojo | +| tony | ++----------+ +``` + +As you can see, the duplicate entries have been removed from the output. + +## Conclusion + +The `SELECT` statement is essential whenever working with SQL. In the next chapter, we are going to learn how to use the `WHERE` clause and take the `SELECT` statements to the next level. diff --git a/docs/docs/Introduction-To-Databases/006-where.md b/docs/docs/Introduction-To-Databases/006-where.md new file mode 100644 index 0000000..0026f9a --- /dev/null +++ b/docs/docs/Introduction-To-Databases/006-where.md @@ -0,0 +1,225 @@ +# WHERE + +The `WHERE` clause allows you to specify different conditions so that you could filter out the data and get a specific result set. + +You would add the `WHERE` clause after the `FROM` clause. + +The syntax would look like this: + +```sql +SELECT column_name FROM table_name WHERE column=some_value; +``` + +## WHERE Clause example + +If we take the example `users` table from the last chapter, let's say that we wanted to get only the active users. The SQL statement would look like this: + +```sql +SELECT DISTINCT username, email, activem FROM users WHERE active=true; +``` + +Output: + +``` ++----------+---------------+--------+ +| username | email | active | ++----------+---------------+--------+ +| bobby | b@devdojo.com | 1 | +| tony | t@devdojo.com | 1 | ++----------+---------------+--------+ +``` + +As you can see, we are only getting `tony` and `bobby` back as their `active` column is `true` or `1`. If we wanted to get the inactive users, we would have to change the `WHERE` clause and set the `active` to `false`: + +``` ++----------+---------------+--------+ +| username | email | active | ++----------+---------------+--------+ +| devdojo | d@devdojo.com | 0 | ++----------+---------------+--------+ +``` + +As another example, let's say that we wanted to select all users with the username `bobby`. The query, in this case, would be: + +```sql +SELECT username, email, active FROM users WHERE username='bobby'; +``` + +The output would look like this: + +``` ++----------+---------------+--------+ +| username | email | active | ++----------+---------------+--------+ +| bobby | b@devdojo.com | 1 | +| bobby | b@devdojo.com | 1 | ++----------+---------------+--------+ +``` + +We are getting 2 entries back as we have 2 users in our database with the username `bobby`. + +## Operators + +In the example, we used the `=` operator, which checks if the result set matches the value that we are looking for. + +A list of popular operators are: + +* `!=` : Not equal operator +* `>` : Greater than +* `>=` : Greater than or equal operator +* `<` : Less than operator +* `<=` : Less than or equal operator + +For more information about other available operators, make sure to check the official documentation [here](https://dev.mysql.com/doc/refman/8.0/en/non-typed-operators.html). + +## AND keyword + +In some cases, you might want to specify multiple criteria. For example, you might want to get all users that are active, and the username matches a specific value. This could be achieved with the `AND` keyword. + +Syntax: + +```sql +SELECT * FROM users WHERE username='bobby' AND active=true; +``` + +The result set would contain the data that matches both conditions. In our case, the output would be: + +``` ++----+----------+-------+----------+--------+---------------+ +| id | username | about | birthday | active | email | ++----+----------+-------+----------+--------+---------------+ +| 2 | bobby | NULL | NULL | 1 | b@devdojo.com | +| 5 | bobby | NULL | NULL | 1 | b@devdojo.com | ++----+----------+-------+----------+--------+---------------+ +``` + +If we were to change the `AND` statement to `active=false`, we would not get any results back as none of the entries in our database match that condition: + +```sql +SELECT * FROM users WHERE username='bobby' AND active=false; +``` +``` +-- Output: +Empty set (0.01 sec) +``` + +## OR keyword + +In some cases, you might want to specify multiple criteria. For example, you might want to get all users that are active, or their username matches a specific value. This could be achieved with the `OR` keyword. + +As with any other programming language, the main difference between `AND` and `OR` is that with `AND`, the result would only return the values that match the two conditions, and with `OR`, you would get a result that matches either of the conditions. + +For example, if we were to run the same query as above but change the `AND` to `OR`, we would get all users that have the username `bobby` and also all users that are not active: + +```sql +SELECT * FROM users WHERE username='bobby' OR active=false; +``` + +Output: + +``` ++----+----------+-------+----------+--------+---------------+ +| id | username | about | birthday | active | email | ++----+----------+-------+----------+--------+---------------+ +| 2 | bobby | NULL | NULL | 1 | b@devdojo.com | +| 3 | devdojo | NULL | NULL | 0 | d@devdojo.com | +| 5 | bobby | NULL | NULL | 1 | b@devdojo.com | +| 6 | devdojo | NULL | NULL | 0 | d@devdojo.com | ++----+----------+-------+----------+--------+---------------+ +``` + +## LIKE operator + +Unlike the `=` operator, the `LIKE` operator allows you to do wildcard matching similar to the `*` symbol in Linux. + +For example, if you wanted to get all users that have the `y` letter in them, you would run the following: + +```sql +SELECT * FROM users WHERE username LIKE '%y%'; +``` + +Output + +``` ++----+----------+-------+----------+--------+---------------+ +| id | username | about | birthday | active | email | ++----+----------+-------+----------+--------+---------------+ +| 2 | bobby | NULL | NULL | 1 | b@devdojo.com | +| 4 | tony | NULL | NULL | 1 | t@devdojo.com | ++----+----------+-------+----------+--------+---------------+ +``` + +As you can see, we are getting only `tony` and `bobby` but not `devdojo` as there is no `y` in `devdojo`. + +This is quite handy when you are building some search functionality for your application. + +# IN operator + +The `IN` operator allows you to provide a list expression and would return the results that match that list of values. + +For example, if you wanted to get all users that have the username `bobby` and `devdojo`, you could use the following: + +```sql +SELECT * FROM users WHERE username IN ('bobby', 'devdojo'); +``` + +Output: + +``` ++----+----------+-------+----------+--------+---------------+ +| id | username | about | birthday | active | email | ++----+----------+-------+----------+--------+---------------+ +| 2 | bobby | NULL | NULL | 1 | b@devdojo.com | +| 3 | devdojo | NULL | NULL | 0 | d@devdojo.com | +| 5 | bobby | NULL | NULL | 1 | b@devdojo.com | +| 6 | devdojo | NULL | NULL | 0 | d@devdojo.com | ++----+----------+-------+----------+--------+---------------+ +``` + +This allows you to simplify your `WHERE` expression so that you don't have to add numerous `OR` statements. + +## IS operator + +If you were to run `SELECT * FROM users WHERE about=NULL;` you would get an empty result set as the `=` operator can't be used to check for NULL values. Instead, you would need to use the `IS` operator instead. + +The `IS` operator is only used to check `NULL` values, and the syntax is the following: + +```sql +SELECT * FROM users WHERE about IS NULL; +``` + +If you wanted to get the results where the value is not NULL, you just need to change `IS` to `IS NOT`: + + +```sql +SELECT * FROM users WHERE about IS NOT NULL; +``` + +## BETWEEN operator + +The `BETWEEN` operator allows to select value with a given range.The values can be numbers, text, or dates. +BETWEEN operator is inclusive: begin and end values are included. + +For Example if you want to select those user which have id between 3 and 6. + +```sql +SELECT * FROM users WHERE id BETWEEN 3 AND 6; +``` + +Output: + +``` ++----+----------+-------+----------+--------+---------------+ +| id | username | about | birthday | active | email | ++----+----------+-------+----------+--------+---------------+ +| 3 | devdojo | NULL | NULL | 0 | d@devdojo.com | +| 5 | bobby | NULL | NULL | 1 | b@devdojo.com | +| 6 | devdojo | NULL | NULL | 0 | d@devdojo.com | ++----+----------+-------+----------+--------+---------------+ +``` + +## Conclusion + +In this chapter, you've learned how to use the `WHERE` clause with different operators to get different type of results based on the parameters that you provide. + +In the next chapter, we will learn how to order the result set. \ No newline at end of file diff --git a/docs/docs/Introduction-To-Databases/007-order-and-group-by.md b/docs/docs/Introduction-To-Databases/007-order-and-group-by.md new file mode 100644 index 0000000..3e828f1 --- /dev/null +++ b/docs/docs/Introduction-To-Databases/007-order-and-group-by.md @@ -0,0 +1,143 @@ +# Sorting with ORDER and GROUP BY + +In the last chapter, you've learned how to use the `SELECT` statement with the `WHERE` clause and filter the result set based on some conditions. + +More often than not, you would want to order the results in a specific way based on a particular column. For example, you might want to order the users alphabetically based on their username. + +In this chapter, you will learn how to use the `ORDER BY` and `GROUP BY` clauses. + +## ORDER BY + +The main thing that you need to keep in mind when using `ORDER BY` is to specify the column or columns you want to order by. In case you want to specify multiple columns to order by, you need to separate each column with a comma. + +If we were to run the following statement without providing an `ORDER BY` clause: + +```sql +SELECT id, username FROM users; +``` + +We will get the following output: + +``` ++----+----------+ +| id | username | ++----+----------+ +| 2 | bobby | +| 3 | devdojo | +| 4 | tony | +| 5 | bobby | +| 6 | devdojo | +| 7 | tony | ++----+----------+ +``` + +As you can see, the result set is sorted by the primary key, which, in our case, is each user's id. If we wanted to sort the output by `username`, we would run the following query: + +```sql +SELECT id, username FROM users ORDER BY username; +``` + +> Note: The `ORDER BY` statement is followed by the column's name that we want to order by. + +The output, in this case, will be: + +``` ++----+----------+ +| id | username | ++----+----------+ +| 2 | bobby | +| 5 | bobby | +| 3 | devdojo | +| 6 | devdojo | +| 4 | tony | +| 7 | tony | ++----+----------+ +``` + +> Note: You can use `ORDER BY` with and without specifying a `WHERE` clause. If you've used a `WHERE` clause, you must put the `ORDER BY` clause after the `WHERE` clause. + +The default sorting is ascending and is specified with the `ASC` keyword, and you don't need to add it explicitly, but if you want to sort by descending order, you need to use the `DESC` keyword. + +If we use the query above and add `DESC` at the end as follows: + + +```sql +SELECT id, username FROM users ORDER BY username DESC; +``` + +We will see the following output: + +``` ++----+----------+ +| id | username | ++----+----------+ +| 4 | tony | +| 7 | tony | +| 3 | devdojo | +| 6 | devdojo | +| 2 | bobby | +| 5 | bobby | ++----+----------+ +``` + +As you can see, we've got the same list of users sorted alphabetically but in reverse order. + +## GROUP BY + +The `GROUP BY` statement allows you to use a function like `COUNT`, `MIN`, `MAX` etc., with multiple columns. + +For example, let's say that we wanted to get all user counts grouped by username. + +In our case, we have two users with the username `bobby`, two users with the username `tony`, and two users with the username `devdojo`. This represented in an SQL statement would look like this: + +```sql +SELECT COUNT(username), username FROM users GROUP BY username; +``` + +The output, in this case, would be: + +``` ++-----------------+----------+ +| COUNT(username) | username | ++-----------------+----------+ +| 2 | bobby | +| 2 | devdojo | +| 2 | tony | ++-----------------+----------+ +``` + +The `GROUP BY` statement grouped the identical usernames. Then it ran a `COUNT` on each of `bobby`, `tony` and `devdojo`. + +The main thing to remember here is that the `GROUP BY` should be added after the `FROM` clause and after the `WHERE` clause. + +## HAVING Clause + +The `HAVING` clause allows you to filter out the results on the groups formed by the `GROUP BY` clause. + +For example, let's say that we wanted to get all usernames that are duplicates, i.e., all the usernames present in more than one table record. + +In our case, we have two users with the username `bobby`, two users with the username `tony`, and two users with username `devdojo`. This represented in an SQL statement would look like this: + +```sql +SELECT COUNT(username), username +FROM users +GROUP BY username +HAVING COUNT(username) > 1; +``` + +The output, in this case, would be: + +``` ++-----------------+----------+ +| COUNT(username) | username | ++-----------------+----------+ +| 2 | bobby | +| 2 | devdojo | +| 2 | tony | ++-----------------+----------+ +``` + +The `GROUP BY` clause grouped the identical usernames, calculated their counts and filtered out the groups using the `HAVING` clause. + +> **NOTE**:- _The WHERE clause places conditions on the selected columns, whereas the HAVING clause places conditions on groups created by the GROUP BY clause._ + diff --git a/docs/docs/Introduction-To-Databases/008-insert.md b/docs/docs/Introduction-To-Databases/008-insert.md new file mode 100644 index 0000000..d9b13f2 --- /dev/null +++ b/docs/docs/Introduction-To-Databases/008-insert.md @@ -0,0 +1,86 @@ +# INSERT + +To add data to your database, you would use the `INSERT` statement. You can insert data into one table at a time only. + +The syntax is the following: + +```sql +INSERT INTO table_name + (column_name_1,column_name_2,column_name_n) +VALUES + ('value_1', 'value_2', 'value_3'); +``` + +You would start with the `INSERT INTO` statement, followed by the table that you want to insert the data into. Then you would specify the list of the columns that you want to insert the data into. Finally, with the `VALUES` statement, you specify the data that you want to insert. + +> The important part is that you need to keep the order of the values based on the order of the columns that you've specified. + +In the above example the `value_1` would go into `column_name_1`, the `value_2` would go into `column_name_2` and the `value_3` would go into `column_name_x`. + +Let's use the table that we created in the last chapter and insert 1 user into our `users` table: + +```sql +INSERT INTO users + (username, email, active) +VALUES + ('greisi', 'g@devdojo.com', true); +``` + +Rundown of the insert statement: + +* `INSERT INTO users`: First, we specify the `INSERT INTO` keywords which tells MySQL that we want to insert data into the `users` table. +* `users (username, email, active)`: Then, we specify the table name `users` and the columns that we want to insert data into. +* `VALUES`: Then, we specify the values that we want to insert in. + +## Inserting multiple records + +We've briefly covered this in one of the previous chapters, but in some cases, you might want to add multiple records in a specific table. + +Let's say that we wanted to create 5 new users, rather than running 5 different queries like this: + +```sql +INSERT INTO users (username, email, active) VALUES ('user1', 'user1@devdojo.com', true); +INSERT INTO users (username, email, active) VALUES ('user1', 'user2@devdojo.com', true); +INSERT INTO users (username, email, active) VALUES ('user1', 'user3@devdojo.com', true); +INSERT INTO users (username, email, active) VALUES ('user1', 'user4@devdojo.com', true); +INSERT INTO users (username, email, active) VALUES ('user1', 'user5@devdojo.com', true); +``` + +What you could do is to combine this into one `INSERT` statement by providing a list of the values that you want to insert as follows: + +```sql +INSERT INTO users + (username, email, active) +VALUES + ('user1', 'user1@devdojo.com', true), + ('user2', 'user2@devdojo.com', true), + ('user3', 'user3@devdojo.com', true), + ('user4', 'user4@devdojo.com', true), + ('user5', 'user5@devdojo.com', true); +``` + +That way, you will add 5 new entries in your `users` table with a single `INSERT` statement. This is going to be much more efficient. + +## Inserting multiple records using another table + +In the previous section, we have discussed how we can insert multiple records using a single INSERT query. +But sometimes there are cases where we need to insert multiple records which are residing in some other table. + +In this section, we are going to learn how we can insert multiple records at once using a single INSERT query. + +Consider a table, say `prospect_users`, which stores the information of the people who want to become the users of our service, but they are not yet actual users. + +In order to add them to our user database, we have to insert there entries into our `users` table. +We can achieve the same by writing an `INSERT` query with multiple `VALUES` listed in them (as discussed in previous section). + +But there is an easier way where we achieve the same by querying the `prospect_users` table. + + +```sql +INSERT INTO users (username, email, active) +SELECT username, email, active +FROM prospect_users +WHERE active=true; +``` + +Using the above statement, an entry for each active prospect users will be made in our `users` table. \ No newline at end of file diff --git a/docs/docs/Introduction-To-Databases/009-update.md b/docs/docs/Introduction-To-Databases/009-update.md new file mode 100644 index 0000000..e53f20a --- /dev/null +++ b/docs/docs/Introduction-To-Databases/009-update.md @@ -0,0 +1,106 @@ +# UPDATE + +As the name suggests, whenever you have to update some data in your database, you would use the `UPDATE` statement. + +You can use the `UPDATE` statement to update multiple columns in a single table. + +The syntax would look like this: + +```sql +UPDATE users SET username='bobbyiliev' WHERE id=1; +``` + +Rundown of the statement: + +* `UPDATE users`: First, we specify the `UPDATE` keyword followed by the table that we want to update. +* `username='bobbyiliev'`: Then we specify the columns that we want to update and the new value that we want to set. +* `WHERE id=1`: Finally, by using the `WHERE` clause, we specify which user should be updated. In our case, it is the user with ID 1. + +The most important thing that you need to keep in mind is that if you don't specify a `WHERE` clause, all of the entries inside the `users` table would be updated, and all users would have the `username` set to `bobbyiliev`. + +> Important: You need to be careful when you use the `UPDATE` statement without a `WHERE` clause as every single row will be updated. + +If you have been following along all of the user entries in our `users` table, it currently have no data in the `about` column: + +``` ++----+----------+-------+ +| id | username | about | ++----+----------+-------+ +| 2 | bobby | NULL | +| 3 | devdojo | NULL | +| 4 | tony | NULL | +| 5 | bobby | NULL | +| 6 | devdojo | NULL | +| 7 | tony | NULL | ++----+----------+-------+ +``` + +Let's go ahead and update this for all users and set the column value to `404 bio not found`, For example: + +```sql +UPDATE users SET about='404 bio not found'; +``` + +The output would let you know how many rows have been affected by the query: + +``` +Query OK, 6 rows affected (0.02 sec) +Rows matched: 6 Changed: 6 Warnings: 0 +``` + +Now, if you were to run a select for all `users`, you would get the following result: + +``` ++----+----------+-------------------+ +| id | username | about | ++----+----------+-------------------+ +| 2 | bobby | 404 bio not found | +| 3 | devdojo | 404 bio not found | +| 4 | tony | 404 bio not found | +| 5 | bobby | 404 bio not found | +| 6 | devdojo | 404 bio not found | +| 7 | tony | 404 bio not found | ++----+----------+-------------------+ +``` + +Let's now say that we wanted to update the `about` column for the user with an id of 2. In this case, we need to specify a `WHERE` clause followed by the ID of the user that we want to update as follows: + +```sql +UPDATE users SET about='Hello World :)' WHERE id=2; +``` + +The output here should indicate that only 1 row was updated: + +``` +Query OK, 1 row affected (0.01 sec) +Rows matched: 1 Changed: 1 Warnings: 0 +``` + +Now, if you again run the `SELECT id, username, about FROM users` query, you would see that the user with `id` of 2 now has an updated `about` column data: + +``` ++----+----------+-------------------+ +| id | username | about | ++----+----------+-------------------+ +| 2 | bobby | Hello World :) | +| 3 | devdojo | 404 bio not found | +| 4 | tony | 404 bio not found | +| 5 | bobby | 404 bio not found | +| 6 | devdojo | 404 bio not found | +| 7 | tony | 404 bio not found | ++----+----------+-------------------+ +``` + +## Updating records using another table + +As we've seen in the previous section, you can insert multiple rows in your table using another table. You can use the same principle for the update command. + +To do that you simply have to list all needed table in the `update` section, then you have to explain which action you want to perform on the table, and then you need to link the table together. + +For example, if you want to update the `about` field in the `users` table using the content of the `about` field in the `prospect_users` table, you would do something like this: + +```sql +update users, prospect_users +set users.about = prospect_users.about +where prospect_users.username = users.username; +``` \ No newline at end of file diff --git a/docs/docs/Introduction-To-Databases/010-delete.md b/docs/docs/Introduction-To-Databases/010-delete.md new file mode 100644 index 0000000..92f30ab --- /dev/null +++ b/docs/docs/Introduction-To-Databases/010-delete.md @@ -0,0 +1,41 @@ +# DELETE + +As the name suggests, the `DELETE` statement would remove data from your database. + +The syntax is as follows: + +```sql +DELETE FROM users WHERE id=5; +``` + +The output should indicate that 1 row was affected: + +``` +Query OK, 1 row affected (0.01 sec) +``` + +> Important: Just like the `UPDATE` statement, if you don't specify a `WHERE` clause, all of the entries from the table will be affected, meaning that all of your users will be deleted. So, it is critical to always add a `WHERE` clause when executing a `DELETE` statement. + +```sql +DELETE FROM users; +``` + +The output should indicate (where x is the number of tuples in the table): +``` +Query OK, x row(s) affected (0.047 sec) +``` + +Similar to the Linux `rm` command, when you use the `DELETE` statement, the data would be gone permanently, and the only way to recover your data would be by restoring a backup. + +## Delete from another table + +As we saw in the two precedents sections you can `INSERT` or `UPDPATE` tables rows based on other table data. You can do the same for the `DELETE`. + +For example, if you want to delete the records from the `users` table if the corresponding prospect has been disabled, you could do it this way: + +```sql +delete users +from users, prospect_users +where users.username = prospect_users.username +and NOT prospect_users.active +``` diff --git a/docs/docs/Introduction-To-Databases/011-join.md b/docs/docs/Introduction-To-Databases/011-join.md new file mode 100644 index 0000000..1eb3d06 --- /dev/null +++ b/docs/docs/Introduction-To-Databases/011-join.md @@ -0,0 +1,370 @@ +# JOIN + +The `JOIN` clause allows you to combine the data from 2 or more tables into one result set. + +As we will be selecting from multiple columns, we need to include the list of the columns we want to choose data from after the `FROM` clause is separated by a comma. + +In this chapter, we will go over the following `JOIN` types: + +* `CROSS` Join +* `INNER` Join +* `LEFT` Join +* `RIGHT` Join + +Before we get started, let's create a new database and two tables that we are going to work with: + +* We are going to call the database `demo_joins`: + +```sql +CREATE DATABASE demo_joins; +``` + +* Then, switch to the new database: + +```sql +USE demo_joins; +``` + +* Then, the first table will be called `users`, and it will only have two columns: `id` and `username`: + +```sql +CREATE TABLE users +( + id INT PRIMARY KEY AUTO_INCREMENT, + username VARCHAR(255) NOT NULL +); +``` + +* Then, let's create a second table called `posts`, and to keep things simple, we will have three two columns: `id`, `user_id` and `title`: + +```sql +CREATE TABLE posts +( + id INT PRIMARY KEY AUTO_INCREMENT, + user_id INT, + title VARCHAR(255) NOT NULL +); +``` + +> The `user_id` column would be used to reference the user's ID that the post belongs to. It is going to be a one to many relations, e.g. one user could have many posts: + +![One to many relation](https://imgur.com/ipIjCaL.png) + +* Now, let's add some data into the two tables first by creating a few users: + +```sql +INSERT INTO users + ( username ) +VALUES + ('bobby'), + ('devdojo'), + ('tony'), + ('greisi'); +``` + +* And finally add some posts: + +```sql +INSERT INTO posts + ( user_id, title ) +VALUES + ('1', 'Hello World!'), + ('2', 'Getting started with SQL'), + ('3', 'SQL is awesome'), + ('2', 'MySQL is up!'), + ('1', 'SQL - structured query language'); +``` + +Now that we've got our tables and demo data ready, let's go ahead and learn how to use joins. + +## CROSS JOIN + +The `CROSS` join allows you to put the result of two tables next to each other without specifying any `WHERE` conditions. This makes the `CROSS` join the simplest one, but it is also not of much use in a real-life scenario. + +So if we were to select all of the users and all of the posts side by side, we would use the following query: + +```sql +SELECT * FROM users CROSS JOIN posts; +``` + +The output will be all of your users and all of the posts side by side: + +``` ++----+----------+----+--------+-----------------+ +| id | username | id |user_id | title | ++----+----------+----+--------+-----------------+ +| 4 | greisi | 1 | 1 | Hello World! | +| 3 | tony | 1 | 1 | Hello World! | +| 2 | devdojo | 1 | 1 | Hello World! | +| 1 | bobby | 1 | 1 | Hello World! | +| 4 | greisi | 2 | 2 | Getting started | +| 3 | tony | 2 | 2 | Getting started | +| 2 | devdojo | 2 | 2 | Getting started | +| 1 | bobby | 2 | 2 | Getting started | +| 4 | greisi | 3 | 3 | SQL is awesome | +| 3 | tony | 3 | 3 | SQL is awesome | +| 2 | devdojo | 3 | 3 | SQL is awesome | +| 1 | bobby | 3 | 3 | SQL is awesome | +| 4 | greisi | 4 | 2 | MySQL is up! | +| 3 | tony | 4 | 2 | MySQL is up! | +| 2 | devdojo | 4 | 2 | MySQL is up! | +| 1 | bobby | 4 | 2 | MySQL is up! | +| 4 | greisi | 5 | 1 | SQL | +| 3 | tony | 5 | 1 | SQL | +| 2 | devdojo | 5 | 1 | SQL | +| 1 | bobby | 5 | 1 | SQL | ++----+----------+----+--------+-----------------+ +``` + +As mentioned above, you will highly unlikely run a `CROSS` join for two whole tables in a real-life scenario. If the tables have tens of thousands of rows, an unqualified CROSS JOIN can take minutes to complete. + +You would most likely use one of the following with a specific condition. + +In MySQL, CROSS JOIN and INNER JOIN are equivalent to JOIN. + +## INNER JOIN + +The `INNER` join is used to join two tables. However, unlike the `CROSS` join, by convention, it is based on a condition. By using an `INNER` join, you can match the first table to the second one. + +As we have a one-to-many relationship, a best practice would be to use a primary key for the posts `id` column and a foreign key for the `user_id`; that way, we can 'link' or relate the users table to the posts table. However, this is beyond the scope of this SQL basics eBook, though I might extend it in the future and add more chapters. + +As an example and to make things a bit clearer, let's say that you wanted to get all of your users and the posts associated with each user. The query that we would use will look like this: + +```sql +SELECT * +FROM users +INNER JOIN posts +ON users.id = posts.user_id; +``` + +Rundown of the query: + +* `SELECT * FROM users`: This is a standard select we've covered many times in the previous chapters. +* `INNER JOIN posts`: Then, we specify the second table and which table we want to join the result set. +* `ON users.id = posts.user_id`: Finally, we specify how we want the data in these two tables to be merged. The `user.id` is the `id` column of the `user` table, which is also the primary ID, and `posts.user_id` is the foreign key in the email address table referring to the ID column in the users table. + +The output will be the following, associating each user with their post based on the `user_id` column: + +``` ++----+----------+----+---------+-----------------+ +| id | username | id | user_id | title | ++----+----------+----+---------+-----------------+ +| 1 | bobby | 1 | 1 | Hello World! | +| 2 | devdojo | 2 | 2 | Getting started | +| 3 | tony | 3 | 3 | SQL is awesome | +| 2 | devdojo | 4 | 2 | MySQL is up! | +| 1 | bobby | 5 | 1 | SQL | ++----+----------+----+---------+-----------------+ +``` +Note that the INNER JOIN could (in MySQL) equivalently be written merely as JOIN, but that can vary for other SQL dialects: + +```sql +SELECT * +FROM users +JOIN posts +ON users.id = posts.user_id; +``` + +The main things that you need to keep in mind here are the `INNER JOIN` and `ON` clauses. + +With the inner join, the `NULL` values are discarded. For example, if you have a user who does not have a post associated with it, the user with NULL posts will not be displayed when running the above `INNER` join query. + +To get the null values as well, you would need to use an outer join. + +### Types of INNER JOIN + +1. **Theta Join ( θ )** :- Theta join combines rows from different tables provided they satisfy the theta condition. + The join condition is denoted by the symbol `θ`. \ + Here the comparison operators `(≤, ≥, ˂, ˃, =, ̚ )` come into picture. \ + **Notation** :- R1θ R2. \ + \ + For example, suppose we want to buy a mobile and a laptop, based on our budget we have thought of buying both such that mobile price should be less than that of laptop. \ + \ + `SELECT mobile.model, laptop.model + FROM mobile, laptop + WHERE mobile.price < laptop.price;` + +2. **Equijoin** :- When Theta join uses only equality (=) comparison operator, it is said to be equijoin. \ + For example, suppose we want to buy a mobile and a laptop, based on our budget we have thought of buying both of the same prices. \ + \ + `SELECT mobile.model, laptop.model + FROM mobile, laptop + WHERE mobile.price = laptop.price;` + +3. **Natural Join ( ⋈ )** :- Natural join does not use any comparison operator. It does not concatenate the way a Cartesian product does. \ + We can perform a Natural Join only if at least one standard column exists between two tables. In addition, the column must have the same name and domain. \ + \ + `SELECT * FROM mobile NATURAL JOIN laptop;` + + +## LEFT JOIN + +Using the `LEFT OUTER` join, you would get all rows from the first table that you've specified, and if there are no associated records within the second table, you will get a `NULL` value. + +In our case, we have a user called `graisi`, which is not associated with a specific post. As you can see from the output from the previous query, the `graisi` user was not present there. To show that user, even though it does not have an associated post with it, you could use a `LEFT OUTER` join: + +```sql +SELECT * +FROM users +LEFT JOIN posts +ON users.id = posts.user_id; +``` + +The output will look like this: + +``` ++----+----------+------+---------+-----------------+ +| id | username | id | user_id | title | ++----+----------+------+---------+-----------------+ +| 1 | bobby | 1 | 1 | Hello World! | +| 2 | devdojo | 2 | 2 | Getting started | +| 3 | tony | 3 | 3 | SQL is awesome | +| 2 | devdojo | 4 | 2 | MySQL is up! | +| 1 | bobby | 5 | 1 | SQL | +| 4 | greisi | NULL | NULL | NULL | ++----+----------+------+---------+-----------------+ +``` + +## RIGHT JOIN + +The `RIGHT OUTER` join is the exact opposite of the `LEFT OUTER` join. It will display all of the rows from the second table and give you a `NULL` value in case that it does not match with an entry from the first table. + +Let's create a post that does not have a matching user id: + +```sql +INSERT INTO posts + ( user_id, title ) +VALUES + ('123', 'No user post!'); +``` + +We specify `123` as the user ID, but we don't have such a user in our `users` table. + +Now, if you were to run the `LEFT` outer join, you would not see the post as it has a null value for the corresponding `users` table. + +But if you were to run a `RIGHT` outer join, you would see the post but not the `greisi` user as it does not have any posts: + +```sql +SELECT * +FROM users +RIGHT JOIN posts +ON users.id = posts.user_id; +``` + +Output: + +``` ++------+----------+----+---------+-----------------+ +| id | username | id | user_id | title | ++------+----------+----+---------+-----------------+ +| 1 | bobby | 1 | 1 | Hello World! | +| 2 | devdojo | 2 | 2 | Getting started | +| 3 | tony | 3 | 3 | SQL is awesome | +| 2 | devdojo | 4 | 2 | MySQL is up! | +| 1 | bobby | 5 | 1 | SQL | +| NULL | NULL | 6 | 123 | No user post! | ++------+----------+----+---------+-----------------+ +``` + +Joins can also be limited with WHERE conditions. For instance, in the preceding example, if we wanted to join the tables and then restrict to only username `bobby`. + + +```sql +SELECT * +FROM users +RIGHT JOIN posts +ON users.id = posts.user_id +WHERE username = 'bobby'; +``` + +Output: + +``` ++------+----------+----+---------+-----------------+ +| id | username | id | user_id | title | ++------+----------+----+---------+-----------------+ +| 1 | bobby | 1 | 1 | Hello World! | +| 1 | bobby | 5 | 1 | SQL | ++------+----------+----+---------+-----------------+ +``` + +## The Impact of Conditions in JOIN vs. WHERE Clauses + +The placement of conditions within a SQL query, specifically in the `JOIN` vs. the `WHERE` clause, can yield different results. + +Take a look at the following example, which retrieves `POSTS` containing the word "SQL" along with their associated user data: + +```sql +SELECT users.*, posts.* +FROM users +LEFT JOIN posts +ON posts.user_id = users.id +WHERE posts.title LIKE '%SQL%'; +``` + +Output: + +```sql ++--+--------+--+-------+-------------------------------+ +|id|username|id|user_id|title | ++--+--------+--+-------+-------------------------------+ +|2 |devdojo |2 |2 |Getting started with SQL | +|3 |tony |3 |3 |SQL is awesome | +|2 |devdojo |4 |2 |MySQL is up! | +|1 |bobby |5 |1 |SQL - structured query language| ++--+--------+--+-------+-------------------------------+ +``` + +However, by shifting the condition to the `JOIN` clause, all users are displayed, but only posts with titles containing "SQL" are included: + +```sql +SELECT users.*, posts.* +FROM users +LEFT JOIN posts +ON posts.user_id = users.id + AND posts.title LIKE '%SQL%'; +``` + +Output: + +```sql ++--+--------+----+-------+-------------------------------+ +|id|username|id |user_id|title | ++--+--------+----+-------+-------------------------------+ +|1 |bobby |5 |1 |SQL - structured query language| +|2 |devdojo |4 |2 |MySQL is up! | +|2 |devdojo |2 |2 |Getting started with SQL | +|3 |tony |3 |3 |SQL is awesome | +|4 |greisi |null|null |null | ++--+--------+----+-------+-------------------------------+ +``` + +## Equivalence of RIGHT and LEFT JOINs + +The `RIGHT JOIN` and `LEFT JOIN` operations in SQL are fundamentally equivalent. They can be interchanged by simply swapping the tables involved. Here's an illustration: + +The following `LEFT JOIN`: + +```sql +SELECT users.*, posts.* +FROM posts +LEFT JOIN users +ON posts.user_id = users.id; +``` + +Can be equivalently written using `RIGHT JOIN` as: + +```sql +SELECT users.*, posts.* +FROM users +RIGHT JOIN posts +ON posts.user_id = users.id; +``` + +## Conclusion + +Joins are fundamental to using SQL with data. The whole concept of joins might be very confusing initially but would make a lot of sense once you get used to it. + +The best way to wrap your head around it is to write some queries, play around with each type of `JOIN`, and see how the result set changes. + +For more information, you could take a look at the official documentation [here](https://dev.mysql.com/doc/refman/8.0/en/join.html). diff --git a/docs/docs/Introduction-To-Databases/012-sql-commnad-categories.md b/docs/docs/Introduction-To-Databases/012-sql-commnad-categories.md new file mode 100644 index 0000000..51c9134 --- /dev/null +++ b/docs/docs/Introduction-To-Databases/012-sql-commnad-categories.md @@ -0,0 +1,121 @@ +# SQL | DDL, DQL, DML, DCL and TCL Commands +Structured Query Language(SQL), as we all know, is the database language by which we can perform certain operations on the existing database. Also, we can use this language to create a database. SQL uses specific commands like Create, Drop, Insert, etc., to carry out the required tasks. +1. **DDL** – Data Definition Language +2. **DQL** – Data Query Language +3. **DML** – Data Manipulation Language +4. **DCL** – Data Control Language + +#### Though many resources claim there to be another category of SQL clauses TCL – Transaction Control Language, so we will see in detail about TCL as well. +![img.png](../assets/sql-commnad.png) + +### DDL (Data Definition Language): +DDL or Data Definition Language consists of the SQL commands used to define the database schema. It simply deals with descriptions of the database schema and is used to create and modify the structure of database objects in the database. These commands usually are not used by a general user, who should be accessing the database via an application. + +#### List of DDL commands: +- `CREATE`: This command is used to create the database or its objects (like table, index, function, views, store procedure, and triggers). +```sql +CREATE TABLE Persons ( + PersonID int, + LastName varchar(255), + FirstName varchar(255), + Address varchar(255), + City varchar(255) +); +``` +- `DROP`: This command is used to delete objects from the database. + +```sql +DROP TABLE table_name; +``` +- `ALTER`: This is used to alter the structure of the database. +```sql +ALTER TABLE Persons +ADD Age int; +``` +- `TRUNCATE`: This is used to remove all records from a table, including all spaces allocated for the records. +```sql +TRUNCATE TABLE Persons; +``` +- `COMMENT`: This is used to add comments to the data dictionary. +```sql +--SELECT * FROM Customers; +SELECT * FROM Persons; +``` +-` RENAME`: This is used to rename an object existing in the database. +```sql +ALTER TABLE Persons +RENAME COLUMN Age TO Year; +``` + +#### DQL (Data Query Language): +**DQL** statements are used for performing queries on the data within schema objects. The purpose of the DQL Command is to get some schema relation based on the query passed to it. We can define DQL as follows. It is a component of the SQL statement that allows getting data from the database and imposing order upon it. It includes the SELECT statement. This command allows getting the data out of the database to perform operations with it. When a SELECT is fired against a table(s), the result is compiled into a different temporary table, which is displayed or perhaps received by the program, i.e. a front-end. + +#### List of DQL: +`SELECT`: It is used to retrieve data from the database. +```sql +SELECT * FROM table_name; +``` +``` ++--------+--------------+------------+--------+---------+ +| emp_id | emp_name | hire_date | salary | dept_id | ++--------+--------------+------------+--------+---------+ +| 1 | Ethan Hunt | 2001-05-01 | 5000 | 4 | +| 2 | Tony Montana | 2002-07-15 | 6500 | 1 | +| 3 | Sarah Connor | 2005-10-18 | 8000 | 5 | +| 4 | Rick Deckard | 2007-01-03 | 7200 | 3 | +| 5 | Martin Blank | 2008-06-24 | 5600 | NULL | ++--------+--------------+------------+--------+---------+ +``` +The SQL commands that deal with the manipulation of data present in the database belong to DML or Data Manipulation Language, including most of the SQL statements. It is the component of the SQL statement that controls access to data and the database. DCL statements are grouped with DML statements. + +#### List of DML commands: +- `INSERT `: It is used to insert data into a table. +```sql +INSERT INTO Customers + (CustomerName, ContactName, Address, City, PostalCode, Country) +VALUES + ('Cardinal', 'Tom B. Erichsen', 'Skagen 21', 'Stavanger', '4006', 'Norway'); +``` +- `UPDATE`: It is used to update existing data within a table. + +```sql +UPDATE Customers +SET ContactName='Alfred Schmidt', City='Frankfurt' +WHERE CustomerID = 1; +``` +- `DELETE `: It is used to delete records from a database table. +```sql + DELETE FROM Customers WHERE CustomerName='Alfreds Futterkiste'; +``` +- `LOCK`: Table control concurrency. +```sql +LOCK TABLES table_name [READ | WRITE] +-------------------------------------- +UNLOCK TABLES; +``` +- `CALL`: Call a PL/SQL or JAVA subprogram. +```sql +CREATE PROCEDURE procedure_name +AS sql_statement +GO; +``` +#### Execute a Stored Procedure +```sql +EXEC procedure_name; +``` +- `EXPLAIN PLAN`: It describes the access path to data. + +#### DCL (Data Control Language): +DCL includes commands such as GRANT and REVOKE, which mainly deal with the database system's rights, permissions, and other controls. + +##### List of DCL commands: +- `GRANT`: This command gives users access privileges to the database. +- `REVOKE`: This command withdraws the user’s access privileges given by using the GRANT command. + +Though many resources claim there to be another category of SQL clauses TCL – Transaction Control Language, we will see in detail about TCL. TCL commands deal with the transaction within the database. + +##### List of TCL commands: +- `COMMIT`: Commits a Transaction. +- `ROLLBACK`: Rollbacks a transaction in case of any error occurs. +- `SAVEPOINT`:Sets a savepoint within a transaction. +- `SET TRANSACTION`: Specify characteristics for the transaction. diff --git a/docs/docs/Introduction-To-Databases/013-sub-queries.md b/docs/docs/Introduction-To-Databases/013-sub-queries.md new file mode 100644 index 0000000..26e13fe --- /dev/null +++ b/docs/docs/Introduction-To-Databases/013-sub-queries.md @@ -0,0 +1,112 @@ +# SQL Sub Queries + +### A subquery is a SQL query nested inside a larger query. + +- A subquery may occur in + - A SELECT clause + - A FROM clause + - A WHERE clause + +- The subquery can be nested inside a SELECT, INSERT, UPDATE, or DELETE statement or inside another subquery. +- A subquery is usually added within the WHERE Clause of another SQL SELECT statement. +- The inner query executes first before its parent query so that the results of an inner query can be passed to the outer query. + +#### You can use a subquery in a SELECT, INSERT, DELETE, or UPDATE statement to perform the following tasks: +- Compare an expression to the result of the query. +- Determine if an expression is included in the results of the query. +- Check whether the query selects any rows. + +**_Subqueries with the `SELECT` Statement_**: + +Consider the CUSTOMERS table having the following records + + +----+----------+-----+-----------+----------+ + | ID | NAME | AGE | ADDRESS | SALARY | + +----+----------+-----+-----------+----------+ + | 1 | Ramesh | 35 | Ahmedabad | 2000.00 | + | 2 | Khilan | 25 | Delhi | 1500.00 | + | 3 | Kaushik | 23 | Kota | 2000.00 | + | 4 | Chaitali | 25 | Mumbai | 6500.00 | + | 5 | Hardik | 27 | Bhopal | 8500.00 | + | 6 | Komal | 22 | MP | 4500.00 | + | 7 | Muffy | 24 | Indore | 10000.00 | + +----+----------+-----+-----------+----------+ +Now, let us check the following subquery with a SELECT statement. + +_**Example**_: +```sql +SELECT * +FROM CUSTOMERS +WHERE ID IN ( + SELECT ID + FROM CUSTOMERS + WHERE SALARY > 4500 +); +``` +This would produce the following result. + + +----+----------+-----+---------+----------+ + | ID | NAME | AGE | ADDRESS | SALARY | + +----+----------+-----+---------+----------+ + | 4 | Chaitali | 25 | Mumbai | 6500.00 | + | 5 | Hardik | 27 | Bhopal | 8500.00 | + | 7 | Muffy | 24 | Indore | 10000.00 | + +----+----------+-----+---------+----------+ + + +**_Subqueries with the `UPDATE` Statement_**: + +The subquery can be used in conjunction with the UPDATE statement. Either single or multiple columns in a table can be updated when using a subquery with the UPDATE statement. + +**_Example_**: + +Assuming, we have CUSTOMERS_BKP table available which is backup of CUSTOMERS table. The following example updates SALARY by 0.25 times in the CUSTOMERS table for all the customers whose AGE is greater than or equal to 27. +```sql +UPDATE CUSTOMERS +SET SALARY = SALARY * 0.25 +WHERE AGE IN ( + SELECT AGE + FROM CUSTOMERS_BKP + WHERE AGE >= 27 +); +``` +This would impact two rows and finally CUSTOMERS table would have the following records. + + +----+----------+-----+-----------+----------+ + | ID | NAME | AGE | ADDRESS | SALARY | + +----+----------+-----+-----------+----------+ + | 1 | Ramesh | 35 | Ahmedabad | 125.00 | + | 2 | Khilan | 25 | Delhi | 1500.00 | + | 3 | Kaushik | 23 | Kota | 2000.00 | + | 4 | Chaitali | 25 | Mumbai | 6500.00 | + | 5 | Hardik | 27 | Bhopal | 2125.00 | + | 6 | Komal | 22 | MP | 4500.00 | + | 7 | Muffy | 24 | Indore | 10000.00 | + +----+----------+-----+-----------+----------+ + +**_Subqueries with the `DELETE` Statement_**: + +The subquery can be used in conjunction with the DELETE statement like with any other statements mentioned above. + +**_Example_**: + +Assuming, we have a CUSTOMERS_BKP table available which is a backup of the CUSTOMERS table. The following example deletes the records from the CUSTOMERS table for all the customers whose AGE is greater than or equal to 27. +```sql +DELETE FROM CUSTOMERS +WHERE AGE IN ( + SELECT AGE + FROM CUSTOMERS_BKP + WHERE AGE >= 27 +); +``` +This would impact two rows and finally the CUSTOMERS table would have the following records. + + +----+----------+-----+---------+----------+ + | ID | NAME | AGE | ADDRESS | SALARY | + +----+----------+-----+---------+----------+ + | 2 | Khilan | 25 | Delhi | 1500.00 | + | 3 | Kaushik | 23 | Kota | 2000.00 | + | 4 | Chaitali | 25 | Mumbai | 6500.00 | + | 6 | Komal | 22 | MP | 4500.00 | + | 7 | Muffy | 24 | Indore | 10000.00 | + +----+----------+-----+---------+----------+ \ No newline at end of file diff --git a/docs/docs/Introduction-To-Databases/014-unions.md b/docs/docs/Introduction-To-Databases/014-unions.md new file mode 100644 index 0000000..68af093 --- /dev/null +++ b/docs/docs/Introduction-To-Databases/014-unions.md @@ -0,0 +1,124 @@ +# SQL - UNIONS CLAUSE + +The SQL UNION clause/operator is used to combine the results of two or more SELECT statements without returning any duplicate rows. + +- While using this UNION clause, each SELECT statement must have: + + - The same number of columns selected + - The same number of column expressions + - The same data type and + - Have them in the same order + +But they need not have to be in the same length. + +_Example_ + +Consider the following two tables. + +Table 1 − customers table is as follows: + + +----+----------+-----+-----------+----------+ + | id | name | age | address | salary | + +----+----------+-----+-----------+----------+ + | 1 | Ramesh | 32 | Ahmedabad | 2000.00 | + | 2 | Khilan | 25 | Delhi | 1500.00 | + | 3 | kaushik | 23 | Kota | 2000.00 | + | 4 | Chaitali | 25 | Mumbai | 6500.00 | + | 5 | Hardik | 27 | Bhopal | 8500.00 | + | 6 | Komal | 22 | MP | 4500.00 | + | 7 | Muffy | 24 | Indore | 10000.00 | + +----+----------+-----+-----------+----------+ + +Table 2 − orders table is as follows: + + +-----+---------------------+-------------+--------+ + | oid | date | customer_id | amount | + +-----+---------------------+-------------+--------+ + | 102 | 2009-10-08 00:00:00 | 3 | 3000 | + | 100 | 2009-10-08 00:00:00 | 3 | 1500 | + | 101 | 2009-11-20 00:00:00 | 2 | 1560 | + | 103 | 2008-05-20 00:00:00 | 4 | 2060 | + +-----+---------------------+-------------+--------+ + +Now, let us join these two tables in our SELECT statement as follows: + +```sql +SELECT id, name, amount, date + FROM customer + LEFT JOIN orders + ON customers.id = orders.customer_id +UNION + SELECT id, name, amount, date + FROM customer + RIGHT JOIN orders + ON customers.id = orders.customer_id +``` + +This would produce the following result: + +### The UNION ALL Clause +The UNION ALL operator is used to combine the results of two SELECT statements including duplicate rows. + +The same rules that apply to the UNION clause will apply to the UNION ALL operator. + +_Example_ - +Consider the following two tables: + +* Table 1 − customers table is as follows: + + +----+----------+-----+-----------+----------+ + | id | name | age | address | salary | + +----+----------+-----+-----------+----------+ + | 1 | Ramesh | 32 | Ahmedabad | 2000.00 | + | 2 | Khilan | 25 | Delhi | 1500.00 | + | 3 | kaushik | 23 | Kota | 2000.00 | + | 4 | Chaitali | 25 | Mumbai | 6500.00 | + | 5 | Hardik | 27 | Bhopal | 8500.00 | + | 6 | Komal | 22 | MP | 4500.00 | + | 7 | Muffy | 24 | Indore | 10000.00 | + +----+----------+-----+-----------+----------+ + +* Table 2 − orders table is as follows: + + +-----+---------------------+-------------+--------+ + | oid | date | customer_id | amount | + +-----+---------------------+-------------+--------+ + | 102 | 2009-10-08 00:00:00 | 3 | 3000 | + | 100 | 2009-10-08 00:00:00 | 3 | 1500 | + | 101 | 2009-11-20 00:00:00 | 2 | 1560 | + | 103 | 2008-05-20 00:00:00 | 4 | 2060 | + +-----+---------------------+-------------+--------+ + +Now, let us join these two tables in our SELECT statement as follows : +```sql +SELECT id, name, amount, date + FROM customers + LEFT JOIN orders + ON customers.id = order.customer_id +UNION ALL + SELECT id, name, amount, date + FROM customers + RIGHT JOIN orders + ON customers.id = orders.customer_id; +``` + +This would produce the following result: + + +------+----------+--------+---------------------+ + | id | name | amount | date | + +------+----------+--------+---------------------+ + | 1 | Ramesh | NULL | NULL | + | 2 | Khilan | 1560 | 2009-11-20 00:00:00 | + | 3 | kaushik | 3000 | 2009-10-08 00:00:00 | + | 3 | kaushik | 1500 | 2009-10-08 00:00:00 | + | 4 | Chaitali | 2060 | 2008-05-20 00:00:00 | + | 5 | Hardik | NULL | NULL | + | 6 | Komal | NULL | NULL | + | 7 | Muffy | NULL | NULL | + | 3 | kaushik | 3000 | 2009-10-08 00:00:00 | + | 3 | kaushik | 1500 | 2009-10-08 00:00:00 | + | 2 | Khilan | 1560 | 2009-11-20 00:00:00 | + | 4 | Chaitali | 2060 | 2008-05-20 00:00:00 | + +------+----------+--------+---------------------+ + +Note : **There are two other clauses (i.e., operators), which are like the UNION clause.** diff --git a/docs/docs/Introduction-To-Databases/015-Keys-in-a-Relational Database.md b/docs/docs/Introduction-To-Databases/015-Keys-in-a-Relational Database.md new file mode 100644 index 0000000..240741e --- /dev/null +++ b/docs/docs/Introduction-To-Databases/015-Keys-in-a-Relational Database.md @@ -0,0 +1,51 @@ +# Relational Keys- Keys in a Relational Database + +A database must be able to inhibit inconsistency occurring due to incorrect data. It must have certain identified attributes in relations to uniquely distinguish the tuples. No two tuples in a relation should have same value for all attributes since it will lead to duplicity of data. duplicity of data leads to inconsistency . Relational database systems have the concept of Relational Keys to distinguish between different records. + +## Types of Relational Keys +### *Super Keys* + +A relation’s tuples can be uniquely identified by various combinations of attributes. Super Keys is defined as a set of one attribute or combinations of two or more attributes that help in distinguishing between tuples in a relation. + +For example, the Customer ID attribute of the relation Customer is unique for all customers. The Customer ID can be used to identify each customer tuple in the relation. Customer ID is a Super Key for relation Customer. + +Customer Name attribute of Customer cannot be considered as Super Key because many customers for the organization can have same name. However when combined with Customer ID it becomes a Super Key {CustomerID, CustomerName}. It means that Super Key can have additional attributes. Consider any key K which is identified as a super key. Any superset of key K is also a super key. For example the possible Super Keys for Customer Relation are + +- [ CustomerID, CustomerName, Customer Address ] +- [ CustomerID, CustomerName, Customer Contact Number ] +- [ CustomerID, Customer Contact Number ] + +### *Candidate Keys* + +If we take a key from the set of super keys for which we don’t have any proper subset defined as a superkey, it is called a candidate key. In other words the minimal attribute super keys are termed as candidate keys. + +If we can identify some distinct sets of attributes which identify the tuples uniquely they fall in the category of candidate keys. For example the possible Candidate Keys for Customer Relation are + +- [ CustomerID ] +- [ CustomerName, Customer Address ] +- [ CustomerName, Customer Contact Number ] +- [ Customer Address, Customer Contact Number ] + +### *Primary Key* + +Out of all possible candidate keys only one is chosen by the database designer as the key to identify the records in a relation in a database. This selected candidate key is called the Primary Key. It is the property of the relation and not of tuples. The primary key attribute(s) does not allow any duplicate values. It also inhibits leaving the primary key attribute without any value (NOT NULL). + +**A relation can have only one primary key.** + +In the Customer Database example {Customer ID} is the attribute taken as the primary key of customer relation. While picking up a candidate key as primary key the designer should ensure that it is an attribute or group of attributes that do not change or may change extremely rarely. + +### *Alternate Keys* + +After selecting one key among candidate keys as primary key, the rest of candidate keys are called the alternate keys. In the customer Database these candidate keys are the alternate keys. + +- [ CustomerName, Customer Address ] +- [ CustomerName, Customer Contact Number ] +- [ Customer Address, Customer Contact Number ] + +### *Foreign Key* + +A foreign key is used to reference values from one relation into another relation. This is possible when the attribute or combination of attributes is primary key in the referenced relation. The relation in which the primary key of a relation is referenced is called the referencing table. The foreign key constraint implements the referential integrity in a database. The referencing relation attribute can have only those values which exist in the primary key attribute(s) of the referenced relation + +**A relation can have multiple foreign key** + +For example in the customer database the orders' relation (referencing relation) has the structure (Order ID, Customer ID, Order Date, Order Status, Total Billing Amount). The attribute Customer ID is the foreign key referencing Customer ID from customer relation (referenced relation). It means that orders can be placed only for the customers whose customer details are already available in the customer relation. \ No newline at end of file diff --git a/docs/docs/Introduction-To-Databases/016-Logical-operator-keywords.md b/docs/docs/Introduction-To-Databases/016-Logical-operator-keywords.md new file mode 100644 index 0000000..e100b34 --- /dev/null +++ b/docs/docs/Introduction-To-Databases/016-Logical-operator-keywords.md @@ -0,0 +1,17 @@ +# Logical Operator Keywords + +Here are the most important Logical Operators summarized in a table. + +Logical Operators can be used for conditions as they show a result in form of a `boolean` (True/False) or Unknown. +So, e.g. if an exact value is `True` for a value, a Logical Operator can proof that it's True. + +| Logical Operator | Explanation | +|------------------|-------------| +| ALL | If all comparisons are True: return True | +| ANY | If any comparison is True: return True | +| AND | If both expressions are True: return True | +| EXISTS | If a subquery contains rows: return True | +| IN | If compared value is equal to at least one value: return True | +| BETWEEN | If there are values in given range: return True | +| NOT | Reverses the value of any boolean | +| OR | If either expression is True: return True | diff --git a/docs/docs/Introduction-To-Databases/017-having-clause_aggregate-functions.md b/docs/docs/Introduction-To-Databases/017-having-clause_aggregate-functions.md new file mode 100644 index 0000000..7c4618e --- /dev/null +++ b/docs/docs/Introduction-To-Databases/017-having-clause_aggregate-functions.md @@ -0,0 +1,186 @@ +# `HAVING` Clause + +Unlike where clause which imposes conditions on columns `Having` clause enables you to specify conditions that filter which group results appear in the results. + +## Syntax + +```sql +SELECT column_name(s) +FROM table_name +WHERE condition +GROUP BY column_name(s) +HAVING condition +ORDER BY column_name(s); +``` + +## Description + +- Used with `aggregate functions` +- Must follow `GROUP BY` clause in the query + +## Aggregate Functions + - SQL aggregation is the task of collecting a set of values to return a single value. + - An aggregate function is a function where the values of multiple rows are grouped together as input on certain criteria to form a single value of more significant meaning. + +## Aggregate Functions Examples + +Suppose this are the table given to us + +|Students | table|| +|--------|-----------|--------| +| rollno | name | class | +| 1 | Sanskriti | TE | +| 1 | Shree | BE | +| 2 | Harry | TE | +| 3 | John | TE | +| 3 | Shivani | TE | + + +|purchase | table|| +|------------|-------|---------------| +| item | price | customer_name | +| Pen | 10 | Sanskriti | +| Bag | 1000 | Sanskriti | +| Vegetables | 500 | Sanskriti | +| Shoes | 5000 | Sanskriti | +| Water Bottle | 800 | XYZ | +| Mouse | 120 | ABC | +| Sun Glasses | 1350 | ABC | + + +### AVG function + + Calculates `average` of the given column of values + +```sql +SELECT AVG(price) AS Avg_Purchase, customer_name +FROM purchase +GROUP BY customer_name; +``` + +| Avg_Purchase | customer_name | +|--------------|---------------| +| 1627.5000 | Sanskriti | + +### SUM function + + Calculates `sum` of values of given column. + +```sql +SELECT SUM(price) AS Total_Bill, customer_name +FROM purchase +GROUP BY customer_name; +``` + +| Total_Bill | customer_name | +|------------|---------------| +| 6510 | Sanskriti | + +### COUNT function + + Gives `count` of entries/ values in given column. + +```sql +SELECT COUNT(item) AS Total_Items, customer_name +FROM purchase +GROUP BY customer_name; +``` + +| Total_Items | customer_name | +|-------------|---------------| +| 4 | Sanskriti | + +### MAX function + + Return `maximum` value from the number of values in the column. + +```sql +SELECT MAX(price) AS Highest_Purchase, customer_name +FROM purchase +GROUP BY customer_name; +``` + +| Highest_Purchase | customer_name | +|-----------------|---------------| +| 5000 | Sanskriti | + +### MIN function + + Return `minimum` value from the number of values in the column. + +```sql +SELECT MIN(price) AS Lowest_Purchase, customer_name +FROM purchase +GROUP BY customer_name; +``` +| Lowest_Purchase | customer_name | +|-----------------|---------------| +| 10 | Sanskriti | + + +## Having clause Examples + +### Example 1 + +```sql +SELECT COUNT(class) AS strength, class +FROM Students +GROUP BY class +HAVING COUNT(class) > 2; +``` + +Above query gives number of students in a class `having` number of students > 2 + +| strength | class | +|----------|-------| +| 4 | TE | + +### Example 2 + +```sql +SELECT customer_name, MIN(price) AS MIN_PURCHASE +FROM purchase +GROUP BY customer_name +HAVING MIN(price) > 10; +``` +Above query finds `minimum` price which is > 10 + +| customer_name | MIN_PURCHASE | +|---------------|------------| +| XYZ | 800 | +| ABC | 120 | + +### Example 3 + +```sql +SELECT customer_name, AVG(price) AS Average_Purchase +FROM purchase +GROUP BY customer_name +HAVING AVG(price) > 550 +ORDER BY customer_name DESC; +``` +Above query calculates `average` of price and prints customer name and average price which is greater than 550 with descending `order` of customer names. + +| customer_name | Average_Purchase | +|---------------|------------------| +| XYZ | 800.0000 | +| Sanskriti | 1627.5000 | +| ABC | 735.0000 | + +### Example 4 + +```sql +SELECT customer_name, SUM(price) AS Total_Purchase +FROM purchase +WHERE customer_name +LIKE "S%" +GROUP BY customer_name +HAVING SUM(price) > 1000; +``` +Calculates `SUM` of price and returns customer name and sum > 1000. + +| customer_name | Total_Purchase | +|---------------|----------------| +| Sanskriti | 6510 | + + diff --git a/docs/docs/Introduction-To-Databases/018-essential-mysql-functions.md b/docs/docs/Introduction-To-Databases/018-essential-mysql-functions.md new file mode 100644 index 0000000..efa833a --- /dev/null +++ b/docs/docs/Introduction-To-Databases/018-essential-mysql-functions.md @@ -0,0 +1,191 @@ +# Essential MySQL Functions + +MySQL has many built-in functions. We will covering some important most used built-in functions; for a complete list refer to the online MySQL Reference Manual (http://dev.mysql.com/doc/). + +> NOTE: As of now we will be going through only function and their output, as they would be self explanatory. + +## Numeric Functions +```sql +SELECT ROUND(5.73) + ``` +6 + +```sql +SELECT ROUND(5.73, 1) + ``` +5.7 + +```sql +SELECT TRUNCATE(5.7582, 2) + ``` +5.75 + +```sql +SELECT CEILING(5.2) + ``` +6 + +```sql +SELECT FLOOR(5.7) + ``` +5 + +```sql +SELECT ABS(-5.2) + ``` +5.2 + +```sql +SELECT RAND() -- Generates a random floating point number b/w 0 & 1 + ``` + +## STRING Functions +```sql +SELECT LENGTH('sky') + ``` +3 + +```sql +SELECT UPPER('sky') + ``` +SKY + +```sql +SELECT LOWER('sky) + ``` +sky + +```sql +SELECT LTRIM(' sky') + ``` +sky + +```sql +SELECT RTRIM('sky ') + ``` +sky + +```sql +SELECT TRIM(' sky ') + ``` +sky + +```sql +SELECT LEFT('Kindergarten', 4) + ``` +Kind + +```sql +SELECT RIGHT('Kindergarten', 6) + ``` +garten + +```sql +SELECT SUBSTRING('Kindergarten', 3, 5) + ``` +nderg + +```sql +SELECT LOCATE('n','Kindergarten') -- LOCATE returns the first occurrence of a character or character string, if found, otherwise it returns 0 + ``` +3 + +```sql +SELECT REPLACE('Kindergarten', 'garten', 'garden') + ``` +Kindergarden + +```sql +SELECT CONCAT('first', 'last') + ``` +firstlast + +## DATE Functions +```sql +SELECT NOW() + ``` +2021-10-21 19:59:47 + +```sql +SELECT CURDATE() + ``` +2021-10-21 + +```sql +SELECT CURTIME() + ``` +20:01:12 + +```sql +SELECT MONTH(NOW()) + ``` +10 + +```sql +SELECT YEAR(NOW()) + ``` +2021 + +```sql +SELECT HOUR(NOW()) + ``` +13 + +```sql +SELECT DAYTIME(NOW()) + ``` +Thursday + +## Formatting Dates and Times + +> In MySQL, the default date format is "YYYY-MM-DD", ex: "2025-05-12", MySQL allows developers to format it the way they want. We will discuss some of them. +```sql +SELECT DATE_FORMAT(NOW(), '%M %D %Y') + ``` +October 22nd 2021 + +```sql +SELECT DATE_FORMAT(NOW(), '%m %d %y') + ``` +10 22 21 + +```sql +SELECT DATE_FORMAT(NOW(), '%m %D %y') + ``` +10 22nd 21 + +```sql +SELECT TIME_FORMAT(NOW(), '%H %i %p') + ``` +14:11 PM + +## Calculating Dates and Times + +```sql +SELECT DATE_ADD(NOW(), INTERVAL 1 DAY) --return tomorrows date and time + ``` + +2021-10-23 14:26:17 + +```sql +SELECT DATE_ADD(NOW(), INTERVAL -1 YEAR) + ``` +or +```sql +SELECT DATE_SUB(NOW(), INTERVAL 1 YEAR) + ``` +> Both the queries will return the same output + +2020-10-22 14:29:47 + +```sql +SELECT DATEDIFF('2021-09-08 09:00', '2021-07-07 17:00') -- It will return the difference in number of days, time won't be considered + ``` + +63 + +```sql +SELECT TIME_TO_SEC('09:00') - TIME_TO_SEC('09:02') + ``` +-120 + diff --git a/docs/docs/Introduction-To-Databases/020-TCL-commands.md b/docs/docs/Introduction-To-Databases/020-TCL-commands.md new file mode 100644 index 0000000..bdbb9e7 --- /dev/null +++ b/docs/docs/Introduction-To-Databases/020-TCL-commands.md @@ -0,0 +1,154 @@ +# `Transaction Control Language` + + - `Transaction Control Language` can be defined as the portion of a database language used for `maintaining consistency` of the database and `managing transactions` in the database. + + - A set of `SQL statements` that are `co-related logically and executed on the data stored in the table` is known as a `transaction`. + +## `TCL` Commands + +- `COMMIT` Command +- `ROLLBACK` Command +- `SAVEPOINT` Command + +## `COMMIT` + +The main use of `COMMIT` command is to `make the transaction permanent`. If there is a need for any transaction to be done in the database that transaction permanent through commit command. + +### Syntax +```sql +COMMIT; +``` + +## `ROLLBACK` + +Using this command, the database can be `restored to the last committed state`. Additionally, it is also used with savepoint command for jumping to a savepoint in a transaction. + +### Syntax +```sql +ROLLBACK TO savepoint-name; +``` + +## `SAVEPOINT` + +The main use of the Savepoint command is to save a transaction temporarily. This way users can rollback to the point whenever it is needed. + +### Syntax +```sql +SAVEPOINT savepoint-name; +``` + +## Examples + +#### This is purchase table that we are going to use through this tutorial + +| item | price | customer_name | +|--------------|-------|---------------| +| Pen | 10 | Sanskriti | +| Bag | 1000 | Sanskriti | +| Vegetables | 500 | Sanskriti | +| Shoes | 5000 | Sanskriti | +| Water Bottle | 800 | XYZ | +| Mouse | 120 | ABC | +| Sun Glasses | 1350 | ABC | + +```sql +UPDATE purchase SET price = 20 WHERE item = "Pen"; +``` +##### O/P : Query OK, 1 row affected (3.02 sec) (Update the price of Pen set it from 10 to 20) + +```sql +SELECT * FROM purchase; +``` +##### O/P +| item | price | customer_name | +|--------------|-------|---------------| +| Pen | 20 | Sanskriti | +| Bag | 1000 | Sanskriti | +| Vegetables | 500 | Sanskriti | +| Shoes | 5000 | Sanskriti | +| Water Bottle | 800 | XYZ | +| Mouse | 120 | ABC | +| Sun Glasses | 1350 | ABC | + +```sql +START TRANSACTION; +``` +##### Start transaction + +```sql +COMMIT; +``` +##### Saved/ Confirmed the transactions till this point + +```sql +ROLLBACK; +``` +##### Lets consider we tried to rollback above transaction + +```sql +SELECT * FROM purchase; +``` +#### O/P: +| item | price | customer_name | +|--------------|-------|---------------| +| Pen | 20 | Sanskriti | +| Bag | 1000 | Sanskriti | +| Vegetables | 500 | Sanskriti | +| Shoes | 5000 | Sanskriti | +| Water Bottle | 800 | XYZ | +| Mouse | 120 | ABC | +| Sun Glasses | 1350 | ABC | +##### As we have committed the transactions the `rollback` will not affect anything + +```sql +SAVEPOINT sv_update; +``` +##### Create the `savepoint` the transactions above this will not be rollbacked + +```sql +UPDATE purchase SET price = 30 WHERE item = "Pen"; +``` +#### O/P : Query OK, 1 row affected (0.57 sec) +#### Rows matched: 1 Changed: 1 Warnings: 0 + +```sql +SELECT * FROM purchase; +``` + +| item | price | customer_name | +|--------------|-------|---------------| +| Pen | 30 | Sanskriti | +| Bag | 1000 | Sanskriti | +| Vegetables | 500 | Sanskriti | +| Shoes | 5000 | Sanskriti | +| Water Bottle | 800 | XYZ | +| Mouse | 120 | ABC | +| Sun Glasses | 1350 | ABC | +##### price of pen is changed to 30 using the `update` command + +```sql +ROLLBACK to sv_update; +``` +##### Now if we `rollback` to the `savepoint` price should be 20 after `rollback` lets see + +```sql +SELECT * FROM purchase; +``` + +| item | price | customer_name | +|--------------|-------|---------------| +| Pen | 20 | Sanskriti | +| Bag | 1000 | Sanskriti | +| Vegetables | 500 | Sanskriti | +| Shoes | 5000 | Sanskriti | +| Water Bottle | 800 | XYZ | +| Mouse | 120 | ABC | +| Sun Glasses | 1350 | ABC | +| Torch | 850 | ABC | +##### As expected we can see `update` query is rollbacked to sv_update. + + + +## Conclusion + +With this short tutorial we have learnt TCL commands. diff --git a/docs/docs/Introduction-To-Databases/index.md b/docs/docs/Introduction-To-Databases/index.md new file mode 100644 index 0000000..b45b617 --- /dev/null +++ b/docs/docs/Introduction-To-Databases/index.md @@ -0,0 +1,39 @@ +# Databases + +Before we dive deep into SQL, let's quickly define what a database is. + +The definition of databases from Wikipedia is: + +> A database is an organized collection of data, generally stored and accessed electronically from a computer system. + +In other words, a database is a collection of data stored and structured in different database tables. + +## Tables and columns + +You've most likely worked with spreadsheet systems like Excel or Google Sheets. At the very basic, database tables are quite similar to spreadsheets. + +Each table has different **columns** which could contain different types of data. + +For example, if you have a todo list app, you would have a database, and in your database, you would have different tables storing different information like: + +* Users - In the users table, you would have some data for your users like: `username`, `name`, and `active`, for example. +* Tasks - The tasks table would store all of the tasks that you are planning to do. The columns of the tasks table would be for example, `task_name`, `status`, `due_date` and `priority`. + +The Users table will look like this: + +``` ++----+----------+---------------+--------+ +| id | username | name | active | ++----+----------+---------------+--------+ +| 1 | bobby | Bobby Iliev | true | +| 2 | grisi | Greisi I. | true | +| 3 | devdojo | Dev Dojo | false | ++----+----------+---------------+--------+ +``` + +Rundown of the table structure: +* We have 4 columns: `id`, `username`, `name` and `active`. +* We also have 3 entries/users. +* The `id` column is a unique identifier of each user and is auto-incremented. + +In the next chapter, we will learn how to install MySQL and create our first database. diff --git a/docs/docs/cover.png b/docs/docs/cover.png new file mode 100644 index 0000000000000000000000000000000000000000..a6c361927c8a6084fdf454957864c91b75a05f28 GIT binary patch literal 159918 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%0AEAp`qLm)J`F{jECu0J{{$!wqXLCb*#;y-#iOS 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