File notes/00_sum.md changed (mode: 100644) (index e0f3acb..43c6cc9) |
... |
... |
On top of the [references](references) and of the "resources" listed at the begi |
104 |
104 |
- Add title to problem, and solve their naming / referencing issue. |
- Add title to problem, and solve their naming / referencing issue. |
105 |
105 |
- Check with `jhove 00_sum.pdf`, `pdfinfo 00_sum.pdf` the validity of the document. |
- Check with `jhove 00_sum.pdf`, `pdfinfo 00_sum.pdf` the validity of the document. |
106 |
106 |
- Compress / optimize output? |
- Compress / optimize output? |
|
107 |
|
- Make better makefile (compile images in latex, clean up, etc.). |
107 |
108 |
|
|
108 |
109 |
# Introduction |
# Introduction |
109 |
110 |
|
|
|
... |
... |
TICKETS(Id (PK), ShowTimeId (FK to SHOWTIME.Id), Price) |
705 |
706 |
- [@Textbook6, Ch. 4--5], [@Textbook7, Ch. 6--7] describes `SQL`, not one of its implementation. |
- [@Textbook6, Ch. 4--5], [@Textbook7, Ch. 6--7] describes `SQL`, not one of its implementation. |
706 |
707 |
- @problem:installation and @problem:sqldoc contain a list of useful links. |
- @problem:installation and @problem:sqldoc contain a list of useful links. |
707 |
708 |
- To compare DBMS, you can look at their features, at <https://en.wikipedia.org/wiki/Comparison_of_relational_database_management_systems>, and at their popularity at <https://db-engines.com/en/ranking> and <https://www.eversql.com/most-popular-databases-in-2018-according-to-stackoverflow-survey/> (if you sum up MySQL and MariaDB, they are first in both). |
- To compare DBMS, you can look at their features, at <https://en.wikipedia.org/wiki/Comparison_of_relational_database_management_systems>, and at their popularity at <https://db-engines.com/en/ranking> and <https://www.eversql.com/most-popular-databases-in-2018-according-to-stackoverflow-survey/> (if you sum up MySQL and MariaDB, they are first in both). |
|
709 |
|
- MySQL and MariaDB have some differences, you can look them up at <https://mariadb.com/kb/en/library/mariadb-vs-mysql-features/> and <https://mariadb.com/kb/en/library/mariadb-vs-mysql-compatibility/>. |
|
710 |
|
|
|
711 |
|
This chapter will be "code-driven": the code will illustrate and help you understand some concepts. |
|
712 |
|
You may want to have a look at @problem:installation, in the [problem section](#sec:gettingstartedwithmysql), as early as possible in this lecture. |
708 |
713 |
|
|
709 |
714 |
## Actors |
## Actors |
710 |
715 |
|
|
|
... |
... |
The three last sublanguages being dubbed "**D**ata **M**anipulation **L**anguage |
733 |
738 |
|
|
734 |
739 |
#### Yet another vocabulary |
#### Yet another vocabulary |
735 |
740 |
|
|
736 |
|
|
|
737 |
741 |
| "Common" / Relational | SQL | |
| "Common" / Relational | SQL | |
738 |
742 |
| :--: | :--: | |
| :--: | :--: | |
739 |
743 |
| "Database" | Schema | |
| "Database" | Schema | |
|
... |
... |
Type and domains are two different things in some implementations, cf. for insta |
759 |
763 |
#### Syntax |
#### Syntax |
760 |
764 |
|
|
761 |
765 |
- A programming language: strict, cryptic error messages, tricky, evolves |
- A programming language: strict, cryptic error messages, tricky, evolves |
762 |
|
- SQL is "kind of" case-insensitive^[The SQL keywords are case-insensitive, but the table and schema names are sometimes case-sensitive, it depends of the actual implementation.], doesn't care about spaces and new lines |
|
|
766 |
|
- SQL is "kind of" case-insensitive^[The SQL keywords are case-insensitive, but the table and schema names are sometimes case-sensitive, it depends of the actual implementation. For instance, MySQL is completely case-insensitive (reserved words, tables, attributes), MariaDB isn't (case for table names matter).], doesn't care about spaces and new lines |
763 |
767 |
- Comments are with `--` or `/* …*/` |
- Comments are with `--` or `/* …*/` |
764 |
768 |
- Every statement ends with a `;` |
- Every statement ends with a `;` |
765 |
769 |
- Syntax is in @problem:sqldoc. |
- Syntax is in @problem:sqldoc. |
|
... |
... |
Type and domains are two different things in some implementations, cf. for insta |
768 |
772 |
|
|
769 |
773 |
## First Commands |
## First Commands |
770 |
774 |
|
|
771 |
|
~~~{.sql} |
|
|
775 |
|
~~~{.sqlmysql, .numberLines} |
772 |
776 |
CREATE SCHEMA HW_FACULTY; |
CREATE SCHEMA HW_FACULTY; |
773 |
777 |
|
|
774 |
|
/* Or |
|
|
778 |
|
/* Or |
775 |
779 |
CREATE DATABASE HW_FACUTLY; |
CREATE DATABASE HW_FACUTLY; |
776 |
780 |
*/ |
*/ |
777 |
781 |
|
|
|
... |
... |
CREATE TABLE HW_FACULTY.PROF( |
787 |
791 |
PRIMARY KEY(Fname, Hiring) |
PRIMARY KEY(Fname, Hiring) |
788 |
792 |
); |
); |
789 |
793 |
|
|
790 |
|
/* Or |
|
|
794 |
|
/* Or, instead of using the fully qualified name HW_FACULTY.PROF, we could have: |
791 |
795 |
USE HW_FACULTY; |
USE HW_FACULTY; |
792 |
796 |
CREATE TABLE PROF(…) |
CREATE TABLE PROF(…) |
793 |
797 |
*/ |
*/ |
|
... |
... |
INSERT INTO PROF VALUES ( |
807 |
811 |
); |
); |
808 |
812 |
~~~ |
~~~ |
809 |
813 |
|
|
810 |
|
Use `DESCRIBE <TableName>` and `SELECT * FROM <TableName>` intensively to see where you are. |
|
811 |
|
Use `DROP TABLE <TableName>` and `DROP SCHEMA <SchemaName>` for a "fresh start". |
|
|
814 |
|
The following commands are particularly useful: |
|
815 |
|
|
|
816 |
|
~~~{.sqlmysql, , .numberLines} |
|
817 |
|
SHOW SCHEMAS; -- List the schema |
|
818 |
|
SHOW TABLES; -- List the tables in a schema |
|
819 |
|
DESCRIBE <TableName>; -- Show the structure of a table |
|
820 |
|
SELECT * FROM <TableName> -- List all the rows in a table |
|
821 |
|
|
|
822 |
|
DROP TABLE <TableName>; -- "Drop" (erase) a table |
|
823 |
|
DROP SCHEMA <SchemaName>; -- Drop a schema |
|
824 |
|
|
|
825 |
|
DESCRIBE <SQL command>; -- Gives explanations as to how the SQL command is processed |
|
826 |
|
~~~ |
812 |
827 |
|
|
813 |
828 |
--- |
--- |
814 |
829 |
|
|
|
... |
... |
f. `CHECK` |
823 |
838 |
|
|
824 |
839 |
We know a. and b. from the Relational Model, here comes new constraints that can't be describe in our relations. |
We know a. and b. from the Relational Model, here comes new constraints that can't be describe in our relations. |
825 |
840 |
|
|
826 |
|
~~~{.sql} |
|
|
841 |
|
~~~{.sqlmysql, , .numberLines} |
827 |
842 |
CREATE TABLE HURRICANE( |
CREATE TABLE HURRICANE( |
828 |
843 |
Name VARCHAR(25) PRIMARY KEY, |
Name VARCHAR(25) PRIMARY KEY, |
829 |
844 |
WindSpeed INT DEFAULT 76, |
WindSpeed INT DEFAULT 76, |
830 |
845 |
Above VARCHAR(25) |
Above VARCHAR(25) |
831 |
846 |
); |
); |
832 |
847 |
-- WindSpeed INT CHECK (WindSpeed > 74 AND WindSpeed < 500), |
-- WindSpeed INT CHECK (WindSpeed > 74 AND WindSpeed < 500), |
|
848 |
|
-- would be parsed but wouldn't have any effect! |
833 |
849 |
|
|
834 |
850 |
CREATE TABLE STATE( |
CREATE TABLE STATE( |
835 |
|
Name VARCHAR(25) UNIQUE, |
|
|
851 |
|
Name VARCHAR(25) UNIQUE, -- NULL can be inserted |
836 |
852 |
Postal_abbr CHAR(2) NOT NULL |
Postal_abbr CHAR(2) NOT NULL |
837 |
853 |
); |
); |
838 |
854 |
~~~ |
~~~ |
839 |
855 |
|
|
840 |
|
- You can insert `NULL` in `UNIQUE` attributes. |
|
841 |
|
- `CHECK` constraints are parsed but don't do anything! |
|
|
856 |
|
`MySQL` can output a description of those tables for us: |
|
857 |
|
|
|
858 |
|
~~~{.sqlmysql} |
|
859 |
|
MariaDB [HW_CONSTRAINTS_PART1]> DESCRIBE HURRICANE; |
|
860 |
|
+-----------+-------------+------+-----+---------+-------+ |
|
861 |
|
| Field | Type | Null | Key | Default | Extra | |
|
862 |
|
+-----------+-------------+------+-----+---------+-------+ |
|
863 |
|
| Name | varchar(25) | NO | PRI | NULL | | |
|
864 |
|
| WindSpeed | int(11) | YES | | 76 | | |
|
865 |
|
| Above | varchar(25) | YES | | NULL | | |
|
866 |
|
+-----------+-------------+------+-----+---------+-------+ |
|
867 |
|
3 rows in set (0.01 sec) |
|
868 |
|
|
|
869 |
|
MariaDB [HW_CONSTRAINTS_PART1]> DESCRIBE STATE; |
|
870 |
|
+-------------+-------------+------+-----+---------+-------+ |
|
871 |
|
| Field | Type | Null | Key | Default | Extra | |
|
872 |
|
+-------------+-------------+------+-----+---------+-------+ |
|
873 |
|
| Name | varchar(25) | NO | PRI | NULL | | |
|
874 |
|
| Postal_abbr | char(2) | NO | UNI | NULL | | |
|
875 |
|
+-------------+-------------+------+-----+---------+-------+ |
|
876 |
|
2 rows in set (0.00 sec) |
|
877 |
|
~~~ |
842 |
878 |
|
|
843 |
|
~~~{.sql} |
|
|
879 |
|
~~~{.sqlmysql, .numberLines} |
844 |
880 |
-- Adding a primary key: |
-- Adding a primary key: |
845 |
881 |
ALTER TABLE STATE ADD PRIMARY KEY (Name); |
ALTER TABLE STATE ADD PRIMARY KEY (Name); |
846 |
882 |
|
|
|
883 |
|
-- Removing the primary key: |
|
884 |
|
ALTER TABLE STATE DROP PRIMARY KEY; |
|
885 |
|
|
847 |
886 |
-- Adding a UNIQUE constraint |
-- Adding a UNIQUE constraint |
848 |
887 |
ALTER TABLE STATE ADD UNIQUE (Postal_abbr); |
ALTER TABLE STATE ADD UNIQUE (Postal_abbr); |
849 |
888 |
|
|
850 |
|
ALTER TABLE STATE MODIFY Postal_abbr CHAR(2); |
|
|
889 |
|
-- Removing a UNIQUE constraint |
|
890 |
|
ALTER TABLE STATE DROP INDEX Postal_abbr; |
851 |
891 |
|
|
852 |
|
ALTER TABLE STATE DROP INDEX Name; |
|
|
892 |
|
-- Adding the NOT NULL constraint |
|
893 |
|
ALTER TABLE STATE MODIFY Postal_abbr CHAR(2) NOT NULL; |
|
894 |
|
|
|
895 |
|
-- Removing the NOT NULL constraint |
|
896 |
|
ALTER TABLE STATE MODIFY Postal_abbr CHAR(2); |
853 |
897 |
|
|
854 |
898 |
-- Changing the default value |
-- Changing the default value |
855 |
899 |
ALTER TABLE HURRICANE ALTER COLUMN WindSpeed SET DEFAULT 74; |
ALTER TABLE HURRICANE ALTER COLUMN WindSpeed SET DEFAULT 74; |
856 |
900 |
|
|
|
901 |
|
-- Removing the default value |
|
902 |
|
ALTER TABLE HURRICANE ALTER COLUMN WindSpeed DROP DEFAULT; |
|
903 |
|
|
857 |
904 |
--Adding a foreign key constraint |
--Adding a foreign key constraint |
858 |
905 |
ALTER TABLE HURRICANE ADD FOREIGN KEY (Above) REFERENCES STATE(Name); |
ALTER TABLE HURRICANE ADD FOREIGN KEY (Above) REFERENCES STATE(Name); |
859 |
906 |
~~~ |
~~~ |
860 |
907 |
|
|
861 |
908 |
- `NOT NULL` is to some extend part of the datatype. |
- `NOT NULL` is to some extend part of the datatype. |
862 |
|
- Note the difference between adding and removing the `NOT NULL` constraint. |
|
|
909 |
|
- Note the difference between adding and removing the `UNIQUE` constraint: in one case, the parenthesis are mandatory, in the other, they would cause an error! In this example, the parenthesis around `(Name)` and `(Postal_abbr)` are mandatory. |
863 |
910 |
- The datatype of the foreign key has to be the same as what we are referring. |
- The datatype of the foreign key has to be the same as what we are referring. |
864 |
|
- The parenthesis around (Name) and (Postal_abbr) to add the primary and foreign keys, and the UNIQUE constraints, are mandatory. |
|
865 |
911 |
|
|
866 |
912 |
A bit of testing: |
A bit of testing: |
867 |
913 |
|
|
868 |
|
~~~{.sql} |
|
|
914 |
|
~~~{.sqlmysql, .numberLines} |
869 |
915 |
INSERT INTO STATE VALUES('Georgia', 'GA'); |
INSERT INTO STATE VALUES('Georgia', 'GA'); |
870 |
916 |
INSERT INTO STATE VALUES('Texas', 'TX'); |
INSERT INTO STATE VALUES('Texas', 'TX'); |
871 |
917 |
INSERT INTO STATE VALUES('FLORIDA', 'FL'); |
INSERT INTO STATE VALUES('FLORIDA', 'FL'); |
872 |
|
UPDATE STATE SET Name = 'Florida' WHERE Postal_abbr = 'FL'; |
|
|
918 |
|
UPDATE STATE SET Name = 'Florida' |
|
919 |
|
WHERE Postal_abbr = 'FL'; |
873 |
920 |
|
|
874 |
921 |
-- There's an error with the following request. Why? |
-- There's an error with the following request. Why? |
875 |
922 |
INSERT INTO HURRICANE VALUES('Irma', 150, 'FL'); |
INSERT INTO HURRICANE VALUES('Irma', 150, 'FL'); |
|
... |
... |
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint f |
881 |
926 |
|
|
882 |
927 |
INSERT INTO HURRICANE VALUES('Harvey', DEFAULT , 'Texas'); |
INSERT INTO HURRICANE VALUES('Harvey', DEFAULT , 'Texas'); |
883 |
928 |
INSERT INTO HURRICANE VALUES('Irma', 150, 'Florida'); |
INSERT INTO HURRICANE VALUES('Irma', 150, 'Florida'); |
884 |
|
DELETE FROM HURRICANE WHERE Name = 'Irma'; |
|
|
929 |
|
DELETE FROM HURRICANE |
|
930 |
|
WHERE Name = 'Irma'; |
885 |
931 |
INSERT INTO HURRICANE VALUES('Irma', 150, 'Georgia'); |
INSERT INTO HURRICANE VALUES('Irma', 150, 'Georgia'); |
886 |
932 |
|
|
887 |
|
UPDATE HURRICANE SET Above = 'Georgia' WHERE Name = 'Irma'; |
|
|
933 |
|
UPDATE HURRICANE SET Above = 'Georgia' |
|
934 |
|
WHERE Name = 'Irma'; |
888 |
935 |
|
|
889 |
936 |
/* |
/* |
890 |
937 |
MariaDB [HW_CONSTRAINTS_PART1]> SELECT * FROM HURRICANE; |
MariaDB [HW_CONSTRAINTS_PART1]> SELECT * FROM HURRICANE; |
|
... |
... |
MariaDB [HW_CONSTRAINTS_PART1]> SELECT * FROM HURRICANE; |
897 |
944 |
*/ |
*/ |
898 |
945 |
|
|
899 |
946 |
-- There's an error with the following request. Why? |
-- There's an error with the following request. Why? |
900 |
|
UPDATE HURRICANE SET Above = 'North Carolina' WHERE Name = 'Irma'; |
|
|
947 |
|
UPDATE HURRICANE SET Above = 'North Carolina' |
|
948 |
|
WHERE Name = 'Irma'; |
901 |
949 |
|
|
902 |
950 |
-- Let's patch it, by adding North Carolina to our STATE table. |
-- Let's patch it, by adding North Carolina to our STATE table. |
903 |
951 |
INSERT INTO STATE VALUES('North Carolina', 'NC'); |
INSERT INTO STATE VALUES('North Carolina', 'NC'); |
904 |
|
UPDATE HURRICANE SET Above = 'North Carolina' WHERE Name = 'Irma'; |
|
|
952 |
|
UPDATE HURRICANE SET Above = 'North Carolina' |
|
953 |
|
WHERE Name = 'Irma'; |
905 |
954 |
~~~ |
~~~ |
906 |
955 |
|
|
907 |
956 |
## Foreign Keys |
## Foreign Keys |
908 |
957 |
|
|
909 |
|
~~~{.sql} |
|
|
958 |
|
~~~{.sqlmysql, .numberLines} |
910 |
959 |
CREATE TABLE STORM( |
CREATE TABLE STORM( |
911 |
960 |
Name VARCHAR(25) PRIMARY KEY, |
Name VARCHAR(25) PRIMARY KEY, |
912 |
961 |
Kind ENUM('Tropical Storm', 'Hurricane'), |
Kind ENUM('Tropical Storm', 'Hurricane'), |
|
... |
... |
CREATE TABLE STATE( |
926 |
975 |
ON UPDATE CASCADE |
ON UPDATE CASCADE |
927 |
976 |
); |
); |
928 |
977 |
|
|
929 |
|
|
|
|
978 |
|
|
930 |
979 |
INSERT INTO STORM VALUES('Harvey', 'Hurricane', 130, '2017-08-17'); |
INSERT INTO STORM VALUES('Harvey', 'Hurricane', 130, '2017-08-17'); |
931 |
980 |
-- In the following, the entry gets created, but date is 0000-00-00! |
-- In the following, the entry gets created, but date is 0000-00-00! |
932 |
981 |
INSERT INTO STORM VALUES('Dummy', 'Hurricane', 120, '2017-17-08'); |
INSERT INTO STORM VALUES('Dummy', 'Hurricane', 120, '2017-17-08'); |
|
... |
... |
INSERT INTO STORM VALUES('Dummy', 'Hurricane', 120, '2017-17-08'); |
934 |
983 |
INSERT INTO STORM VALUES('Dummy2', 'Hurricane', 120, DATE'2017-17-08'); |
INSERT INTO STORM VALUES('Dummy2', 'Hurricane', 120, DATE'2017-17-08'); |
935 |
984 |
-- The next one sets NULL for DATE. |
-- The next one sets NULL for DATE. |
936 |
985 |
INSERT INTO STORM VALUES('Irma', 'Tropical Storm', 102, DEFAULT); |
INSERT INTO STORM VALUES('Irma', 'Tropical Storm', 102, DEFAULT); |
|
986 |
|
~~~ |
|
987 |
|
|
|
988 |
|
MySQL will always notify you if there is an error in a date attribute |
|
989 |
|
|
|
990 |
|
~~~{.sqlmysql, .numberLines} |
937 |
991 |
|
|
938 |
992 |
INSERT INTO STATE VALUES('Georgia', 'GA', NULL); |
INSERT INTO STATE VALUES('Georgia', 'GA', NULL); |
939 |
993 |
INSERT INTO STATE VALUES('Texas', 'TX', NULL); |
INSERT INTO STATE VALUES('Texas', 'TX', NULL); |
940 |
994 |
INSERT INTO STATE VALUES('Florida', 'FL', NULL); |
INSERT INTO STATE VALUES('Florida', 'FL', NULL); |
941 |
995 |
|
|
942 |
996 |
-- This instruction is not using the primary key, is that a problem? |
-- This instruction is not using the primary key, is that a problem? |
943 |
|
UPDATE STATE SET Affected_by = 'Harvey' WHERE Name = 'Georgia'; |
|
|
997 |
|
UPDATE STATE SET Affected_by = 'Harvey' |
|
998 |
|
WHERE Name = 'Georgia'; |
944 |
999 |
|
|
945 |
1000 |
UPDATE STORM SET Name = 'Harley' WHERE Name = 'Harvey'; |
UPDATE STORM SET Name = 'Harley' WHERE Name = 'Harvey'; |
946 |
|
DELETE FROM STORM WHERE Name = 'Harley'; |
|
|
1001 |
|
DELETE FROM STORM |
|
1002 |
|
WHERE Name = 'Harley'; |
947 |
1003 |
~~~ |
~~~ |
948 |
1004 |
|
|
949 |
1005 |
## Foreign Keys Restrictions |
## Foreign Keys Restrictions |
950 |
1006 |
|
|
951 |
|
~~~{.sql} |
|
|
1007 |
|
~~~{.sqlmysql, .numberLines} |
952 |
1008 |
CREATE TABLE F_Key( |
CREATE TABLE F_Key( |
953 |
1009 |
Attribute VARCHAR(25) PRIMARY KEY |
Attribute VARCHAR(25) PRIMARY KEY |
954 |
1010 |
); |
); |
|
... |
... |
SELECT * FROM Table_cascade; |
1005 |
1061 |
SELECT * FROM Table_set_null; |
SELECT * FROM Table_set_null; |
1006 |
1062 |
|
|
1007 |
1063 |
-- The following will fail because of the Table_default table: |
-- The following will fail because of the Table_default table: |
1008 |
|
UPDATE F_Key SET Attribute = 'After Update' WHERE Attribute = 'First Test'; |
|
1009 |
|
DELETE FROM F_Key WHERE Attribute = 'First Test'; |
|
|
1064 |
|
UPDATE F_Key SET Attribute = 'After Update' |
|
1065 |
|
WHERE Attribute = 'First Test'; |
|
1066 |
|
DELETE FROM F_Key |
|
1067 |
|
WHERE Attribute = 'First Test'; |
1010 |
1068 |
|
|
1011 |
1069 |
-- Let us drop this table, and try again. |
-- Let us drop this table, and try again. |
1012 |
1070 |
DROP TABLE Table_default; |
DROP TABLE Table_default; |
|
... |
... |
DROP TABLE Table_default; |
1014 |
1072 |
|
|
1015 |
1073 |
--- |
--- |
1016 |
1074 |
|
|
1017 |
|
~~~{.sql} |
|
|
1075 |
|
~~~{.sqlmysql, .numberLines} |
1018 |
1076 |
-- The following fails too, this time because of the Table_restrict table: |
-- The following fails too, this time because of the Table_restrict table: |
1019 |
|
UPDATE F_Key SET Attribute = 'After Update' WHERE Attribute = 'First Test'; |
|
1020 |
|
DELETE FROM F_Key WHERE Attribute = 'First Test'; |
|
|
1077 |
|
UPDATE F_Key SET Attribute = 'After Update' |
|
1078 |
|
WHERE Attribute = 'First Test'; |
|
1079 |
|
DELETE FROM F_Key |
|
1080 |
|
WHERE Attribute = 'First Test'; |
1021 |
1081 |
|
|
1022 |
1082 |
-- Let us drop this table, and try again. |
-- Let us drop this table, and try again. |
1023 |
1083 |
DROP TABLE Table_restrict; |
DROP TABLE Table_restrict; |
|
... |
... |
INSERT INTO F_Key VALUES('Second Test'); |
1052 |
1112 |
INSERT INTO Table_cascade VALUES('Default', 'Second Test'); |
INSERT INTO Table_cascade VALUES('Default', 'Second Test'); |
1053 |
1113 |
INSERT INTO Table_set_null VALUES('Restrict', 'Second Test'); |
INSERT INTO Table_set_null VALUES('Restrict', 'Second Test'); |
1054 |
1114 |
|
|
1055 |
|
DELETE FROM F_Key WHERE Attribute = 'Second Test'; |
|
|
1115 |
|
DELETE FROM F_Key |
|
1116 |
|
WHERE Attribute = 'Second Test'; |
1056 |
1117 |
|
|
1057 |
|
SELECT * FROM Table_cascade; |
|
1058 |
|
SELECT * FROM Table_set_null; |
|
|
1118 |
|
/* |
|
1119 |
|
MariaDB [HW_CONSTRAINTS_PART3]> SELECT * FROM Table_cascade; |
|
1120 |
|
+------------+--------------+ |
|
1121 |
|
| Attribute1 | Attribute2 | |
|
1122 |
|
+------------+--------------+ |
|
1123 |
|
| Cascade | After Update | |
|
1124 |
|
+------------+--------------+ |
|
1125 |
|
1 row in set (0.00 sec) |
|
1126 |
|
|
|
1127 |
|
MariaDB [HW_CONSTRAINTS_PART3]> SELECT * FROM Table_set_null; |
|
1128 |
|
+------------+------------+ |
|
1129 |
|
| Attribute1 | Attribute2 | |
|
1130 |
|
+------------+------------+ |
|
1131 |
|
| Restrict | NULL | |
|
1132 |
|
| Set null | NULL | |
|
1133 |
|
+------------+------------+ |
|
1134 |
|
2 rows in set (0.00 sec) |
|
1135 |
|
*/ |
1059 |
1136 |
~~~ |
~~~ |
1060 |
1137 |
|
|
1061 |
1138 |
--- |
--- |
|
... |
... |
SELECT * FROM Table_set_null; |
1066 |
1142 |
#### Construction |
#### Construction |
1067 |
1143 |
|
|
1068 |
1144 |
- Remember, we start by creating a schema and tables inside of it. |
- Remember, we start by creating a schema and tables inside of it. |
1069 |
|
- What if foreign keys are mutually dependent? |
|
|
1145 |
|
- What if foreign keys are mutually dependent? What if we have something like: |
1070 |
1146 |
|
|
1071 |
|
~~~{.sql} |
|
|
1147 |
|
{ width=100% } |
|
1151 |
|
\ |
|
1152 |
|
|
|
1153 |
|
~~~{.sqlmysql, .numberLines} |
1072 |
1154 |
CREATE TABLE PROF( |
CREATE TABLE PROF( |
1073 |
1155 |
Login VARCHAR(25) PRIMARY KEY, |
Login VARCHAR(25) PRIMARY KEY, |
1074 |
1156 |
Name VARCHAR(25), |
Name VARCHAR(25), |
|
... |
... |
CREATE TABLE DEPARTMENT( |
1083 |
1165 |
ON UPDATE CASCADE |
ON UPDATE CASCADE |
1084 |
1166 |
); |
); |
1085 |
1167 |
|
|
1086 |
|
ALTER TABLE PROF ADD FOREIGN KEY (Department) REFERENCES DEPARTMENT(Code); |
|
|
1168 |
|
ALTER TABLE PROF ADD FOREIGN KEY (Department) |
|
1169 |
|
REFERENCES DEPARTMENT(Code); |
1087 |
1170 |
~~~ |
~~~ |
1088 |
1171 |
|
|
1089 |
1172 |
Note the structure of the `ALTER TABLE` command: |
Note the structure of the `ALTER TABLE` command: |
1090 |
1173 |
|
|
1091 |
|
- … `KEY Department REFERENCES Code;`: error |
|
1092 |
|
- … `KEY (Department) REFERENCES (Code);`: error |
|
1093 |
|
- … `KEY PROF(Department) REFERENCES DEPARTMENT(Code);`: ok |
|
|
1174 |
|
- … `KEY Department REFERENCES Code;`⇒ error |
|
1175 |
|
- … `KEY (Department) REFERENCES (Code);`⇒ error |
|
1176 |
|
- … `KEY PROF(Department) REFERENCES DEPARTMENT(Code);` ⇒ ok |
1094 |
1177 |
|
|
1095 |
|
~~~{.sql} |
|
|
1178 |
|
~~~{.sqlmysql, .numberLines} |
1096 |
1179 |
CREATE TABLE STUDENT( |
CREATE TABLE STUDENT( |
1097 |
1180 |
Login VARCHAR(25) PRIMARY KEY, |
Login VARCHAR(25) PRIMARY KEY, |
1098 |
1181 |
Name VARCHAR(25), |
Name VARCHAR(25), |
|
... |
... |
CREATE TABLE STUDENT( |
1106 |
1189 |
|
|
1107 |
1190 |
We can insert multiple values at once: |
We can insert multiple values at once: |
1108 |
1191 |
|
|
1109 |
|
~~~{.sql} |
|
|
1192 |
|
~~~{.sqlmysql} |
1110 |
1193 |
INSERT INTO DEPARTMENT VALUES |
INSERT INTO DEPARTMENT VALUES |
1111 |
1194 |
('MATH', 'Mathematics', NULL), |
('MATH', 'Mathematics', NULL), |
1112 |
1195 |
('CS', 'Computer Science', NULL); |
('CS', 'Computer Science', NULL); |
|
... |
... |
INSERT INTO DEPARTMENT VALUES |
1114 |
1197 |
|
|
1115 |
1198 |
We can specify which attributes we are giving: |
We can specify which attributes we are giving: |
1116 |
1199 |
|
|
1117 |
|
~~~{.sql} |
|
|
1200 |
|
~~~{.sqlmysql} |
1118 |
1201 |
INSERT INTO DEPARTMENT (Code, Name) VALUES |
INSERT INTO DEPARTMENT (Code, Name) VALUES |
1119 |
1202 |
('CYBR', 'Cyber Secturity'); |
('CYBR', 'Cyber Secturity'); |
1120 |
1203 |
~~~ |
~~~ |
1121 |
1204 |
|
|
1122 |
1205 |
And we can even specify the order (even the trivial one): |
And we can even specify the order (even the trivial one): |
1123 |
1206 |
|
|
1124 |
|
~~~{.sql} |
|
|
1207 |
|
~~~{.sqlmysql, .numberLines} |
1125 |
1208 |
INSERT INTO PROF (Login, Department, Name) VALUES |
INSERT INTO PROF (Login, Department, Name) VALUES |
1126 |
1209 |
('caubert', 'CS', 'Clément Aubert'); |
('caubert', 'CS', 'Clément Aubert'); |
1127 |
1210 |
|
|
|
... |
... |
INSERT INTO STUDENT (Login, Name, Registered, Major) VALUES |
1138 |
1221 |
('caubert', 'Clément Aubert', NULL, 'CYBR'); |
('caubert', 'Clément Aubert', NULL, 'CYBR'); |
1139 |
1222 |
~~~ |
~~~ |
1140 |
1223 |
|
|
1141 |
|
Note the date litterals. |
|
1142 |
|
|
|
1143 |
|
#### A note on the differences between MySQL and MariaDB {#differenceMySQLMariaDB} |
|
1144 |
|
|
|
1145 |
|
- MySQL is completely case-insensitive (reserved words, tables, attributes), MariaDB isn't (case for tables matter). |
|
1146 |
|
- MySQL will always notify you if there is an error in a date attribute |
|
1147 |
|
|
|
1148 |
|
Refer to <https://mariadb.com/kb/en/library/mariadb-vs-mysql-features/> and <https://mariadb.com/kb/en/library/mariadb-vs-mysql-compatibility/> for a full list. |
|
1149 |
|
|
|
|
1224 |
|
Note the date literals. |
1150 |
1225 |
|
|
1151 |
1226 |
## A First Look at Conditions |
## A First Look at Conditions |
1152 |
1227 |
|
|
1153 |
1228 |
Order of clauses does not matter, not even for optimization purpose. |
Order of clauses does not matter, not even for optimization purpose. |
1154 |
1229 |
|
|
1155 |
1230 |
|
|
1156 |
|
~~~{.sql} |
|
|
1231 |
|
~~~{.sqlmysql} |
1157 |
1232 |
UPDATE <table> |
UPDATE <table> |
1158 |
1233 |
SET <attribute1> = <value1>, <attribute2> = <value2>, … |
SET <attribute1> = <value1>, <attribute2> = <value2>, … |
1159 |
1234 |
WHERE <condition>; |
WHERE <condition>; |
|
... |
... |
WHERE <condition>; |
1161 |
1236 |
SELECT <attribute list, called projection attributes> |
SELECT <attribute list, called projection attributes> |
1162 |
1237 |
FROM <table list> |
FROM <table list> |
1163 |
1238 |
WHERE <condition>; |
WHERE <condition>; |
|
1239 |
|
|
|
1240 |
|
DELETE FROM <table list> |
|
1241 |
|
WHERE <condition>; |
1164 |
1242 |
~~~ |
~~~ |
1165 |
1243 |
|
|
1166 |
1244 |
Conditions can |
Conditions can |
1167 |
1245 |
|
|
1168 |
1246 |
- be compounded |
- be compounded |
1169 |
|
- `condition1 AND condition2 AND condition3` |
|
|
1247 |
|
- `condition1 AND condition2` |
1170 |
1248 |
- `condition1 OR condition2` |
- `condition1 OR condition2` |
1171 |
1249 |
- `NOT condition` |
- `NOT condition` |
|
1250 |
|
- Usage of parenthesis is possible |
1172 |
1251 |
- be trivial / empty |
- be trivial / empty |
1173 |
|
- use regular expressions (escape character is `\`). |
|
|
1252 |
|
- use regular expressions |
|
1253 |
|
- uses the expression `LIKE`, |
|
1254 |
|
- escape character is `\`, |
|
1255 |
|
- `_` will match one character (any character), `%` will match any number of character, |
|
1256 |
|
- advanced regular expression possible using the `REGEXP` keyword. |
1174 |
1257 |
|
|
1175 |
|
~~~{.sql} |
|
1176 |
|
UPDATE Department SET Head = 'aturing' WHERE Code = 'MATH'; |
|
|
1258 |
|
~~~{.sqlmysql} |
|
1259 |
|
SELECT Login FROM STUDENT; |
1177 |
1260 |
|
|
1178 |
|
UPDATE Department SET Head = 'bgates' WHERE Code = 'CS' OR NOT Code = 'CYBR'; |
|
|
1261 |
|
UPDATE Department SET Head = 'aturing' |
|
1262 |
|
WHERE Code = 'MATH'; |
1179 |
1263 |
|
|
1180 |
|
SELECT Login FROM STUDENT WHERE Major = 'CYBR'; |
|
|
1264 |
|
UPDATE Department SET Head = 'bgates' |
|
1265 |
|
WHERE Code = 'CS' OR Code = 'CYBR'; |
1181 |
1266 |
|
|
1182 |
|
SELECT Login, Name FROM PROF WHERE Department = 'CS'; |
|
|
1267 |
|
SELECT Login FROM STUDENT |
|
1268 |
|
WHERE NOT Major = 'CYBR'; |
1183 |
1269 |
|
|
1184 |
|
SELECT Login FROM STUDENT WHERE Major = 'CYBR' AND Registered > DATE'20121001'; |
|
|
1270 |
|
SELECT Login, Name FROM PROF |
|
1271 |
|
WHERE Department = 'CS'; |
1185 |
1272 |
|
|
1186 |
|
SELECT Login FROM STUDENT; |
|
|
1273 |
|
SELECT Login FROM STUDENT |
|
1274 |
|
WHERE Major = 'CYBR' |
|
1275 |
|
AND Registered > DATE'20121001'; |
1187 |
1276 |
|
|
1188 |
|
SELECT Login FROM STUDENT WHERE Name LIKE 'Ava%'; |
|
|
1277 |
|
SELECT Login FROM STUDENT |
|
1278 |
|
WHERE Name LIKE 'Ava%'; |
1189 |
1279 |
|
|
1190 |
|
SELECT Name FROM PROF WHENE Login LIKE '_aubert'; |
|
|
1280 |
|
SELECT Name FROM PROF |
|
1281 |
|
WHERE Login LIKE '_aubert'; |
1191 |
1282 |
~~~ |
~~~ |
1192 |
1283 |
|
|
1193 |
1284 |
--- |
--- |
1194 |
1285 |
|
|
1195 |
1286 |
## Various Tools |
## Various Tools |
1196 |
1287 |
|
|
1197 |
|
For `DISTINCT`, `ALL` and `UNION`, cf. [@Textbook6, 4.3.4]. For `ORDER BY` , cf. [@Textbook6, 4.3.6]. |
|
1198 |
|
For aggregate functions, cf. [@Textbook6, 5.1.7]. |
|
|
1288 |
|
For `DISTINCT`, `ALL` and `UNION`, cf. [@Textbook6, 4.3.4] or [@Textbook7, 6.3.4]. |
|
1289 |
|
For `ORDER BY` , cf. [@Textbook6, 4.3.6] or [@Textbook7, 6.3.6]. |
|
1290 |
|
For aggregate functions, cf. [@Textbook6, 5.1.7] or [@Textbook7, 7.1.7]. |
1199 |
1291 |
|
|
1200 |
|
### DISTINCT / ALL and Union |
|
|
1292 |
|
### DISTINCT / ALL |
1201 |
1293 |
|
|
1202 |
|
Note: SQL treats tables as multi-set, there can be repetitions in the tables. |
|
|
1294 |
|
The result of a `SELECT` query, for instance, is a table, and SQL treats tables as multi-set, hence there can be repetitions in the result of a query, but we can remove them: |
1203 |
1295 |
|
|
1204 |
|
~~~{.sql} |
|
|
1296 |
|
~~~{.sqlmysql} |
1205 |
1297 |
SELECT DISTINCT Major FROM STUDENT; |
SELECT DISTINCT Major FROM STUDENT; |
1206 |
1298 |
~~~ |
~~~ |
1207 |
1299 |
|
|
1208 |
|
The default behaviour is `ALL`, but we can declare it explicitely. |
|
|
1300 |
|
The default behaviour is equivalent to specifying `ALL`, and it display the duplicates. |
|
1301 |
|
|
|
1302 |
|
### UNION |
1209 |
1303 |
|
|
1210 |
|
~~~{.sql} |
|
|
1304 |
|
~~~{.sqlmysql} |
1211 |
1305 |
(SELECT Login FROM STUDENT) UNION (SELECT Login FROM PROF); |
(SELECT Login FROM STUDENT) UNION (SELECT Login FROM PROF); |
1212 |
1306 |
~~~ |
~~~ |
1213 |
1307 |
|
|
1214 |
|
There is also `INTERSECT` and `EXCEPT` in the specification, but MariaDB and MySQL do not implement them. |
|
|
1308 |
|
There is also `INTERSECT` and `EXCEPT` in the specification, but MySQL does not implement them (cf. <https://en.wikipedia.org/wiki/Comparison_of_relational_database_management_systems#Database_capabilities>). |
1215 |
1309 |
|
|
1216 |
1310 |
### ORDER BY |
### ORDER BY |
1217 |
1311 |
|
|
1218 |
1312 |
You can have `ORDER BY` specifications: |
You can have `ORDER BY` specifications: |
1219 |
1313 |
|
|
1220 |
|
~~~{.sql} |
|
1221 |
|
SELECT Login FROM GRADE WHERE Grade > 3.0 ORDER BY Grade; |
|
|
1314 |
|
~~~{.sqlmysql} |
|
1315 |
|
SELECT Login FROM GRADE |
|
1316 |
|
WHERE Grade > 3.0 |
|
1317 |
|
ORDER BY Grade; |
1222 |
1318 |
|
|
1223 |
|
SELECT Login FROM GRADE WHERE Grade > 3.0 ORDER BY Grade DESC; |
|
|
1319 |
|
SELECT Login FROM GRADE |
|
1320 |
|
WHERE Grade > 3.0 |
|
1321 |
|
ORDER BY Grade DESC; |
1224 |
1322 |
|
|
1225 |
|
SELECT Login, Major FROM STUDENT ORDER BY Major, Name; |
|
|
1323 |
|
SELECT Login, Major FROM STUDENT |
|
1324 |
|
ORDER BY Major, Name; |
1226 |
1325 |
~~~ |
~~~ |
1227 |
1326 |
|
|
1228 |
1327 |
### Aggregate functions |
### Aggregate functions |
1229 |
1328 |
|
|
1230 |
1329 |
You can use `MAX`, `SUM`, `MIN`, `AVG`, `COUNT`: |
You can use `MAX`, `SUM`, `MIN`, `AVG`, `COUNT`: |
1231 |
1330 |
|
|
1232 |
|
~~~{.sql} |
|
|
1331 |
|
~~~{.sqlmysql} |
1233 |
1332 |
SELECT MAX(Registered) FROM STUDENT; |
SELECT MAX(Registered) FROM STUDENT; |
1234 |
1333 |
|
|
1235 |
1334 |
SELECT COUNT(Name) FROM STUDENT; |
SELECT COUNT(Name) FROM STUDENT; |
|
... |
... |
SELECT COUNT(DISTINCT Name) FROM STUDENT; |
1239 |
1338 |
|
|
1240 |
1339 |
### Aliases for columns |
### Aliases for columns |
1241 |
1340 |
|
|
1242 |
|
~~~{.sql} |
|
|
1341 |
|
~~~{.sqlmysql} |
|
1342 |
|
SELECT Login FROM PROF; |
|
1343 |
|
+---------+ |
|
1344 |
|
| Login | |
|
1345 |
|
+---------+ |
|
1346 |
|
| aturing | |
|
1347 |
|
| caubert | |
|
1348 |
|
| bgates | |
|
1349 |
|
| perdos | |
|
1350 |
|
+---------+ |
|
1351 |
|
|
1243 |
1352 |
SELECT Login AS Username FROM PROF; |
SELECT Login AS Username FROM PROF; |
|
1353 |
|
+----------+ |
|
1354 |
|
| Username | |
|
1355 |
|
+----------+ |
|
1356 |
|
| aturing | |
|
1357 |
|
| caubert | |
|
1358 |
|
| bgates | |
|
1359 |
|
| perdos | |
|
1360 |
|
+----------+ |
1244 |
1361 |
~~~ |
~~~ |
1245 |
1362 |
|
|
1246 |
1363 |
## Three-Valued Logic |
## Three-Valued Logic |
1247 |
1364 |
|
|
1248 |
|
Cf. [@Textbook6,5.1.1] |
|
|
1365 |
|
Cf. [@Textbook6, 5.1.1], [@Textbook7, 7.1.1] |
1249 |
1366 |
|
|
1250 |
1367 |
### Meaning of `NULL` |
### Meaning of `NULL` |
1251 |
1368 |
|
|
1252 |
1369 |
`NULL` is |
`NULL` is |
1253 |
1370 |
|
|
1254 |
|
1. Unknown Value |
|
1255 |
|
2. Unavailable / Withheld |
|
1256 |
|
3. Not Applicable |
|
|
1371 |
|
1. Unknown value ("What is the date of birth of Jack the Ripper", "Is P = NP?") |
|
1372 |
|
2. Unavailable / Withheld ("What is the number of english spies in France", "What is the identity of the Tiananmen Square Guy") |
|
1373 |
|
3. Not Applicable ("What is the US SSN of a french person?", "What is the email address of an author of the XIXth century?") |
1257 |
1374 |
|
|
1258 |
1375 |
### Comparison with unknown values |
### Comparison with unknown values |
1259 |
1376 |
|
|
1260 |
|
If `NULL` is involved in a comparison, the result evaluates to "Unknown". |
|
|
1377 |
|
If `NULL` is involved in a comparison, the result evaluates to "**U**nknown". |
1261 |
1378 |
|
|
1262 |
1379 |
|||| |
|||| |
1263 |
1380 |
:--: | :--: | :--: | :--: |
:--: | :--: | :--: | :--: |
|
... |
... |
For nested queries, cf. [@Textbook6, 5.1.2]. |
1292 |
1409 |
|
|
1293 |
1410 |
### Select-project-join (4.3.1) |
### Select-project-join (4.3.1) |
1294 |
1411 |
|
|
1295 |
|
~~~{.sql} |
|
1296 |
|
SELECT Login FROM PROF, DEPARTMENT WHERE DEPARTMENT.Name = 'Mathematics' AND Department = Code; |
|
|
1412 |
|
~~~{.sqlmysql} |
|
1413 |
|
SELECT Login FROM PROF, DEPARTMENT |
|
1414 |
|
WHERE DEPARTMENT.Name = 'Mathematics' |
|
1415 |
|
AND Department = Code; |
1297 |
1416 |
~~~ |
~~~ |
1298 |
1417 |
|
|
1299 |
1418 |
- `Department.Name = 'Mathematics'` is the selection condition |
- `Department.Name = 'Mathematics'` is the selection condition |
|
... |
... |
SELECT Login FROM PROF, DEPARTMENT WHERE DEPARTMENT.Name = 'Mathematics' AND Dep |
1301 |
1420 |
- Why do we use the fully qualified Name attribute for `Name`? |
- Why do we use the fully qualified Name attribute for `Name`? |
1302 |
1421 |
- We have to list all the tables we want to consult, even if we use fully qualified names. |
- We have to list all the tables we want to consult, even if we use fully qualified names. |
1303 |
1422 |
|
|
1304 |
|
~~~{.sql} |
|
1305 |
|
SELECT Name FROM STUDENT, GRADE WHERE Grade > 3.0 AND STUDENT.Login = GRADE.Login; |
|
|
1423 |
|
~~~{.sqlmysql} |
|
1424 |
|
SELECT Name FROM STUDENT, GRADE |
|
1425 |
|
WHERE Grade > 3.0 |
|
1426 |
|
AND STUDENT.Login = GRADE.Login; |
1306 |
1427 |
~~~ |
~~~ |
1307 |
1428 |
|
|
1308 |
1429 |
- `Grade > 3.0` is the selection condition |
- `Grade > 3.0` is the selection condition |
|
... |
... |
SELECT Name FROM STUDENT, GRADE WHERE Grade > 3.0 AND STUDENT.Login = GRADE.Logi |
1310 |
1431 |
|
|
1311 |
1432 |
We can have two join conditions! |
We can have two join conditions! |
1312 |
1433 |
|
|
1313 |
|
~~~{.sql} |
|
1314 |
|
SELECT PROF.Name FROM PROF, DEPARTMENT, STUDENT WHERE STUDENT.Name = 'Ava Alyx' AND STUDENT.Major = DEPARTMENT.Code AND DEPARTMENT.Head = PROF.Login; |
|
|
1434 |
|
~~~{.sqlmysql} |
|
1435 |
|
SELECT PROF.Name FROM PROF, DEPARTMENT, STUDENT |
|
1436 |
|
WHERE STUDENT.Name = 'Ava Alyx' |
|
1437 |
|
AND STUDENT.Major = DEPARTMENT.Code |
|
1438 |
|
AND DEPARTMENT.Head = PROF.Login; |
1315 |
1439 |
~~~ |
~~~ |
1316 |
1440 |
|
|
1317 |
1441 |
### Aliasing tuples |
### Aliasing tuples |
1318 |
1442 |
|
|
1319 |
|
~~~{.sql} |
|
1320 |
|
SELECT A.Name FROM PROF AS A, DEPARTMENT, STUDENT AS B WHERE B.Name = 'Ava Alyx' AND B.Major = DEPARTMENT.Code AND DEPARTMENT.Head = A.Login; |
|
|
1443 |
|
~~~{.sqlmysql} |
|
1444 |
|
SELECT A.Name FROM PROF AS A, DEPARTMENT, STUDENT AS B |
|
1445 |
|
WHERE B.Name = 'Ava Alyx' |
|
1446 |
|
AND B.Major = DEPARTMENT.Code |
|
1447 |
|
AND DEPARTMENT.Head = A.Login; |
1321 |
1448 |
~~~ |
~~~ |
1322 |
1449 |
|
|
1323 |
|
~~~{.sql} |
|
1324 |
|
SELECT Others.Login FROM GRADE AS Mine, GRADE AS Others WHERE Mine.Login = 'aalyx' and Mine.Grade < Others.Grade; |
|
|
1450 |
|
~~~{.sqlmysql} |
|
1451 |
|
SELECT Others.Login FROM GRADE AS Mine, GRADE AS Others |
|
1452 |
|
WHERE Mine.Login = 'aalyx' |
|
1453 |
|
AND Mine.Grade < Others.Grade; |
1325 |
1454 |
~~~ |
~~~ |
1326 |
1455 |
|
|
1327 |
1456 |
--- |
--- |
1328 |
1457 |
|
|
1329 |
|
~~~{.sql} |
|
|
1458 |
|
~~~{.sqlmysql} |
1330 |
1459 |
SELECT Fellow.Name AS 'Fellow of Ava' |
SELECT Fellow.Name AS 'Fellow of Ava' |
1331 |
1460 |
FROM STUDENT AS Me, STUDENT AS Fellow |
FROM STUDENT AS Me, STUDENT AS Fellow |
1332 |
|
WHERE Me.Name = 'Ava Alyx' AND Fellow.Major = Me.Major AND NOT Fellow.Name = 'Ava Alyx'; |
|
|
1461 |
|
WHERE Me.Name = 'Ava Alyx' |
|
1462 |
|
AND Fellow.Major = Me.Major |
|
1463 |
|
AND NOT Fellow.Name = 'Ava Alyx'; |
1333 |
1464 |
~~~ |
~~~ |
1334 |
1465 |
|
|
1335 |
1466 |
### Nested queries |
### Nested queries |
1336 |
1467 |
|
|
1337 |
|
~~~{.sql} |
|
|
1468 |
|
~~~{.sqlmysql} |
1338 |
1469 |
SELECT Login FROM GRADE WHERE Grade > |
SELECT Login FROM GRADE WHERE Grade > |
1339 |
1470 |
(SELECT AVG(Grade) FROM GRADE); |
(SELECT AVG(Grade) FROM GRADE); |
1340 |
1471 |
~~~ |
~~~ |
|
... |
... |
SELECT Login FROM GRADE WHERE Grade > |
1342 |
1473 |
Outer query, inner query. |
Outer query, inner query. |
1343 |
1474 |
(Average of all non NULL values.) |
(Average of all non NULL values.) |
1344 |
1475 |
|
|
1345 |
|
~~~{.sql} |
|
|
1476 |
|
~~~{.sqlmysql} |
1346 |
1477 |
SELECT Login FROM GRADE WHERE Grade >= ALL (SELECT Grade FROM GRADE WHERE Grade IS NOT NULL); |
SELECT Login FROM GRADE WHERE Grade >= ALL (SELECT Grade FROM GRADE WHERE Grade IS NOT NULL); |
1347 |
1478 |
|
|
1348 |
1479 |
SELECT Login |
SELECT Login |
|
... |
... |
WHERE DEPARTMENT IN ( SELECT Major |
1357 |
1488 |
|
|
1358 |
1489 |
### Select-project-join (4.3.1) |
### Select-project-join (4.3.1) |
1359 |
1490 |
|
|
1360 |
|
~~~{.sql} |
|
|
1491 |
|
~~~{.sqlmysql} |
1361 |
1492 |
SELECT Login FROM PROF, DEPARTMENT WHERE DEPARTMENT.Name = 'Mathematics' AND Department = Code; |
SELECT Login FROM PROF, DEPARTMENT WHERE DEPARTMENT.Name = 'Mathematics' AND Department = Code; |
1362 |
1493 |
~~~ |
~~~ |
1363 |
1494 |
|
|
|
... |
... |
SELECT Login FROM PROF, DEPARTMENT WHERE DEPARTMENT.Name = 'Mathematics' AND Dep |
1365 |
1496 |
- `Department = Code` is the join condition, because it combines two tuples. |
- `Department = Code` is the join condition, because it combines two tuples. |
1366 |
1497 |
- Why do we use the fully qualified Name attribute for `Name`? |
- Why do we use the fully qualified Name attribute for `Name`? |
1367 |
1498 |
|
|
1368 |
|
~~~{.sql} |
|
|
1499 |
|
~~~{.sqlmysql} |
1369 |
1500 |
SELECT Name FROM STUDENT, GRADE WHERE Grade > 3.0 AND STUDENT.Login = GRADE.Login; |
SELECT Name FROM STUDENT, GRADE WHERE Grade > 3.0 AND STUDENT.Login = GRADE.Login; |
1370 |
1501 |
~~~ |
~~~ |
1371 |
1502 |
|
|
|
... |
... |
SELECT Name FROM STUDENT, GRADE WHERE Grade > 3.0 AND STUDENT.Login = GRADE.Logi |
1374 |
1505 |
|
|
1375 |
1506 |
We can have two join conditions! |
We can have two join conditions! |
1376 |
1507 |
|
|
1377 |
|
~~~{.sql} |
|
|
1508 |
|
~~~{.sqlmysql} |
1378 |
1509 |
SELECT PROF.Name FROM PROF, DEPARTMENT, STUDENT WHERE STUDENT.Name = 'Ava Alyx' AND STUDENT.Major = DEPARTMENT.Code AND DEPARTMENT.Head = PROF.Login; |
SELECT PROF.Name FROM PROF, DEPARTMENT, STUDENT WHERE STUDENT.Name = 'Ava Alyx' AND STUDENT.Major = DEPARTMENT.Code AND DEPARTMENT.Head = PROF.Login; |
1379 |
1510 |
~~~ |
~~~ |
1380 |
1511 |
|
|
1381 |
1512 |
### Aliasing Tuples |
### Aliasing Tuples |
1382 |
1513 |
|
|
1383 |
|
~~~{.sql} |
|
|
1514 |
|
~~~{.sqlmysql} |
1384 |
1515 |
SELECT A.Name FROM PROF AS A, DEPARTMENT, STUDENT AS B WHERE B.Name = 'Ava Alyx' AND B.Major = DEPARTMENT.Code AND DEPARTMENT.Head = A.Login; |
SELECT A.Name FROM PROF AS A, DEPARTMENT, STUDENT AS B WHERE B.Name = 'Ava Alyx' AND B.Major = DEPARTMENT.Code AND DEPARTMENT.Head = A.Login; |
1385 |
1516 |
~~~ |
~~~ |
1386 |
1517 |
|
|
1387 |
|
~~~{.sql} |
|
|
1518 |
|
~~~{.sqlmysql} |
1388 |
1519 |
SELECT Others.Login FROM GRADE AS Mine, GRADE as Others WHERE Mine.Login = 'aalyx' and Mine.Grade < Others.Grade; |
SELECT Others.Login FROM GRADE AS Mine, GRADE as Others WHERE Mine.Login = 'aalyx' and Mine.Grade < Others.Grade; |
1389 |
1520 |
~~~ |
~~~ |
1390 |
1521 |
|
|
1391 |
|
~~~{.sql} |
|
|
1522 |
|
~~~{.sqlmysql} |
1392 |
1523 |
SELECT Fellow.Name AS 'Fellow of Ava' |
SELECT Fellow.Name AS 'Fellow of Ava' |
1393 |
1524 |
FROM STUDENT AS Me, STUDENT AS Fellow |
FROM STUDENT AS Me, STUDENT AS Fellow |
1394 |
1525 |
WHERE Me.Name = 'Ava Alyx' AND Fellow.Major = Me.Major AND NOT Fellow.Name = 'Ava Alyx'; |
WHERE Me.Name = 'Ava Alyx' AND Fellow.Major = Me.Major AND NOT Fellow.Name = 'Ava Alyx'; |
|
... |
... |
WHERE Me.Name = 'Ava Alyx' AND Fellow.Major = Me.Major AND NOT Fellow.Name = 'Av |
1396 |
1527 |
|
|
1397 |
1528 |
### Nested Queries |
### Nested Queries |
1398 |
1529 |
|
|
1399 |
|
~~~{.sql} |
|
|
1530 |
|
~~~{.sqlmysql} |
1400 |
1531 |
SELECT Login FROM GRADE WHERE Grade > |
SELECT Login FROM GRADE WHERE Grade > |
1401 |
1532 |
(SELECT AVG(Grade) FROM GRADE); |
(SELECT AVG(Grade) FROM GRADE); |
1402 |
1533 |
~~~ |
~~~ |
|
... |
... |
SELECT Login FROM GRADE WHERE Grade > |
1404 |
1535 |
Outer query, inner query. |
Outer query, inner query. |
1405 |
1536 |
(Average of all non NULL values.) |
(Average of all non NULL values.) |
1406 |
1537 |
|
|
1407 |
|
~~~{.sql} |
|
|
1538 |
|
~~~{.sqlmysql} |
1408 |
1539 |
SELECT Login FROM GRADE WHERE Grade >= ALL (SELECT Grade FROM GRADE WHERE Grade IS NOT NULL); |
SELECT Login FROM GRADE WHERE Grade >= ALL (SELECT Grade FROM GRADE WHERE Grade IS NOT NULL); |
1409 |
1540 |
|
|
1410 |
1541 |
SELECT Login |
SELECT Login |
|
... |
... |
Solution +.# |
1857 |
1988 |
|
|
1858 |
1989 |
## Problems |
## Problems |
1859 |
1990 |
|
|
1860 |
|
### Setting up MySQL |
|
|
1991 |
|
### Setting up MySQL {#sec:gettingstartedwithmysql} |
1861 |
1992 |
|
|
1862 |
1993 |
Problem -.+.#installation |
Problem -.+.#installation |
1863 |
1994 |
|
|
1864 |
1995 |
In this problem, you will install the [MySQL](https://www.mysql.com/) DataBase Managment System and set it up. |
In this problem, you will install the [MySQL](https://www.mysql.com/) DataBase Managment System and set it up. |
1865 |
1996 |
On top of being open source and free, it is one of the most widespread and used DBMS, as well as one of the most well-documented. |
On top of being open source and free, it is one of the most widespread and used DBMS, as well as one of the most well-documented. |
1866 |
|
Linux users will use its community-developed fork, \href{https://mariadb.org/}{MariaDB}, but that won't make a difference in this course (up to [what's mentioned in this section](#differenceMySQLMariaDB)). |
|
|
1997 |
|
Linux users will use its community-developed fork, \href{https://mariadb.org/}{MariaDB}, but that won't make a difference in this course (up to some minor aspects). |
1867 |
1998 |
|
|
1868 |
1999 |
**bogue: cross ref?** |
**bogue: cross ref?** |
1869 |
2000 |
|
|