* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Download CSS122_WINTER09_LECTURE08
Open Database Connectivity wikipedia , lookup
Microsoft SQL Server wikipedia , lookup
Concurrency control wikipedia , lookup
Entity–attribute–value model wikipedia , lookup
Ingres (database) wikipedia , lookup
Relational algebra wikipedia , lookup
Microsoft Jet Database Engine wikipedia , lookup
Clusterpoint wikipedia , lookup
Versant Object Database wikipedia , lookup
Extensible Storage Engine wikipedia , lookup
Using Relational Databases and SQL Lecture 8: Correlated Subqueries and the Data Manipulation Language Steven Emory Department of Computer Science California State University, Los Angeles SELECT Clause Subqueries A SELECT clause subquery must return a single value (not a list or table) Examples: SELECT (SELECT 1) + (SELECT 2); -- 3 SELECT (SELECT COUNT(*) FROM Movies); -- 6 SELECT (SELECT * FROM Movies); -- ERROR!!! SELECT Clause Subqueries SELECT clause subqueries are good for singlevalue calculations, such as percentages Example: -- What percent of accounts are male? SELECT Clause Subqueries Example -- OUTER QUERY SELECT 100*(X)/(Y); -- INNER QUERY X = number of male accounts SELECT COUNT(*) FROM Accounts WHERE Gender = 'M'; -- INNER QUERY Y = number of total accounts SELECT COUNT(*) FROM Accounts; -- SOLUTION SELECT 100*(SELECT COUNT(*) FROM Accounts WHERE Gender = 'M')/(SELECT COUNT(*) FROM Accounts); SELECT Clause Subqueries A SELECT clause subquery is even more useful when the outer query and inner query are correlated (the inner query is dependent on data from the outer query) Correlated Subqueries Previous subqueries have been non-correlated. non-correlated means ‘no dependencies’ which means you can run the inner query separately Correlated subqueries are inner queries that are ‘dependent’ on data from outer queries. correlated means ‘with dependencies’ which means you can’t run the inner query separately the result of the inner query ‘depends on’ data given to it from the outer query Correlated Subqueries Some FROM clause subquery problems can be rewritten using correlated subqueries in the SELECT clause. Let’s try an example: List each movie title along with the number of ratings and the number of genres for that movie. +--------------------------------+---------+--------+ | Title | Ratings | Genres | +--------------------------------+---------+--------+ | Star Trek: Generations | 10 | 4 | | X-Men | 12 | 4 | | X-Men: The Last Stand | 12 | 4 | | Things We Lost in the Fire | 9 | 1 | | The X Files | 12 | 5 | | The X Files: I Want to Believe | 11 | 3 | +--------------------------------+---------+--------+ Correlated Subqueries Non-correlated solution: SELECT Title, X.Ratings, Y.Genres FROM Movies M LEFT JOIN (SELECT MovieID, COUNT(Rating) AS Ratings FROM Ratings GROUP BY MovieID) X ON M.MovieID = X.MovieID LEFT JOIN (SELECT MovieID, COUNT(Genre) AS Genres FROM XRefGenresMovies GROUP BY MovieID) Y ON M.MovieID = Y.MovieID; Take out the inner queries and try running them. Both run because they are independent of the outer query! Correlated Subqueries Correlated setup: -- OUTER QUERY SELECT Title, (X) AS Ratings, (Y) AS Genres FROM Movie M; -- INNER QUERY X SELECT COUNT(Rating) FROM Ratings WHERE MovieID = M.MovieID; -- INNER QUERY Y SELECT COUNT(Genre) FROM XRefGenresMovies WHERE MovieID = M.MovieID; Correlated Subqueries Correlated solution (dependencies are underlined): SELECT Title, (SELECT COUNT(Rating) FROM Ratings WHERE MovieID = M.MovieID) AS Ratings, (SELECT COUNT(Genre) FROM XRefGenresMovies WHERE MovieID = M.MovieID) AS Genres FROM Movies M; Take out the inner queries and try running them. They won’t run because they are dependent on the MovieID attribute from the outer query. Correlated Subqueries So which one do you choose? Subqueries in the FROM clause or correlated subqueries in the SELECT clause? Whichever one runs faster! Our database is too small to do any real testing. Notice the correlated version is shorter and looks nicer. Data Manipulation Language DML for short Contains commands for modifying table data Insertion commands (INSERT INTO) Deletion commands (DELETE) Update commands (UPDATE) Not a query Queries extract data from the database Commands do not extract data from the database Before We Start When modifying the database data, you are going to mess up because nobody is perfect If you mess up there are two ways to restore the original database: Remove and restore the tables Use transactions (use BEGIN and ROLLBACK) I prefer using BEGIN and ROLLBACK Use BEGIN before entering DML commands Use ROLLBACK to undo all changes USE COMMIT to accept all changes Transactions ACID Atomicity Consistency Isolation Durability SQL Keywords BEGIN/START TRANSACTION COMMIT ROLLBACK Inserting Records Two syntaxes: INSERT INTO Insert one record at a time INSERT SELECT Insert one or more records at a time Inserting Records INSERT INTO Syntax -- Form #1: Insert whole record. INSERT INTO tablename VALUES(value1, value2, ..., valuen); -- Form #2: Insert partial record. Non-specified fieldnames are assigned default values. INSERT INTO tablename(field1, field2, ..., fieldn) VALUES(value1, value2, ..., valuen); IGNORE You can use the IGNORE keyword between INSERT and INTO to suppress duplicate error messages. Inserting Records INSERT SELECT Syntax -- Form #1: Insert whole record. INSERT INTO destination_table SELECT field1, field2, ..., fieldn FROM source_tables WHERE conditions; -- Form #2: Insert partial record. Non-specified fieldnames are assigned default values. INSERT INTO destination_table(df1, df2, ..., dfn) SELECT sf1, sf2, ..., sfn FROM source_tables WHERE conditions; INSERT INTO Example Example: Add Kung Fu Panda into the database. INSERT INTO Movies VALUES(7, 'Kung Fu Panda', '2008-06-06', 'G', 92, 'USA', 'English', (SELECT CompanyID FROM Companies WHERE Name = 'Dreamworks Pictures')); INSERT INTO and Subqueries As in the previous example, subqueries in the INSERT command work, but only if the update table and the subquery table are different. This rule only applies to MySQL, other database management systems may behave differently. INSERT SELECT Example Example: Associate all movies that have ‘The X Files’ anywhere in the title with the romance genre. INSERT IGNORE INTO XRefGenresMovies SELECT MovieID, 'Romance' FROM Movies WHERE Title LIKE '%The X Files%'; Deleting Records Deletes one or more rows from a table Deletes all rows without WHERE condition Two syntaxes Single-Table DELETE Syntax Multi-Table DELETE Syntax Single-Table DELETE Syntax Deletes one or more rows from a table Deletes all rows without WHERE condition Syntax: DELETE FROM tablename WHERE conditions; Single-Table DELETE Syntax Examples: Delete all ratings. Delete all ratings by semory. Single-Table DELETE Syntax Solutions: -- Delete all ratings. DELETE FROM Ratings; -- Delete all ratings by semory. DELETE FROM Ratings WHERE AccountID = (SELECT AccountID FROM Accounts WHERE Username = 'semory'); Multi-Table DELETE Syntax Deletes rows from multiple tables You must be very cautious or else you may delete something you didn’t want to delete Syntax: DELETE T1, T2, ..., Tn FROM T1 JOIN T2 JOIN ... JOIN Tn WHERE conditions; Note: If you use table alias in the FROM clause, you must use the alias in the DELETE clause as well (see examples later on). Multi-Table DELETE Syntax Examples: -- Delete all ratings by semory (use multi-table delete syntax instead of using single-table delete syntax with a subquery). -- Delete all directors from the database (from both the People and XRefDirectorsMovies tables). Multi-Table DELETE Syntax Examples: -- Delete all ratings by semory. DELETE Ratings FROM Accounts JOIN Ratings USING(AccountID) WHERE Username = 'semory'; -- Delete all ratings by semory (alternate). DELETE R FROM Accounts A JOIN Ratings R USING(AccountID) WHERE Username = 'semory'; -- Delete all directors from the database. DELETE P, D FROM People P JOIN XRefDirectorsMovies D ON P.PersonID = D.DirectorID; Multi-Table DELETE Syntax There is a big problem in the last example. Multi-table delete can lead to orphaned records if misused (a foreign key with no primary key). DELETE P, D FROM People P JOIN XRefDirectorsMovies D ON P.PersonID = D.DirectorID; Jonathan Frakes is both an actor and a director. If we delete him from the People and XRefDirectorsMovies tables, we orphan him in the XRefActorsMovies and Spouses table! Multi-Table DELETE Syntax Therefore, be careful what you delete! If you delete a record, and that record is referenced somewhere else, you have an orphaned record! No real good solution exists in MySQL. Best solution is to only delete records from the XRefDirectorsMovies table and leave the People table alone since these people may be referenced somewhere else. DELETE FROM XRefDirectorsMovies; Updating Records To update existing records, you may use one of the following syntaxes: Single-table syntax. Multi-table equi-join syntax. Only equi-join is supported. You may not use any other join syntax (JOIN ON, JOIN USING, etc.) Updating Records To update existing records: -- Single-table syntax. UPDATE [IGNORE] tablename SET field1 = value1, field2 = value2, ... WHERE conditions; -- Multi-table equi-join syntax. UPDATE [IGNORE] tablename1, tablename2, ... SET field1 = value1, field2 = value2, ... WHERE conditions; -- Multi-table subquery syntax. UPDATE [IGNORE] tablename SET field1 = subquery1, field2 = subquery2, ... WHERE conditions; Updating Records You may use the IGNORE keyword immediately after UPDATE to ignore errors when an update produces duplicate primary keys. Example: -- ERROR! BEEP! UPDATE Movies SET MovieID = 1 WHERE MovieID = 2; -- Error will be ignored! UPDATE IGNORE Movies SET MovieID = 1 WHERE MovieID = 2; Updating Records Examples: -- The user ojisan has decided to change his username to uncle_steve. Update the database to reflect this change. -- The user colderstone has decided to change his username and password to jackstone and slsev0812z3, respectively. Update the database to reflect this change. -- Dreamworks Pictures went bankrupt and was bought out by Paramount Pictures. Modify all CompanyIDs in the Movies table to reflect this change. Updating Records Examples: -- The user ojisan has decided to change his username to uncle_steve. Update the database to reflect this change. UPDATE Accounts SET Username = 'uncle_steve' WHERE Username = 'ojisan'; Updating Records Examples: -- The user colderstone has decided to change his username and password to jackstone and slsev0812z3, respectively. Update the database to reflect this change. UPDATE Accounts SET Username = 'jackstone', Password = 'slsev0812z3' WHERE Username = 'colderstone'; Updating Records Examples: -- Dreamworks Pictures went bankrupt and was bought out by Paramount Pictures. Modify all CompanyIDs in the Movies table to reflect this change. UPDATE Movies SET CompanyID = (SELECT CompanyID FROM Companies WHERE Name = 'Paramount Pictures') WHERE CompanyID = (SELECT CompanyID FROM Companies WHERE Name = 'Dreamworks Pictures');