* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Download DBA 1: Introduction to Database Administration
Tandem Computers wikipedia , lookup
Microsoft Access wikipedia , lookup
Relational algebra wikipedia , lookup
Concurrency control wikipedia , lookup
Extensible Storage Engine wikipedia , lookup
Functional Database Model wikipedia , lookup
Oracle Database wikipedia , lookup
Entity–attribute–value model wikipedia , lookup
Ingres (database) wikipedia , lookup
Microsoft Jet Database Engine wikipedia , lookup
Clusterpoint wikipedia , lookup
Microsoft SQL Server wikipedia , lookup
Open Database Connectivity wikipedia , lookup
Database model wikipedia , lookup
DBA 1: Introduction to Database Administration Lesso n 1: Int ro duct io n Getting Started Lesso n 2: St o ring Dat a Sto ring Data Data and Data Types What is NULL and NOT NULL, Anyway? Our First Table Lesso n 3: Re lat io nships Be t we e n T able s Other Tables Lesso n 4: INSERT , SELECT , UPDAT E, DELET E DESCRIBING Yo ur Tables Insert SELECT Update Delete Lesso n 5: T ransact io ns Making Sure Yo ur Co mmands Behave ACID Transactio n Iso latio n Levels Using Transactio ns Co mmitting and ro lling back Lesso n 6 : J o ins Co mbining Tables with a Jo in Other Jo ins Left Jo ins Full Outer Jo ins / Unio n Lesso n 7: Aggre gat e s, Funct io ns, and Co ndit io nals Aggregating Data Functio ns Co nditio nals Lesso n 8 : Subque rie s and Vie ws Querying Queries Views Creating a View Restrictio ns o n Views Dro pping a View Lesso n 9 : St o re d Pro ce dure s Using Sto red Pro cedures Mo tivatio ns Creating Sto red Pro cedures Setup Duplicating o ur View Parameters Variables Lesso n 10 : PIVOT and UNPIVOT PIVOTing Data UNPIVOTing Data Lesso n 11: Full T e xt Creating Full-Text Indexes Querying Full-Text Indexes Lesso n 12: Inf o rm at io n Abo ut t he Dat abase INFORMATION_SCHEMA TABLES COLUMNS VIEWS ROUTINES Lesso n 13: Final Pro je ct Final Pro ject Specificatio n Copyright © 1998-2014 O'Reilly Media, Inc. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License. See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information. Introduction Welco me to the O'Reilly DBA Series! In this co urse, yo u will learn the basics to create a well-designed database using basic database co mmands. Yo u will also learn ho w to manipulate the data sto red in these tables and to return meaningful results to help analyze the data sto red. Course Objectives When yo u co mplete this co urse, yo u will be able to : create, read, update, and delete data using basic SQL co mmands. perfo rm relatio nal jo ins and transactio ns o n SQL tables. aggregate data thro ugh functio ns and co nditio nals. perfo rm subqueries and manipulate views. create sto red pro cedures within SQL. summarize data using PIVOT and UNPIVOT. demo nstrate kno wledge o f data indices and info rmatio n schemas. create a full-fledged blo g database. Fro m beginning to end, yo u will learn by do ing pro jects in yo ur o wn Unix and MySQL enviro nments, and then handing them in fo r instructo r feedback. These pro jects, as well as the final pro ject—develo ping a co mplete database and demo nstrating administrative tasks—will add to yo ur po rtfo lio and will co ntribute to certificate co mpletio n. Besides a bro wser and internet co nnectio n, all so ftware is pro vided o nline by the O'Reilly Scho o l o f Techno lo gy. Learning with O'Reilly School of T echnology Courses As with every O'Reilly Scho o l o f Techno lo gy co urse, we'll take a user-active appro ach to learning. This means that yo u (the user) will be active! Yo u'll learn by do ing, building live pro grams, testing them and experimenting with them— hands-o n! To learn a new skill o r techno lo gy, yo u have to experiment. The mo re yo u experiment, the mo re yo u learn. Our system is designed to maximize experimentatio n and help yo u learn to learn a new skill. We'll pro gram as much as po ssible to be sure that the principles sink in and stay with yo u. Each time we discuss a new co ncept, yo u'll put it into co de and see what YOU can do with it. On o ccasio n we'll even give yo u co de that do esn't wo rk, so yo u can see co mmo n mistakes and ho w to reco ver fro m them. Making mistakes is actually ano ther go o d way to learn. Abo ve all, we want to help yo u to learn to learn. We give yo u the to o ls to take co ntro l o f yo ur o wn learning experience. When yo u co mplete an OST co urse, yo u kno w the subject matter, and yo u kno w ho w to expand yo ur kno wledge, so yo u can handle changes like so ftware and o perating system updates. Here are so me tips fo r using O'Reilly Scho o l o f Techno lo gy co urses effectively: T ype t he co de . Resist the temptatio n to cut and paste the example co de we give yo u. Typing the co de actually gives yo u a feel fo r the pro gramming task. Then play aro und with the examples to find o ut what else yo u can make them do , and to check yo ur understanding. It's highly unlikely yo u'll break anything by experimentatio n. If yo u do break so mething, that's an indicatio n to us that we need to impro ve o ur system! T ake yo ur t im e . Learning takes time. Rushing can have negative effects o n yo ur pro gress. Slo w do wn and let yo ur brain abso rb the new info rmatio n tho ro ughly. Taking yo ur time helps to maintain a relaxed, po sitive appro ach. It also gives yo u the chance to try new things and learn mo re than yo u o therwise wo uld if yo u blew thro ugh all o f the co ursewo rk to o quickly. Expe rim e nt . Wander fro m the path o ften and explo re the po ssibilities. We can't anticipate all o f yo ur questio ns and ideas, so it's up to yo u to experiment and create o n yo ur o wn. Yo ur instructo r will help if yo u go co mpletely o ff the rails. Acce pt guidance , but do n't de pe nd o n it . Try to so lve pro blems o n yo ur o wn. Go ing fro m misunderstanding to understanding is the best way to acquire a new skill. Part o f what yo u're learning is pro blem so lving. Of co urse, yo u can always co ntact yo ur instructo r fo r hints when yo u need them. Use all available re so urce s! In real-life pro blem-so lving, yo u aren't bo und by false limitatio ns; in OST co urses, yo u are free to use any reso urces at yo ur dispo sal to so lve pro blems yo u enco unter: the Internet, co urses, yo u are free to use any reso urces at yo ur dispo sal to so lve pro blems yo u enco unter: the Internet, reference bo o ks, and o nline help are all fair game. Have f un! Relax, keep practicing, and do n't be afraid to make mistakes! Yo ur instructo r will keep yo u at it until yo u've mastered the skill. We want yo u to get that satisfied, "I'm so co o l! I did it!" feeling. And yo u'll have so me pro jects to sho w o ff when yo u're do ne. Lesson Format We'll try o ut lo ts o f examples in each lesso n. We'll have yo u write co de, lo o k at co de, and edit existing co de. The co de will be presented in bo xes that will indicate what needs to be do ne to the co de inside. Whenever yo u see white bo xes like the o ne belo w, yo u'll type the co ntents into the edito r windo w to try the example yo urself. The CODE TO TYPE bar o n to p o f the white bo x co ntains directio ns fo r yo u to fo llo w: CODE TO TYPE: White boxes like this contain code for you to try out (type into a file to run). If you have already written some of the code, new code for you to add looks like this. If we want you to remove existing code, the code to remove will look like this. We may also include instructive comments that you don't need to type. We may run pro grams and do so me o ther activities in a terminal sessio n in the o perating system o r o ther co mmandline enviro nment. These will be sho wn like this: INTERACTIVE SESSION: The plain black text that we present in these INTERACTIVE boxes is provided by the system (not for you to type). The commands we want you to type look lik e this. Co de and info rmatio n presented in a gray OBSERVE bo x is fo r yo u to inspect and absorb. This info rmatio n is o ften co lo r-co ded, and fo llo wed by text explaining the co de in detail: OBSERVE: Gray "Observe" boxes like this contain information (usually code specifics) for you to observe. The paragraph(s) that fo llo w may pro vide additio n details o n inf o rm at io n that was highlighted in the Observe bo x. We'll also set especially pertinent info rmatio n apart in "No te" bo xes: Note T ip No tes pro vide info rmatio n that is useful, but no t abso lutely necessary fo r perfo rming the tasks at hand. Tips pro vide info rmatio n that might help make the to o ls easier fo r yo u to use, such as sho rtcut keys. WARNING Warnings pro vide info rmatio n that can help prevent pro gram crashes and data lo ss. T he CodeRunner Screen This co urse is presented in Co deRunner, OST's self-co ntained enviro nment. We'll discuss the details later, but here's a quick o verview o f the vario us areas o f the screen: These video s explain ho w to use Co deRunner: File Management Demo Co de Edito r Demo Co ursewo rk Demo Getting Started In this co urse, yo u will be creating SQL files. SQL files are made up o f SQL statements and have an .sql extensio n. Click the Ne w T e rm inal butto n to co nnect to Unix o r click the Co nne ct t o MySQL butto n to co nnect directly to the MySQL server. In this co urse we'll primarily use the Unix Terminal and no t the MySQL server directly. By do ing so we have so me additio nal co ntro l o ver ho w we co nnect to MySQL. Many o f the pro jects will be turned in as SQL files. Click the Ne w T e rm inal butto n to co nnect to Unix no w. Yo u will see pro mpts fo r the lo gin and passwo rd yo u were given when yo u registered with OST, altho ugh the system may fill o ne o r bo th o f these in fo r yo u. If the system do esn't auto matically lo g yo u in, type yo ur username and passwo rd when pro mpted. (Yo u may need to click inside the Unix Terminal windo w to be able to type. When typing yo ur passwo rd, yo u will no t see any characters reflected back to yo u as yo u type.) Yo u will then be lo gged in to o ne o f the OST servers. Once yo u see the UNIX pro mpt, it's time to co nnect to MySQL! Be sure to replace bo th o ccurrences o f username with yo ur o wn username. Type the fo llo wing at the UNIX pro mpt: cold1:~$ mysql -h sql -p -u username username Yo ur screen will lo o k like this: OBSERVE: cold1:~$ mysql -h sql -p -u username username Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 135535 Server version: 5.1.69-log Source distribution Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> To co nnect to a mysql database, we run the pro gram m ysql. To specify which database server we want to co nnect to , we type -h sql. We want to be pro mpted to pro vide a passwo rd, so we use the -p o ptio n. To specify o ur username, we use the -u username o ptio n. Finally, the database we want to use has the same name as o ur username, so we pro vide it again: username. Befo re we are ready to use MySQL, let's type in a co mmand that tells MySQL to act in a "traditio nal" way. The co mmand will cause MySQL to act mo re like Po stgreSQL, Micro so ft SQL Server, and Oracle. Type the fo llo wing at the MySQL pro mpt: mysql> set sql_mode='traditional'; Query OK, 0 rows affected (0.00 sec) mysql> When yo u are ready to leave mysql and return to the Unix pro mpt, type e xit as sho wn. INTERACTIVE SESSION: mysql> exit Bye cold1:~$ Fo r mo st pro jects, yo u will select SQL fro m the Syntax menu in Co deRunner. If yo u are in the Unix Terminal, click o n the "untitled" tab next to the Terminal tab. No w, click the Ne w File butto n in the menu bar to create a new "untitled" tab. Enter the fo llo wing co de as sho wn: Type the fo llo wing into Co deRunner: set sql_mode='traditional'; select now(); select 'hello world' as Message; To save yo ur file, click the Save butto n . Fo r this example, name the file dba1le sso n1pro je ct 1.sql: Note When naming files and creating tables, please be sure to name them exactly as requested. The .sql extensio n is impo rtant fo r MySQL files, and in a Unix system, case is significant: dba1lesso n1pro ject1.sql and DBA1Lesso n1Pro ject1.sql wo uld be entirely different files, and Artists and artists wo uld be different tables. While file and table names are case sensitive, MySQL keywo rds, such as SET and SELECT , are no t, and can be entered in either upper o r lo wer case. To o pen a file yo u have previo usly saved, click the Lo ad butto n and select the file fro m the Lo ad File windo w, o r do uble-click the file in the File Bro wser. No te that when yo u save a file, the wo rd "untitled" is replaced by the file name in the co de edito r tab. When yo u o pen a file, the file o pens in a new tab. Test it in the Unix Terminal using the fo llo wing co mmand: Type the fo llo wing at the UNIX pro mpt: cold1:~$ mysql -t -h sql -p -u username username < dba1lesson1project1.sql Enter password: +---------------------+ | now() | +---------------------+ | 2013-10-16 15:56:48 | +---------------------+ +-------------+ | Message | +-------------+ | hello world | +-------------+ cold1:~$ OBSERVE: cold1:~$ mysql -t -h sql -p -u username username < dba1lesson1project1.sql The -t o ptio n tells MySQL to o utput yo ur queries in a nice table fo rmat. Be sure to replace username with yo ur specific username, and dba1le sso n1pro je ct 1.sql with yo ur pro ject filename. Yo u've finished this lesso n! When yo u finish a lesso n, co mplete the ho mewo rk o bjectives and quizzes. To get started o n the first o bjective, click Obje ct ive 1 in the curriculum area in the upper left. Fo r this o bjective, yo u'll submit the dba1le sso n1pro je ct 1.sql file we created here. No w yo u're ready to mo ve o n to the next lesso n, where yo u'll dive right in and create so me tables! Copyright © 1998-2014 O'Reilly Media, Inc. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License. See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information. Storing Data Storing Data Befo re we get started, make sure yo u are in the Unix Terminal and then co nnect to MySQL. Click the Ne w T e rm inal butto n and lo g in. Be sure to click in the windo w befo re yo u start typing. When yo u have lo gged in, co nnect to the MySQL server. Remember to replace username with yo ur actual username, and be sure to type yo ur username twice! Type the fo llo wing at the UNIX pro mpt: cold1:~$ mysql -h sql -p -u username username Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 778597 Server version: 5.0.41-community-log MySQL Community Edition (GPL) Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> Do n't fo rget—yo u also need to set the 'TRADITIONAL' mo de. Type the fo llo wing at the MySQL pro mpt: mysql> set sql_mode='traditional'; No w yo u're ready to go ! Databases excel at fo ur o peratio ns: Creating data, Reading data, Updating data, and Deleting data; we refer to these o peratio ns co llectively as CRUD. The mo st po pular databases use Structured Query Language (SQL) to perfo rm tho se o peratio ns. Yo u canno t build a skyscraper witho ut blueprints, and yo u canno t sto re data in a database witho ut defining what type o f info rmatio n yo u wish to sto re, and ho w yo u want to sto re it. The subset o f SQL to create yo ur blueprints is called Data Definition Language (DDL). Data and Data T ypes Befo re yo u can build the walls o f a skyscraper, yo u must decide which material yo u will use to build yo ur walls. Database administrato rs must also cho o se the material with which to co nstruct their database. Let's wo rk with an example. Suppo se yo u've just been hired by a used bo o k sto re. Yo ur jo b is to build a new database system fo r tracking bo o ks, amo ng o ther things. Since we are interested in keeping track o f bo o ks, we need to determine the data that co mprises a bo o k. Mo st bo o ks have a title, an autho r, the date the bo o k was published, a co unt o f the number o f pages, and a price. So me bo o ks co ntain a brief descriptio n o f their co ntent, o thers do no t. Fo r example, Database Nation was written by Simso n Garfinkel in December 20 0 0 and currently co sts $16 .9 5. The descriptio n o f the bo o k reads: "As the 21st century begins, advances in techno lo gy endanger o ur privacy in ways never befo re imagined. This newly revised update o f the po pular hardco ver editio n, 'Database Natio n: The Death o f Privacy in the 21st Century,' is the co mpelling acco unt o f ho w invasive techno lo gies will affect o ur lives in the co ming years. It's a timely, far-reaching, entertaining, and tho ught-pro vo king lo o k at the serio us threats to privacy facing us to day." Here is the co ver o f Database Nation, with so me o f its data items highlighted: Database tables sto re info rmatio n in ro ws and co lumns. The co lumns are the definitio n (o r template) that each ro w must fo llo w. Fo r a table that sto res bo o k info rmatio n, we might have co lumns fo r T it le , Aut ho r, Dat e Publishe d, Num be r o f Page s, Price , and De script io n. Each co lumn o f info rmatio n is o f a different type. Fo r example, the title and autho r are textual. The date published is exactly that: a date. The number o f pages is a no n-negative integer. The co st is a decimal, with two decimal places. The descriptio n, if o ne exists, is also textual. As a database administrato r (DBA), yo ur jo b is to pick the smallest and mo st appro priate data type fo r the info rmatio n we want to sto re. Yo u co uld just sto re everything as a bunch o f wo rds. Fo r example, yo u co uld sto re the Date Published as 0 5 /10 /20 0 7 . If yo u saw this data, wo uld yo u be certain it was May 10 th, 20 0 7, o r co uld it be Octo ber 5th, 20 0 7? If yo u sto re it as a date, there wo uld be no questio n, because the database co uld return the date to yo u in any fo rm yo u like, even "May 10 th, 20 0 7." It co uld also do so me calculatio ns fo r yo u, like tell yo u that "o ne mo nth prio r to the publish date" was "April 10 th, 20 0 7." Data types can be classified into three gro ups: text data types, numeric data types, and date/time data types. Here are so me o f the data types MySQL suppo rts: Gro up Dat a T ype De script io n Sam ple Text CHAR A fixed length o f zero to 255 characters. Useful fo r data like state co des, which are always two characters lo ng. IL Text VARCHAR A variable length o f zero to 6 5535 characters. Useful fo r data who se length varies, but is always within a certain size range. Co mmo n examples are first o r last names. ILLINOIS Text TEXT A variable length o f up to 6 5535 characters. Illino is is a great state. Text MEDIUMTEXT A variable length o f up to 16 777215 characters. This histo ry o f Illino is... Text LONGTEXT A variable length o f up to 429 49 6 729 5 characters. The lo nger histo ry o f Illino is... Numeric INT Integer (who le) numbers. 5 Numeric FLOAT An appro ximate decimal po int value sto red in 4 bytes. 5.15 Numeric DOUBLE An appro ximate decimal po int value sto red in 8 bytes. 7.25 Numeric DECIMAL An exact decimal po int value. The preferred data type fo r sto ring mo netary values such as prices o r salaries. 2.25 Date DATE Year, mo nth and day. 20 0 9 -1231 Date DATETIME Year, mo nth, day and time. 20 0 9 -1231 14:25:0 0 Date TIME Time o nly. 14:25:0 0 Date YEAR Year o nly. Year(4) has a range o f 19 0 1-2155, year(2) has a range o f 20 12 19 70 -20 6 9 . What is NULL and NOT NULL, Anyway? In a database, yo u might have a co lumn that is o ptio nal, such as a seco nd address line fo r yo ur custo mers. Elsewhere yo u might want to sto re so me bit o f info rmatio n, like the list price (a decimal), which is also o ptio nal. Yo u co uld set the list price to be $-9 9 9 9 .9 9 and define that value as the "no list price" value, but there is a better way. NULL is no thing. It is no value. WARNING Be careful with NULL—NULL is no t equal to "" o r 0 . It is not an empty string. It cannot be co mpared to so mething else. Ho wever, even tho ugh is no thing, yo u can tell if so mething IS NULL o r IS NOT NULL. Our First T able In o rder to interact quickly with data in o ur tables, we need to define the primary key co lumns o n o ur table. A primary key is the minimum set o f info rmatio n needed to uniquely identify a ro w in a database table. At first glance, the primary key fo r o ur bo o k table co uld be the title. Dat abase Nat io n is o ne title; ho wever, the bo o k might co me in hardco ver and paperback editio ns, and there might so meday be ano ther bo o k with the same title. If o ur bo o k sto re sto cks bo th editio ns, o r the o ther bo o k with the same title, the title "Database Natio n" alo ne wo n't be eno ugh fo r us to distinguish between the different bo o ks. Thus we wo n't be able to use the title as o ur primary key. Amo ng o ther aspects o f a bo o k that we might sto re in a database, the price, the autho r, the descriptio n, and the catego ry are all po tentially no t unique. Yo u might decide to sho eho rn so me extra info rmatio n to the bo o k's title, perhaps creating two bo o ks: Database Natio n - Hard Co py Database Natio n - Paperback This type o f co mpro mise isn't a go o d idea. The title is Dat abase Nat io n, no t Dat abase Nat io n - Hard Co py. Our manager might step in at this po int, and tell us that everything in the sto re has a unique Pro duct Co de . This pro duct co de sho uld be o ur primary key, since it can be used to uniquely identify a ro w in o ur table. We will use the Pro duct Co de as o ur primary key, add a co lumn called Cat e go ry, and fo rget abo ut the Autho r, the Date Published, and Number o f Pages co lumns fo r no w. Befo re we get started, make sure Co deRunner is in MySQL mo de. Click in the windo w, and type in yo ur passwo rd. Type the fo llo wing at the MySQL pro mpt: mysql> CREATE TABLE Products --> ( --> ProductCode char(20) NOT NULL, --> Title varchar(50) NOT NULL, --> Category varchar(30) NOT NULL, --> Description text, --> Price DECIMAL(9,2) NOT NULL, --> PRIMARY KEY(ProductCode) --> ) ENGINE=INNODB; Query OK, 0 rows affected (0.00 sec) mysql> Let's take a clo ser lo o k: OBSERVE: mysql> CREATE TABLE Products --> ( --> ProductCode char(20) NOT NULL, --> Title varchar(50) NOT NULL, --> Category varchar(30) NOT NULL, --> Description text, --> Price DECIMAL(9,2) NOT NULL, --> PRIMARY KEY(ProductCode) --> ) ENGINE=INNODB; The Pro duct s table is fairly small; it co ntains a Pro duct Co de used to uniquely identify a ro w, the Title o f the item, a Catego ry, an o ptio nal Descriptio n, and the Price. The NOT NULL keywo rds indicate which co lumns are required (canno t be null). We didn't specify "NOT NULL" fo r De script io n, so we do n't require a value in that co lumn. Finally, we specify o ur PRIMARY KEY as Pro duct Co de . Can a primary key be null? Create a little test table to find o ut. Note In this co urse, we use the INNODB engine (ENGINE=INNODB) fo r mo st o f the tables we create. This engine allo ws us to use mo re standard SQL than the no rmal MySQL tables. Believe it o r no t, yo u just created a new table! In the next lesso n, yo u'll create additio nal tables, and see ho w all o f the tables relate to each o ther. See yo u there! Copyright © 1998-2014 O'Reilly Media, Inc. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License. See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information. Relationships Between Tables Other T ables In the last lesso n, we learned ho w to create tables. One table is o kay, but we'll need a few additio nal tables to keep track o f custo mers, invento ry, and o rders. In the last lesso n we decided to sto re the Pro ductCo de, Title, Catego ry, Descriptio n, and Price fo r all o f o ur bo o ks. Being a bo o k sto re, it wo uld be nice to track o ur custo mers and o rders so we kno w which bo o ks are selling well. We co uld add a new co lumn called "Custo mer" and a co lumn called "DatePurchased" to o ur bo o k table, but then we wo uld have to co py the Pro ductCo de, Title, Catego ry, Descriptio n and Price each time a bo o k was so ld! Also , we designed the Pro ducts table to co ntain pro ducts, and a custo mer isn't a pro duct! A better so lutio n is to use a separate table fo r each gro up o f info rmatio n—a table fo r bo o ks, a table fo r custo mers, and a table fo r o rders. This way we do n't have a lo t o f duplicate info rmatio n in o ur tables, wasting space and po tentially causing co nfusio n. MySQL, Po stgreSQL, Oracle, and SQL Server are all relational databases. They efficiently sto re info rmatio n in multiple tables that are linked to gether by relatio nships. The first table we'll create will keep track o f custo mers. The data used to describe a custo mer sho uld include their first and last name, address, and email address. But suppo se yo u had two custo mers with the name "Jo hn Smith," o r a custo mer who shares his email address with his wife? Ho w wo uld yo u keep these individual entries separate? We need a primary key fo r o ur custo mer table, but we really do n't have any unique info rmatio n. Fo rtunately we can have the database create a unique co lumn fo r us. MySQL pro vides an AUT O_INCREMENT that will auto matically po pulate a co lumn with an increasing integer number. The value fo r the first ro w is 1, then the next ro w is 2, and so o n. It do es no t repeat numbers. This type o f key is also kno wn as a surrogate key. We'll use a surro gate key fo r o ur custo mer table, and call it Cust o m e rID. Type the fo llo wing at the MySQL pro mpt: mysql> -> -> -> -> -> -> -> -> -> -> -> -> -> Query mysql> CREATE TABLE Customers ( CustomerID int AUTO_INCREMENT NOT NULL, FirstName varchar(50) NOT NULL, LastName varchar(50) NOT NULL, AddressLine1 varchar(50) NOT NULL, AddressLine2 varchar(50), City varchar(50) NOT NULL, State char(2), PostalCode varchar(10), EmailAddress varchar(100), DateAdded DATETIME NOT NULL, PRIMARY KEY(CustomerID) ) ENGINE=INNODB; OK, 0 rows affected (0.01 sec) Let's discuss so me impo rtant parts o f this co mmand: OBSERVE: mysql> CREATE TABLE Customers -> ( -> CustomerID int AUTO_INCREMENT NOT NULL, -> FirstName varchar(50) NOT NULL, -> LastName varchar(50) NOT NULL, -> AddressLine1 varchar(50) NOT NULL, -> AddressLine2 varchar(50), -> City varchar(50) NOT NULL, -> State char(2), -> PostalCode varchar(10), -> EmailAddress varchar(100), -> DateAdded DATETIME NOT NULL, -> PRIMARY KEY(CustomerID) -> ) ENGINE=INNODB; The f irst line t e lls t he dat abase se rve r t o cre at e a ne w t able nam e d Cust o m e rs. This table co ntains o ur surro gate key co lumn named Cust o m e rID. No tice the use o f the mySQL-specific AUT O_INCREMENT keywo rd. Note Auto -Increment co lumns so metimes have gaps. Fo r instance, a table may have a 1 in the first ro w, then 5 in the next ro w, depending o n whether ro ws are added o r remo ved fro m the table. Next, we defined the name co lumn. First Nam e will be a varchar with a maximum length o f 5 0 characters. This sho uld be a required value fo r all custo mers, so it is defined as NOT NULL. The co lumns fo r LastName and AddressLine1 are defined similarly. Addre ssLine 2 is also a varchar o f maximum length 5 0 characters, but since so me peo ple do n't have a seco nd address line, yo u do n't need to include the NOT NULL keywo rds. Dat e Adde d will sto re the date and time the custo mer is added to the table. Finally, yo u let the database engine kno w that the PRIMARY KEY is the surro gate key, Cust o m e rID. No w that yo u have the Custo mers table in place, let's create so me additio nal tables to help o rganize the bo o ksto re. We'll need to create tables to sto re Inve nt o ry, track Orde rs, and tell us what pro ducts make up an o rder (Orde rLine ). We can represent these tables graphically this way: In the diagram, arro ws po int to the so urce o f the info rmatio n. In o ther wo rds, the Cust o m e rID in Orders has a co rrespo nding Cust o m e rID in Custo mers. Here are the o ther tables we'll create: T able Nam e Co lum ns Invento ry Pro ductCo de, QuantityInSto ck Orders OrderNumber, Custo merID, Invo iceNumber, DatePlaced, OrderStatus Order Line OrderNumber, Pro ductCo de, Quantity, ExtendedAmo unt The Inve nt o ry table will keep track o f the number o f bo o ks in sto ck. No te that we uniquely identify the quantity in sto ck by Pro duct Co de , which relates back to the Pro ducts table. We need to include the Pro duct Co de in bo th tables in o rder to make this link. A Pro ductCo de o f "ABC123" in Pro ducts will co rrespo nd exactly to a Pro ductCo de o f "ABC123" in Invento ry. Type the fo llo wing at the MySQL pro mpt: mysql> CREATE TABLE Inventory ( ProductCode char(10) NOT NULL, QuantityInStock int NOT NULL, PRIMARY KEY(ProductCode) ) ENGINE=INNODB; Query OK, 0 rows affected (0.00 sec) mysql> Next, create a table to ho ld Orde rs. This table will co ntain an auto -increment co lumn to uniquely identify each o rder. Type the fo llo wing at the MySQL pro mpt: mysql> CREATE TABLE Orders ( OrderNumber int AUTO_INCREMENT NOT NULL, CustomerID int NOT NULL, InvoiceNumber varchar(15), DatePlaced DATETIME, OrderStatus char(10), PRIMARY KEY(OrderNumber) ) ENGINE=INNODB; Query OK, 0 rows affected (0.01 sec) mysql> Finally, the Orde rLine table will be used to reco rd the items purchased fo r each unique o rder. Type the fo llo wing at the MySQL pro mpt: mysql> CREATE TABLE OrderLine ( OrderNumber int NOT NULL, ProductCode char(10) NOT NULL, Quantity int NOT NULL, ExtendedAmount DECIMAL(9, 2) NOT NULL, PRIMARY KEY(OrderNumber, ProductCode) ) ENGINE=INNODB; Query OK, 0 rows affected (0.01 sec) mysql> This table has so mething new: OBSERVE: PRIMARY KEY(OrderNumber, ProductCode) The PRIMARY KEY is defined o n two co lumns. A PRIMARY KEY uniquely identifies a ro w in a table. Often the primary key is just o ne co lumn, such as a userid o r UPC co de. It can be multiple co lumns, ho wever. Note A key (primary o r o ther) that spans multiple co lumns is also kno wn as a composite key. In o ur table the Orde rNum be r and Pro duct Co de to gether will uniquely identify a ro w. Believe it o r no t... yo u just made fo ur new tables! In the next lesso n yo u will learn ho w to sto re data in these tables. See yo u there! Copyright © 1998-2014 O'Reilly Media, Inc. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License. See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information. INSERT, SELECT, UPDATE, DELETE DESCRIBING Your T ables In the last lesso n yo u created tables that will sto re data fo r yo ur bo o ksto re. No w it's time to actually sto re so me data! Befo re we get started, let's examine the tables created in the last lesso n. MySQL has a DESCRIBE keywo rd that can be used to do just that. Note Befo re yo u get started, make sure yo u are co nnected to MySQL, and have set the 'traditio nal' mo de. Type the fo llo wing at the MySQL pro mpt: mysql> DESCRIBE Customers; +--------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +--------------+--------------+------+-----+---------+----------------+ | CustomerID | int(11) | NO | PRI | NULL | auto_increment | | FirstName | varchar(50) | NO | | | | | LastName | varchar(50) | NO | | | | | AddressLine1 | varchar(50) | NO | | | | | AddressLine2 | varchar(50) | YES | | NULL | | | City | varchar(50) | NO | | | | | State | char(2) | YES | | NULL | | | PostalCode | varchar(10) | YES | | NULL | | | EmailAddress | varchar(100) | YES | | NULL | | | DateAdded | datetime | NO | | | | +--------------+--------------+------+-----+---------+----------------+ 10 rows in set (0.02 sec) DESCRIBE returns a lo t o f useful info rmatio n: the co lumn names, the data types (and sizes), whether the co lumn can be NULL, any default values, and whether the co lumn is auto _increment. Insert To add data to a table, use the INSERT keywo rd. Type the fo llo wing at the MySQL pro mpt: mysql> INSERT INTO Customers -> (FirstName, LastName, AddressLine1, City, State, PostalCode, DateAdded, EmailAdd ress) -> VALUES ('John', 'Smith', '123 4th Street', 'Chicago', 'IL', '60606', NOW(), 'joh [email protected]'); Query OK, 1 row affected (0.01 sec) Co ngratulatio ns, yo u just added a ro w o f data into yo ur table! Let's lo o k clo ser. OBSERVE: mysql> INSERT INTO Customers ->(FirstName, LastName, AddressLine1, City, State, PostalCode, DateAdded, EmailAddr ess) ->VALUES ('John', 'Smith', '123 4th Street', 'Chicago', 'IL', '60606', NOW(), 'john @hotmail.com'); The syntax fo r INSERT is fairly co mpact. First, yo u specify the target table fo r yo ur data—in this case, Cust o m e rs. Next, yo u list the specific co lumns fo r which yo u will pro vide data. There are co mmas between each co lumn name, and they are enclo sed within pare nt he se s (). Note Yo u do n't have to pro vide data fo r all co lumns—o nly the required (no n-null) co lumns. Next, yo u specify the VALUES fo r each co lumn. Values that will be sto red in text co lumns must have single quo tatio n marks (') aro und them. The DateAdded co lumn in the Custo mers table must be the date, right now. Fo rtunately, mySQL pro vides a NOW() functio n that returns the date and time in the pro per fo rmat fo r use in o ur table. Note It's o kay to change the o rder o f yo ur co lumns—see ho w DateAdded is befo re EmailAddress? Just remember to pro vide yo ur VALUES in the same o rder yo u specified the co lum ns. No w let's insert ano ther reco rd. Type the fo llo wing at the MySQL pro mpt: mysql> INSERT INTO Customers -> (FirstName, LastName, DateAdded, EmailAddress) -> VALUES ('Jane', 'Adams', NOW(), '[email protected]'); ERROR 1364 (HY000): Field 'AddressLine1' doesn't have a default value mysql> While this erro r message may seem strange, everything is wo rking perfectly. When we created the table, we defined the co lumn "AddressLine1" to be NOT NULL. We didn't pro vide a value fo r AddressLine1 in o ur insert statement, the database set it to NULL by default, resulting in this erro r. WARNING If yo u see so mething like Que ry OK, 1 ro w af f e ct e d, 2 warnings (0 .0 0 se c), yo u'll need to go back to the start o f the lesso n and make sure yo u typed the SET sql_m o de ='T RADIT IONAL'; co mmand. Yo u sho uld also remo ve everything fro m Custo mers and start again—to do this, type DELET E FROM Cust o m e rs; at the MySQL pro mpt. Fix yo ur INSERT statement by pro viding the AddressLine1 and City: Type the fo llo wing at the MySQL pro mpt: mysql> INSERT INTO Customers -> (FirstName, LastName, DateAdded, EmailAddress, AddressLine1, City) -> VALUES ('Jane', 'Adams', NOW(), '[email protected]', '300 N. Michigan', 'Chicago' ); Query OK, 1 row affected (0.01 sec) mysql> Add mo re custo mers—try adding o ne with an AddressLine2. SELECT INSERTing data into tables is fine, but chances are yo u want to retrieve info rmatio n as well. In SQL, the keywo rd to get info rmatio n o ut o f a table is SELECT . Type the fo llo wing at the MySQL pro mpt: mysql> SELECT * FROM Customers; +------------+-----------+----------+-----------------+--------------+---------+------+------------+------------------+---------------------+ | CustomerID | FirstName | LastName | AddressLine1 | AddressLine2 | City | State | PostalCode | EmailAddress | DateAdded | +------------+-----------+----------+-----------------+--------------+---------+------+------------+------------------+---------------------+ | 21 | John | Smith | 123 4th Street | NULL | Chicago | IL | 60606 | [email protected] | 2007-09-19 20:36:38 | | 31 | Jane | Adams | 300 N. Michigan | NULL | Chicago | NULL | NULL | [email protected] | 2007-09-19 20:52:36 | +------------+-----------+----------+-----------------+--------------+---------+------+------------+------------------+---------------------+ 2 rows in set (0.00 sec) mysql> Note The Custo merID values yo u see pro bably wo n't match yo ur o wn Custo merIDs, because the co lumn is an auto increment co lumn. Yo ur o utput may no t lo o k to o nice—in fact it might be pretty ugly! That's because MySQL may have to wrap the ro ws to fit yo ur screen. As yo u learn mo re abo ut MySQL, yo u'll disco ver o ther ways to present the info rmatio n. Fo r example, try SELECT * FROM Cust o m e rs\G. We wo n't get into this in detail here, but fo r an idea o f what's available, see the MySQL develo per do cumentatio n. In a SELECT statement (as in many co mputer co mmands), the asterisk (*) means "all co lumns." Thus the SQL statement yo u entered co uld be translated to English as "retrieve data fro m all co lumns, fro m the table called Custo mers." Of co urse, the list returned fro m this SELECT statement is pretty lo ng, so let's o mit the address info rmatio n fo r no w. Type the fo llo wing at the MySQL pro mpt: mysql> SELECT CustomerID, FirstName, LastName, EmailAddress FROM Customers; +------------+-----------+----------+------------------+ | CustomerID | FirstName | LastName | EmailAddress | +------------+-----------+----------+------------------+ | 21 | John | Smith | [email protected] | | 31 | Jane | Adams | [email protected] | +------------+-----------+----------+------------------+ 2 rows in set (0.00 sec) mysql> OBSERVE: mysql> SELECT CustomerID, FirstName, LastName, EmailAddress FROM Customers; This time, MySQL o nly retrieves the co lumns yo u specified (Cust o m e rID, First Nam e , Last Nam e , and Em ailAddre ss). What if yo u o nly want to retrieve custo mers fro m Illino is? The SELECT statement can include a WHERE clause that enables yo u to filter yo ur ro ws. Type the fo llo wing at the MySQL pro mpt: mysql> SELECT CustomerID, FirstName, LastName, EmailAddress, State FROM Customers -> WHERE State='IL'; +------------+-----------+----------+------------------+-------+ | CustomerID | FirstName | LastName | EmailAddress | State | +------------+-----------+----------+------------------+-------+ | 21 | John | Smith | [email protected] | IL | +------------+-----------+----------+------------------+-------+ 1 row in set (0.01 sec) mysql> OBSERVE: mysql> SELECT CustomerID, FirstName, LastName, EmailAddress, State FROM Customers -> WHERE State='IL'; The results o nly include ro ws WHERE the St at e is e qual t o 'IL.' This time Ms. Adams isn't included because we didn't specify a state fo r her. We kno w Chicago is in Illino is, but SQL do esn't! What if yo u o nly want to see yo ur custo mers fro m Illino is who have a gmail address? Remember that email addresses at gmail end with gmail.co m. Type the fo llo wing at the MySQL pro mpt: mysql> SELECT CustomerID, FirstName, LastName, EmailAddress, State FROM Customers -> WHERE State='IL' AND EmailAddress LIKE '%gmail.com'; Empty set (0.00 sec) mysql> We do n't have any custo mers in Illino is with gmail acco unts, so no ro ws were returned. This query sho ws so mething new. OBSERVE: mysql> SELECT CustomerID, FirstName, LastName, EmailAddress, State FROM Customers WHERE State='IL' AND EmailAddress LIKE '%gmail.com'; AND is a co njunctio n that co nnects the two queries, to return o nly custo mers in Illino is AND with email addresses at gmail. Note Yo u can also use OR in the WHERE clause. Other co mpariso ns yo u can do include IS NULL, IS NOT NULL, != (no t equals), and < o r >. LIKE do esn't do an exact match o n a co lumn. The special character % means "anything" to SQL, so Em ailAddre ss LIKE '% gm ail.co m ' co uld be translated to English as "EmailAddress that ends with gmail.co m." Update No w yo u have data in yo ur tables, but at so me po int this data might change. Suppo se, fo r example, that yo ur custo mer Jo hn Smith tells yo u that his email address has changed. It used to be 'jo hn@ho tmail.co m,' but no w it's 'jo [email protected] m.' Let's UPDAT E his ro w in the Custo mers table. In the fo llo wing example, be sure to change the Custo merID fro m id to whatever Custo merID yo ur individual Jo hn Smith was given. Type the fo llo wing at the MySQL pro mpt: mysql> UPDATE Customers -> SET EmailAddress='[email protected]' -> WHERE CustomerID=id; Query OK, 1 row affected (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> OBSERVE: mysql> UPDATE Customers -> SET EmailAddress='[email protected]' -> WHERE CustomerID=id; UPDATE statements have two impo rtant parts: the co lum n updat e s, and the WHERE clause. The co lum n updat e s specify the new values fo r the given co lumns. The WHERE clause tells the database which ro ws in the database yo u want to update. Let's check to make sure the data was updated. Type the fo llo wing at the MySQL pro mpt: mysql> SELECT CustomerID, FirstName, LastName, EmailAddress FROM Customers; +------------+-----------+----------+------------------+ | CustomerID | FirstName | LastName | EmailAddress | +------------+-----------+----------+------------------+ | 21 | John | Smith | [email protected] | | 31 | Jane | Adams | [email protected] | +------------+-----------+----------+------------------+ 2 rows in set (0.00 sec) mysql> Yes, it has been updated. The WHERE clause is no t required, but if yo u do n't pro vide o ne, every ro w in the database will be updated. If yo u want to update o nly o ne ro w, yo u'll need to specify eno ugh co nditio ns in yo ur WHERE clause to limit yo ur change to that o ne ro w. T ip If yo u're no t sure ho w to limit yo ur UPDATE statement co rrectly, write it as a SELECT statement first. If yo ur SELECT statement returns the intended ro ws, chances are yo ur UPDATE statement will o nly change the intended ro ws as well. Yo u can change multiple co lumns as well. Befo re we do , let's write a SELECT statement to make sure o ur WHERE clause is co rrect. Once again, be sure to change the Custo merID fro m id to whatever Custo merID yo ur individual Jo hn Smith was given. Type the fo llo wing at the MySQL pro mpt: mysql> SELECT * -> FROM Customers -> WHERE CustomerID=21; +------------+-----------+----------+----------------+--------------+---------+-------+ ------------+----------------+---------------------+ | CustomerID | FirstName | LastName | AddressLine1 | AddressLine2 | City | State | PostalCode | EmailAddress | DateAdded | +------------+-----------+----------+----------------+--------------+---------+-------+ ------------+----------------+---------------------+ | 21 | John | Smith | 123 4th Street | NULL | Chicago | IL | 60606 | [email protected] | 2007-09-19 20:36:38 | +------------+-----------+----------+----------------+--------------+---------+-------+ ------------+----------------+---------------------+ 1 row in set (0.00 sec) mysql> One ro w was returned, with the co rrect custo mer. No w that we're co nfident that we've written the co rrect WHERE clause, let's rewrite the SELECT statement as an UPDATE statement. Type the fo llo wing at the MySQL pro mpt: mysql> UPDATE Customers -> SET EmailAddress='[email protected]', City='Evanston' -> WHERE CustomerID=id; Query OK, 0 rows affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> Yo ur results sho w that o ne ro w was matched, and o ne ro w was changed. If yo u need additio nal co nfirmatio n that the change to o k place, write ano ther SELECT query to check fo r yo urself! Delete No w that yo u have data in yo ur tables and have altered that data, ho w do yo u get rid o f it? Perhaps yo ur custo mer Ms. Adams wants to be remo ved fro m yo ur system. o f 31. Do uble-check her Custo merID with SELECT and replace id in the co mmand with her Custo merID fro m yo ur system. Type the fo llo wing at the MySQL pro mpt: mysql> DELETE FROM Customers -> WHERE CustomerID=id; Query OK, 1 row affected (0.00 sec) mysql> Is the data really go ne? Let's find o ut. Type the fo llo wing at the MySQL pro mpt: mysql> SELECT CustomerID, FirstName, LastName, EmailAddress FROM Customers; +------------+-----------+----------+---------------------+ | CustomerID | FirstName | LastName | EmailAddress | +------------+-----------+----------+---------------------+ | 21 | John | Smith | [email protected] | +------------+-----------+----------+---------------------+ 1 row in set (0.00 sec) mysql> Yep, it's go ne! Take a mo ment to reflect o n the wo rk yo u've just do ne. Yo u added data to yo ur tables, retrieved it, filtered it, updated so me ro ws, and deleted so me o ld reco rds. In the next lab yo u'll learn ho w to keep yo ur data secure and co nsistent thro ugh the use o f transactio ns. See yo u there! Copyright © 1998-2014 O'Reilly Media, Inc. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License. See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information. Transactions Making Sure Your Commands Behave Welco me back! In the last lesso n yo u learned ho w to sto re and retrieve data fro m yo ur database. Yo u also learned to create tables in yo ur database to track custo mers, invento ry, and sales. In this lesso n we'll discuss the steps yo u can take to make sure the data in yo ur database is always co rrect and up-to -date, even if many peo ple are wo rking with the data at the same time. Fo r this lesso n, yo u'll need to have two Unix terminals o pen at the same time. The two sessio ns will be o pen in different tabs. To tell them apart, use the po sitio n o f the tabs, and the tabs' names ("Terminal1" and "Terminal2," o r similar). Lo g into MySQL and be sure to set the 'traditio nal' mo de in each Unix terminal! When yo u switch to a new terminal yo u will need to click in it befo re yo u can type in it. Let's go back to o ur bo o ksto re. When a bo o k is so ld, several things need to happen: 1. Check pro duct invento ry to make sure the item is in sto ck. 2. Create an o rder. 3. Add the pro duct to the o rder item table. 4. Update invento ry to reflect the new quantity in sto ck. 5. Check the invento ry level again so the sales staff is alerted when sto ck gets lo w. But what happens if two peo ple try to purchase the same bo o k at the same time? Who gets the bo o k? What happens if yo u add invento ry to the database when so meo ne purchases a bo o k? In the database wo rld, transactions are used to gro up related co mmands so all co mmands execute o r all co mmands do no t execute. There is no in-between. ACID Databases must maintain fo ur pro perties: At o m icit y, Co nsist e ncy, Iso lat io n, and Durabilit y. To help yo u remember this, use the acro nym ACID. At o m icit y: Transactio ns canno t be divided o r split. Transactio ns either succeed o r fail as a single unit. Co nsist e ncy: Databases o nly sto re data that is co nsistent with the rules defined fo r sto ring data. Fo r instance, if an invento ry table isn't allo wed to have negative quantities, then no ro ws will be allo wed to have negative quantities. Iso lat io n: Transactio ns are independent o f the o utside wo rld. No o utside change can cause an unexpected change within o ur transactio n. When making a sale, no o ther sales can change the quantity in invento ry until this sale has been co mpleted. Durabilit y: Once a database transactio n co mmits, the data is secure in the database. All databases handle Ato micity, Co nsistency, and Durability internally and auto matically. The Iso latio n pro perty depends o n the user—it's usually set to a secure level by default, but depending o n yo ur requirements, yo u can raise o r lo wer it. Note MySQL is a unique database because it do esn't always suppo rt ACID pro perties. Depending o n the versio n o f MySQL being used and the way yo ur database is set up, transactio ns may no t secure yo ur data. To ensure MySQL will secure yo ur data, always use the Inno DB engine. T ransaction Isolation Levels There are fo ur primary transactio n iso latio n levels suppo rted by databases. The first is called read uncommitted. It is the fastest, but least safe level. Transactio ns run with this iso latio n level are no t guaranteed to o ccur independently o f o ther transactio ns. This means that o ne sale transactio n is allo wed to "dirty read" the results o f o ther inco mplete sale transactio ns. (A "dirty read" is when the database gives yo u data that has no t yet been co mmitted to disk.) This iso latio n level is o nly used in certain circumstances where yo u do n't necessarily care if the data is inco rrect. The next transactio n level, called read committed, is slightly safer than read unco mmitted. Dirty reads are no t po ssible under this iso latio n level. If yo u run a query at the beginning o f yo ur transactio n, and run the same query at the end o f the transactio n, the results wo n't be the same if ano ther transactio n begins and co mmits in the middle o f yo ur transactio n. Repeatable read is usually the default transactio n iso latio n level. In this iso latio n level, yo u canno t get dirty reads, and no o ther transactio ns can change ro ws during yo ur transactio n. The highest level o f safety, and the slo west transactio n level, is serializable. Under this iso latio n level, each 'read' and 'write' to the database o ccurs in sequence. This iso latio n level can cause perfo rmance issues, since yo ur transactio n might have to wait fo r so meo ne else's transactio n to co mplete. Using T ransactions Befo re yo u query the database, yo u sho uld specify yo ur transactio n iso latio n level. In MySQL this is do ne via the SET co mmand. Be sure yo u are in the first o f yo ur two Unix terminals befo re executing these first co mmands. Type the fo llo wing at the MySQL pro mpt in the first Unix terminal: mysql> SET transaction isolation level read committed; Query OK, 0 rows affected (0.00 sec) mysql> This co mmand do esn't return any ro ws. Mo st database servers allo w yo u to pro cess many SQL statements to gether as a single batch. In MySQL yo u begin a batch with the ST ART T RANSACT ION statement, and end it with COMMIT , o r undo it with ROLLBACK. As always, yo u must end each individual SQL statement with a semico lo n (;). Let's create a simple transactio n. Type the fo llo wing at the MySQL pro mpt in first Unix terminal: mysql> START TRANSACTION; Query OK, 0 rows affected (0.00 sec) mysql> SELECT LastName FROM Customers; +----------+ | LastName | +----------+ | Smith | +----------+ 1 row in set (0.01 sec) mysql> COMMIT; Query OK, 0 rows affected (0.01 sec) mysql> Note It's o kay if the results returned fro m yo ur query are different fro m this example. OBSERVE: mysql> START TRANSACTION; mysql> SELECT LastName FROM Customers; mysql> COMMIT; First, yo u ST ART T RANSACT ION. In this batch yo u are o nly executing o ne statement, to return the co unt fro m the Cust o m e rs table. Ho wever, yo u co uld do additio nal wo rk in yo ur batch by adding mo re SQL statements. Finally, yo u end yo ur batch with COMMIT ;. Of co urse, this example o nly selected data fro m the database—it didn't update o r add data. What happens when yo u use a transactio n with an INSERT statement? To find o ut, yo u'll use bo th Unix terminals. Type the fo llo wing at the MySQL pro mpt in the first Unix terminal: mysql> START TRANSACTION; Query OK, 0 rows affected (0.00 sec) mysql> INSERT INTO Customers -> (FirstName, LastName, AddressLine1, City, State, PostalCode, DateAdded, EmailAdd ress) -> VALUES ('John', 'Doe', '123 4th Street', 'Chicago', 'IL', '60606', NOW(), 'johnd [email protected]'); Query OK, 1 row affected (0.00 sec) mysql> Next, o pen a seco nd Unix terminal sessio n, start mysql, and set sql_mo de='traditio nal'. Type the fo llo wing at the MySQL pro mpt in the seco nd Unix terminal: mysql> SELECT FirstName, LastName FROM Customers; +-----------+----------+ | FirstName | LastName | +-----------+----------+ | John | Smith | +-----------+----------+ 1 row in set (0.00 sec) mysql> Yo ur table may have mo re ro ws than the table sho wn abo ve, but yo u sho uld see that J o hn Do e is no t there. If yo ur transactio n iso latio n level was set co rrectly, yo u won't see any ro ws fo r Jo hn Do e. This is the co rrect result, since we set the re ad co m m it t e d iso latio n level befo re we started the batch. Note If yo u do see Jo hn Do e, yo u pro bably missed the step where yo u entered SET t ransact io n iso lat io n le ve l re ad co m m it t e d; o n the first terminal. Switch back to the first terminal, delete Jo hn Do e, and try again fro m the beginning. No w switch back to the first Unix terminal, where yo u typed in the INSERT statement. Type the fo llo wing at the MySQL pro mpt in the first Unix terminal: mysql> COMMIT; Query OK, 0 rows affected (0.00 sec) mysql> Switch back to the seco nd Unix terminal, where yo u typed in the SELECT statement and run it again (yo u can use the up arro w o n yo ur keybo ard to repeat the co mmand). Type the fo llo wing at the MySQL pro mpt in the seco nd Unix terminal: mysql> SELECT FirstName, LastName FROM Customers; +-----------+----------+ | FirstName | LastName | +-----------+----------+ | John | Smith | | John | Doe | +-----------+----------+ 2 rows in set (0.00 sec) mysql> There is o ne o ther way to end yo ur batch—yo u can undo yo ur changes with the ROLLBACK statement. Make sure yo u are in the first Unix terminal. Type the fo llo wing at the MySQL pro mpt in the first Unix terminal: mysql> START TRANSACTION; Query OK, 0 rows affected (0.00 sec) mysql> INSERT INTO Customers -> (FirstName, LastName, AddressLine1, City, State, PostalCode, DateAdded, EmailAdd ress) -> VALUES ('Becky', 'Stein', '123 4th Street', 'Chicago', 'IL', '60606', NOW(), 'bs [email protected]'); Query OK, 1 row affected (0.01 sec) mysql> ROLLBACK; Query OK, 0 rows affected (0.00 sec) mysql> No w, switch to the seco nd Unix terminal and repeat the SELECT: Type the fo llo wing at the MySQL pro mpt in the seco nd Unix terminal: mysql> SELECT FirstName, LastName FROM Customers; +-----------+----------+ | FirstName | LastName | +-----------+----------+ | John | Smith | | John | Doe | +-----------+----------+ 2 rows in set (0.00 sec) mysql> Yo ur o utput may be different fro m the abo ve, but since yo u rolled back the transactio n, yo u do n't see any ro ws fo r Becky Stein. Committing and rolling back Yo u might be asking, "so when do I use COMMIT and ROLLBACK?" Transactio ns are usually used in applicatio ns o r in sto red pro cedures. Yo ur applicatio n will begin a transactio n, then execute a query. If that query was successful, the applicatio n executes the next query. If any query fails, the transactio n is ro lled back. If all queries succeed, the transactio n is co mmitted. Using transactio ns fo r this means yo ur applicatio n do esn't have to try to undo any database wo rk if there is a pro blem. The database do es the hard wo rk fo r yo u! Yo u've learned a very po werful way to make sure yo ur data stays secure. In the next lesso n yo u'll learn ho w to co mbine data fro m all o f yo ur tables in po werful and meaningful ways. Se e yo u t he n! Copyright © 1998-2014 O'Reilly Media, Inc. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License. See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information. Joins Combining T ables with a Join In this lesso n, yo u'll learn ho w to co mbine data fro m many tables into a single query. Wo uldn't it be nice to be able to write a query that wo uld allo w yo u to see the current invento ry o f the bo o k sto re? Until no w the o nly way yo u had to find this info rmatio n was by writing two queries: o ne to list the pro ducts in the sto re, and ano ther to list the quantities in the sto re. Befo re we begin this lesso n, let's clear the pro ducts and invento ry table and start fresh. We haven't "o fficially" added any reco rds to these tables, but if yo u've added any, yo u can delete them using the DELET E keywo rd yo u learned abo ut earlier. Type the fo llo wing at the MySQL pro mpt: mysql> DELETE FROM Inventory; Query OK, 15 rows affected (0.07 sec) mysql> DELETE FROM Products; Query OK, 15 rows affected (0.00 sec) No w that o ur tables are empty, let's create so me new data. O'Reilly has a very nice bo o k catalo g, so let's bo rro w a few descriptio ns fro m that. We'll do wnlo ad an SQL file to save us so me time. This text file co ntains many INSERT statements that we'll submit to the database server, instead o f typing each and every INSERT co mmand o urselves. First, get back to the Unix pro mpt. Type the fo llo wing at the MySQL pro mpt: mysql> exit; Bye cold1:~$ Next, we'll grab the file fro m O'Reilly's servers using the curl co mmand. Type the fo llo wing at the Unix pro mpt: cold1:~$ curl -L https://courses.oreillyschool.com/dba1/downloads/products.sql > produc ts.sql % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 9520 100 9520 0 0 53816 0 --:--:-- --:--:-- --:--:-- 178k cold1:~$ Once that file has do wnlo aded, we'll use the m ysql co mmand to impo rt the pro ducts (replace username with yo ur username). If the data is impo rted successfully, yo u'll see no results. Type the fo llo wing at the Unix pro mpt: cold1:~$ mysql -h sql -p -u username username < products.sql Enter password: cold1:~$ Next, insert the data fo r invento ries. Lo g back into MySQL, and be sure to set yo ur sql_m o de ! Type the fo llo wing at the MySQL pro mpt: mysql> INSERT INTO Inventory values ('artofsql', 52); Query OK, 1 row affected (0.01 sec) mysql> INSERT INTO Inventory values ('databaseid', 0); Query OK, 1 row affected (0.00 sec) mysql> INSERT INTO Inventory values ('mysqlspp', 5); Query OK, 1 row affected (0.00 sec) mysql> INSERT INTO Inventory values ('sqlhks', 32); Query OK, 1 row affected (0.01 sec) mysql> INSERT INTO Inventory values ('sqltuning', 105); Query OK, 1 row affected (0.01 sec) mysql> To co mbine two tables in o ne query, yo u use a J OIN. A jo in between the Pro ducts table and Invento ry table will match every ro w in Pro ducts with every ro w in Invento ry. Let's try it o ut! INTERACTIVE SESSION: mysql> SELECT * FROM Products JOIN Inventory; +-------------+------------------------------------+-----------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------+-------------+-----------------+ | ProductCode | Title | Category | Description | Price | productcode | QuantityInSt ock | +-------------+------------------------------------+-----------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------+-------------+-----------------+ | databaseid | Database in Depth | Database Theory |This book sheds l ight on the principles behind the relational model, which is fundamental to all databas e-backed applications--and, consequently, most of the work that goes on in the computin g world today. Database in Depth: The Relational Model for Practitioners goes beyond th e hype and gets to the heart of how relational databases actually work. Ideal for exper ienced database developers and designers, this concise guide gives you a clear view of the technology--a view that's not influenced by any vendor or product. Featuring an ext ensive set of exercises, it will help you: * understand why and how the relational mode l is still directly relevant to modern database technology (and will remain so for the foreseeable future) * see why and how the SQL standard is seriously deficient * use the best current theoretical knowledge in the design of their databases and database appli cations * make informed decisions in their daily database professional activities Datab ase in Depth will appeal not only to database developers and designers, but also to a d iverse field of professionals and academics, including database administrators (DBAs), information modelers, database consultants, and more. Virtually everyone who deals with relational databases should have at least a passing understanding of the fundamentals of working with relational models. Author C.J. Date has been involved with the relation al model from its earliest days. An exceptionally clear-thinking writer, Date lays out principle and theory in a manner that is easily understood. Few others can speak as aut horitatively the topic of relational databases as Date can. | 29.95 | artofsql | 52 | | sqlhks | SQL Hacks | SQL |Whether you're ru nning Access, MySQL, SQL Server, Oracle, or PostgreSQL, this book will help you push th e limits of traditional SQL to squeeze data effectively from your database. The book of fers 100 hacks -- unique tips and tools -- that bring you the knowledge of experts who apply what they know in the real world to help you take full advantage of the expressiv e power of SQL. You'll find practical techniques to address complex data manipulation p roblems. Learn how to: * Wrangle data in the most efficient way possible * Aggregate an d organize your data for meaningful and accurate reporting * Make the most of subquerie s, joins, and unions * Stay on top of the performance of your queries and the server th at runs them * Avoid common SQL security pitfalls, including the dreaded SQL injection attack Let SQL Hacks serve as your toolbox for digging up and manipulating data. If you love to tinker and optimize, SQL is the perfect technology and SQL Hacks is the must-h ave book for you. | 29.99 | artofsql | 52 | | artofsql | The Art of SQL | Database Theory |For all the buzz about trendy IT techniques, data processing is still at the core of our systems, especi ally now that enterprises all over the world are confronted with exploding volumes of d ata. Database performance has become a major headache, and most IT departments believe that developers should provide simple SQL code to solve immediate problems and let DBAs tune any "bad SQL" later. In The Art of SQL, author and SQL expert Stephane Faroult ar gues that this "safe approach" only leads to disaster. His insightful book, named after Art of War by Sun Tzu, contends that writing quick inefficient code is sweeping the di rt under the rug. SQL code may run for 5 to 10 years, surviving several major releases of the database management system and on several generations of hardware. The code must be fast and sound from the start, and that requires a firm understanding of SQL and re lational theory. The Art of SQL offers best practices that teach experienced SQL users to focus on strategy rather than specifics. Faroult's approach takes a page from Sun Tz u's classic treatise by viewing database design as a military campaign. You need knowle dge, skills, and talent. Talent can't be taught, but every strategist from Sun Tzu to m odern-day generals believed that it can be nurtured through the experience of others. T hey passed on their experience acquired in the field through basic principles that serv ed as guiding stars amid the sound and fury of battle. This is what Faroult does with S QL. Like a successful battle plan, good architectural choices are based on contingencie s. What if the volume of this or that table increases unexpectedly? What if, following a merger, the number of users doubles? What if you want to keep several years of data o nline? Faroult's way of looking at SQL performance may be unconventional and unique, bu t he's deadly serious about writing good SQL and using SQL well. The Art of SQL is not a cookbook, listing problems and giving recipes. The aim is to get you-and your manager -to raise good questions. | 44.99 | artofsql | 52 | | sqltuning | SQL Tuning | Database Theory |A poorly performi ng database application not only costs users time, but also has an impact on other appl ications running on the same computer or the same network. SQL Tuning provides an essen tial next step for SQL developers and database administrators who want to extend their SQL tuning expertise and get the most from their database applications. There are two b asic issues to focus on when tuning SQL: how to find and interpret the execution plan o f an SQL statement and how to change SQL to get a specific alternate execution plan. SQ L Tuning provides answers to these questions and addresses a third issue that's even mo re important: how to find the optimal execution plan for the query to use. Author Dan T ow outlines a timesaving method he's developed for finding the optimum execution plan-rapidly and systematically--regardless of the complexity of the SQL or the database pla tform being used. You'll learn how to understand and control SQL execution plans and ho w to diagram SQL queries to deduce the best execution plan for a query. Key chapters in the book include exercises to reinforce the concepts you've learned. SQL Tuning conclu des by addressing special concerns and unique solutions to "unsolvable problems." Wheth er you are a programmer who develops SQL-based applications or a database administrator or other who troubleshoots poorly tuned applications, SQL Tuning will arm you with a r eliable and deterministic method for tuning your SQL queries to gain optimal performanc e. | 39.95 | artofsql | 52 | | mysqlspp | MySQL Stored Procedure Programming | MySQL |The implementatio n of stored procedures in MySQL 5.0 a huge milestone -- one that is expected to lead to widespread enterprise adoption of the already extremely popular MySQL database. If you are serious about building the web-based database applications of the future, you need to get up to speed quickly on how stored procedures work -- and how to build them the right way. This book, destined to be the bible of stored procedure development, is a re source that no real MySQL programmer can afford to do without. In the decade since MySQ L burst on the scene, it has become the dominant open source database, with capabilitie s and performance rivaling those of commercial RDBMS offerings like Oracle and SQL Serv er. Along with Linux and PHP, MySQL is at the heart of millions of applications. And no w, with support for stored procedures, functions, and triggers in MySQL 5.0, MySQL offe rs the programming power needed for true enterprise use. MySQL's new procedural languag e has a straightforward syntax, making it easy to write simple programs. But it's not s o easy to write secure, easily maintained, high-performance, and bug-free programs. Few in the MySQL world have substantial experience yet with stored procedures, but Guy Har rison and Steven Feuerstein have decades of combined expertise. In MySQL Stored Procedu re Programming, they put that hard-won experience to good use. Packed with code example s and covering everything from language basics to application building to advanced tuni ng and best practices, this highly readable book is the one-stop guide to MySQL develop ment. It consists of four major sections: * MySQL stored programming fundamentals -- tu torial, basic statements, SQL in stored programs, and error handling * Building MySQL s tored programs -- transaction handling, built-in functions, stored functions, and trigg ers * MySQL stored programs in applications -- using stored programs with PHP, Java, Pe rl, Python, and .NET (C# and VB.NET) * Optimizing MySQL stored programs -- security, ba sic and advanced SQL tuning, optimizing stored program code, and programming best pract ices A companion web site contains many thousands of lines of code, that you can put to use immediately. Guy Harrison is Chief Architect of Database Solutions at Quest Softwa re and a frequent speaker and writer on MySQL topics. Steven Feuerstein is the author o f Oracle PL/SQL Programming, the classic reference for Oracle stored programming for mo re than ten years. Both have decades of experience as database developers, and between them they have authored a dozen books. | 44.99 | artofsql | 52 | | databaseid | Database in Depth | Database Theory |This book sheds l ight on the principles behind the relational model, which is fundamental to all databas e-backed applications--and, consequently, most of the work that goes on in the computin g world today. Database in Depth: The Relational Model for Practitioners goes beyond th e hype and gets to the heart of how relational databases actually work. Ideal for exper ienced database developers and designers, this concise guide gives you a clear view of the technology--a view that's not influenced by any vendor or product. Featuring an ext ensive set of exercises, it will help you: * understand why and how the relational mode l is still directly relevant to modern database technology (and will remain so for the foreseeable future) * see why and how the SQL standard is seriously deficient * use the best current theoretical knowledge in the design of their databases and database appli cations * make informed decisions in their daily database professional activities Datab ase in Depth will appeal not only to database developers and designers, but also to a d iverse field of professionals and academics, including database administrators (DBAs), information modelers, database consultants, and more. Virtually everyone who deals with relational databases should have at least a passing understanding of the fundamentals of working with relational models. Author C.J. Date has been involved with the relation al model from its earliest days. An exceptionally clear-thinking writer, Date lays out principle and theory in a manner that is easily understood. Few others can speak as aut horitatively the topic of relational databases as Date can. | 29.95 | databaseid | 0 | | sqlhks | SQL Hacks | SQL |Whether you're ru nning Access, MySQL, SQL Server, Oracle, or PostgreSQL, this book will help you push th e limits of traditional SQL to squeeze data effectively from your database. The book of fers 100 hacks -- unique tips and tools -- that bring you the knowledge of experts who apply what they know in the real world to help you take full advantage of the expressiv e power of SQL. You'll find practical techniques to address complex data manipulation p roblems. Learn how to: * Wrangle data in the most efficient way possible * Aggregate an d organize your data for meaningful and accurate reporting * Make the most of subquerie s, joins, and unions * Stay on top of the performance of your queries and the server th at runs them * Avoid common SQL security pitfalls, including the dreaded SQL injection attack Let SQL Hacks serve as your toolbox for digging up and manipulating data. If you love to tinker and optimize, SQL is the perfect technology and SQL Hacks is the must-h ave book for you. | 29.99 | databaseid | 0 | | artofsql | The Art of SQL | Database Theory |For all the buzz about trendy IT techniques, data processing is still at the core of our systems, especi ally now that enterprises all over the world are confronted with exploding volumes of d ata. Database performance has become a major headache, and most IT departments believe that developers should provide simple SQL code to solve immediate problems and let DBAs tune any "bad SQL" later. In The Art of SQL, author and SQL expert Stephane Faroult ar gues that this "safe approach" only leads to disaster. His insightful book, named after Art of War by Sun Tzu, contends that writing quick inefficient code is sweeping the di rt under the rug. SQL code may run for 5 to 10 years, surviving several major releases of the database management system and on several generations of hardware. The code must be fast and sound from the start, and that requires a firm understanding of SQL and re lational theory. The Art of SQL offers best practices that teach experienced SQL users to focus on strategy rather than specifics. Faroult's approach takes a page from Sun Tz u's classic treatise by viewing database design as a military campaign. You need knowle dge, skills, and talent. Talent can't be taught, but every strategist from Sun Tzu to m odern-day generals believed that it can be nurtured through the experience of others. T hey passed on their experience acquired in the field through basic principles that serv ed as guiding stars amid the sound and fury of battle. This is what Faroult does with S QL. Like a successful battle plan, good architectural choices are based on contingencie s. What if the volume of this or that table increases unexpectedly? What if, following a merger, the number of users doubles? What if you want to keep several years of data o nline? Faroult's way of looking at SQL performance may be unconventional and unique, bu t he's deadly serious about writing good SQL and using SQL well. The Art of SQL is not a cookbook, listing problems and giving recipes. The aim is to get you-and your manager -to raise good questions. | 44.99 | databaseid | 0 | | sqltuning | SQL Tuning | Database Theory |A poorly performi ng database application not only costs users time, but also has an impact on other appl ications running on the same computer or the same network. SQL Tuning provides an essen tial next step for SQL developers and database administrators who want to extend their SQL tuning expertise and get the most from their database applications. There are two b asic issues to focus on when tuning SQL: how to find and interpret the execution plan o f an SQL statement and how to change SQL to get a specific alternate execution plan. SQ L Tuning provides answers to these questions and addresses a third issue that's even mo re important: how to find the optimal execution plan for the query to use. Author Dan T ow outlines a timesaving method he's developed for finding the optimum execution plan-rapidly and systematically--regardless of the complexity of the SQL or the database pla tform being used. You'll learn how to understand and control SQL execution plans and ho w to diagram SQL queries to deduce the best execution plan for a query. Key chapters in the book include exercises to reinforce the concepts you've learned. SQL Tuning conclu des by addressing special concerns and unique solutions to "unsolvable problems." Wheth er you are a programmer who develops SQL-based applications or a database administrator or other who troubleshoots poorly tuned applications, SQL Tuning will arm you with a r eliable and deterministic method for tuning your SQL queries to gain optimal performanc e. | 39.95 | databaseid | 0 | | mysqlspp | MySQL Stored Procedure Programming | MySQL |The implementatio n of stored procedures in MySQL 5.0 a huge milestone -- one that is expected to lead to widespread enterprise adoption of the already extremely popular MySQL database. If you are serious about building the web-based database applications of the future, you need to get up to speed quickly on how stored procedures work -- and how to build them the right way. This book, destined to be the bible of stored procedure development, is a re source that no real MySQL programmer can afford to do without. In the decade since MySQ L burst on the scene, it has become the dominant open source database, with capabilitie s and performance rivaling those of commercial RDBMS offerings like Oracle and SQL Serv er. Along with Linux and PHP, MySQL is at the heart of millions of applications. And no w, with support for stored procedures, functions, and triggers in MySQL 5.0, MySQL offe rs the programming power needed for true enterprise use. MySQL's new procedural languag e has a straightforward syntax, making it easy to write simple programs. But it's not s o easy to write secure, easily maintained, high-performance, and bug-free programs. Few in the MySQL world have substantial experience yet with stored procedures, but Guy Har rison and Steven Feuerstein have decades of combined expertise. In MySQL Stored Procedu re Programming, they put that hard-won experience to good use. Packed with code example s and covering everything from language basics to application building to advanced tuni ng and best practices, this highly readable book is the one-stop guide to MySQL develop ment. It consists of four major sections: * MySQL stored programming fundamentals -- tu torial, basic statements, SQL in stored programs, and error handling * Building MySQL s tored programs -- transaction handling, built-in functions, stored functions, and trigg ers * MySQL stored programs in applications -- using stored programs with PHP, Java, Pe rl, Python, and .NET (C# and VB.NET) * Optimizing MySQL stored programs -- security, ba sic and advanced SQL tuning, optimizing stored program code, and programming best pract ices A companion web site contains many thousands of lines of code, that you can put to use immediately. Guy Harrison is Chief Architect of Database Solutions at Quest Softwa re and a frequent speaker and writer on MySQL topics. Steven Feuerstein is the author o f Oracle PL/SQL Programming, the classic reference for Oracle stored programming for mo re than ten years. Both have decades of experience as database developers, and between them they have authored a dozen books. | 44.99 | databaseid | 0 | | databaseid | Database in Depth | Database Theory |This book sheds l ight on the principles behind the relational model, which is fundamental to all databas e-backed applications--and, consequently, most of the work that goes on in the computin g world today. Database in Depth: The Relational Model for Practitioners goes beyond th e hype and gets to the heart of how relational databases actually work. Ideal for exper ienced database developers and designers, this concise guide gives you a clear view of the technology--a view that's not influenced by any vendor or product. Featuring an ext ensive set of exercises, it will help you: * understand why and how the relational mode l is still directly relevant to modern database technology (and will remain so for the foreseeable future) * see why and how the SQL standard is seriously deficient * use the best current theoretical knowledge in the design of their databases and database appli cations * make informed decisions in their daily database professional activities Datab ase in Depth will appeal not only to database developers and designers, but also to a d iverse field of professionals and academics, including database administrators (DBAs), information modelers, database consultants, and more. Virtually everyone who deals with relational databases should have at least a passing understanding of the fundamentals of working with relational models. Author C.J. Date has been involved with the relation al model from its earliest days. An exceptionally clear-thinking writer, Date lays out principle and theory in a manner that is easily understood. Few others can speak as aut horitatively the topic of relational databases as Date can. | 29.95 | mysqlspp | 5 | | sqlhks | SQL Hacks | SQL |Whether you're ru nning Access, MySQL, SQL Server, Oracle, or PostgreSQL, this book will help you push th e limits of traditional SQL to squeeze data effectively from your database. The book of fers 100 hacks -- unique tips and tools -- that bring you the knowledge of experts who apply what they know in the real world to help you take full advantage of the expressiv e power of SQL. You'll find practical techniques to address complex data manipulation p roblems. Learn how to: * Wrangle data in the most efficient way possible * Aggregate an d organize your data for meaningful and accurate reporting * Make the most of subquerie s, joins, and unions * Stay on top of the performance of your queries and the server th at runs them * Avoid common SQL security pitfalls, including the dreaded SQL injection attack Let SQL Hacks serve as your toolbox for digging up and manipulating data. If you love to tinker and optimize, SQL is the perfect technology and SQL Hacks is the must-h ave book for you. | 29.99 | mysqlspp | 5 | | artofsql | The Art of SQL | Database Theory |For all the buzz about trendy IT techniques, data processing is still at the core of our systems, especi ally now that enterprises all over the world are confronted with exploding volumes of d ata. Database performance has become a major headache, and most IT departments believe that developers should provide simple SQL code to solve immediate problems and let DBAs tune any "bad SQL" later. In The Art of SQL, author and SQL expert Stephane Faroult ar gues that this "safe approach" only leads to disaster. His insightful book, named after Art of War by Sun Tzu, contends that writing quick inefficient code is sweeping the di rt under the rug. SQL code may run for 5 to 10 years, surviving several major releases of the database management system and on several generations of hardware. The code must be fast and sound from the start, and that requires a firm understanding of SQL and re lational theory. The Art of SQL offers best practices that teach experienced SQL users to focus on strategy rather than specifics. Faroult's approach takes a page from Sun Tz u's classic treatise by viewing database design as a military campaign. You need knowle dge, skills, and talent. Talent can't be taught, but every strategist from Sun Tzu to m odern-day generals believed that it can be nurtured through the experience of others. T hey passed on their experience acquired in the field through basic principles that serv ed as guiding stars amid the sound and fury of battle. This is what Faroult does with S QL. Like a successful battle plan, good architectural choices are based on contingencie s. What if the volume of this or that table increases unexpectedly? What if, following a merger, the number of users doubles? What if you want to keep several years of data o nline? Faroult's way of looking at SQL performance may be unconventional and unique, bu t he's deadly serious about writing good SQL and using SQL well. The Art of SQL is not a cookbook, listing problems and giving recipes. The aim is to get you-and your manager -to raise good questions. | 44.99 | mysqlspp | 5 | | sqltuning | SQL Tuning | Database Theory |A poorly performi ng database application not only costs users time, but also has an impact on other appl ications running on the same computer or the same network. SQL Tuning provides an essen tial next step for SQL developers and database administrators who want to extend their SQL tuning expertise and get the most from their database applications. There are two b asic issues to focus on when tuning SQL: how to find and interpret the execution plan o f an SQL statement and how to change SQL to get a specific alternate execution plan. SQ L Tuning provides answers to these questions and addresses a third issue that's even mo re important: how to find the optimal execution plan for the query to use. Author Dan T ow outlines a timesaving method he's developed for finding the optimum execution plan-rapidly and systematically--regardless of the complexity of the SQL or the database pla tform being used. You'll learn how to understand and control SQL execution plans and ho w to diagram SQL queries to deduce the best execution plan for a query. Key chapters in the book include exercises to reinforce the concepts you've learned. SQL Tuning conclu des by addressing special concerns and unique solutions to "unsolvable problems." Wheth er you are a programmer who develops SQL-based applications or a database administrator or other who troubleshoots poorly tuned applications, SQL Tuning will arm you with a r eliable and deterministic method for tuning your SQL queries to gain optimal performanc e. | 39.95 | mysqlspp | 5 | | mysqlspp | MySQL Stored Procedure Programming | MySQL |The implementatio n of stored procedures in MySQL 5.0 a huge milestone -- one that is expected to lead to widespread enterprise adoption of the already extremely popular MySQL database. If you are serious about building the web-based database applications of the future, you need to get up to speed quickly on how stored procedures work -- and how to build them the right way. This book, destined to be the bible of stored procedure development, is a re source that no real MySQL programmer can afford to do without. In the decade since MySQ L burst on the scene, it has become the dominant open source database, with capabilitie s and performance rivaling those of commercial RDBMS offerings like Oracle and SQL Serv er. Along with Linux and PHP, MySQL is at the heart of millions of applications. And no w, with support for stored procedures, functions, and triggers in MySQL 5.0, MySQL offe rs the programming power needed for true enterprise use. MySQL's new procedural languag e has a straightforward syntax, making it easy to write simple programs. But it's not s o easy to write secure, easily maintained, high-performance, and bug-free programs. Few in the MySQL world have substantial experience yet with stored procedures, but Guy Har rison and Steven Feuerstein have decades of combined expertise. In MySQL Stored Procedu re Programming, they put that hard-won experience to good use. Packed with code example s and covering everything from language basics to application building to advanced tuni ng and best practices, this highly readable book is the one-stop guide to MySQL develop ment. It consists of four major sections: * MySQL stored programming fundamentals -- tu torial, basic statements, SQL in stored programs, and error handling * Building MySQL s tored programs -- transaction handling, built-in functions, stored functions, and trigg ers * MySQL stored programs in applications -- using stored programs with PHP, Java, Pe rl, Python, and .NET (C# and VB.NET) * Optimizing MySQL stored programs -- security, ba sic and advanced SQL tuning, optimizing stored program code, and programming best pract ices A companion web site contains many thousands of lines of code, that you can put to use immediately. Guy Harrison is Chief Architect of Database Solutions at Quest Softwa re and a frequent speaker and writer on MySQL topics. Steven Feuerstein is the author o f Oracle PL/SQL Programming, the classic reference for Oracle stored programming for mo re than ten years. Both have decades of experience as database developers, and between them they have authored a dozen books. | 44.99 | mysqlspp | 5 | | databaseid | Database in Depth | Database Theory |This book sheds l ight on the principles behind the relational model, which is fundamental to all databas e-backed applications--and, consequently, most of the work that goes on in the computin g world today. Database in Depth: The Relational Model for Practitioners goes beyond th e hype and gets to the heart of how relational databases actually work. Ideal for exper ienced database developers and designers, this concise guide gives you a clear view of the technology--a view that's not influenced by any vendor or product. Featuring an ext ensive set of exercises, it will help you: * understand why and how the relational mode l is still directly relevant to modern database technology (and will remain so for the foreseeable future) * see why and how the SQL standard is seriously deficient * use the best current theoretical knowledge in the design of their databases and database appli cations * make informed decisions in their daily database professional activities Datab ase in Depth will appeal not only to database developers and designers, but also to a d iverse field of professionals and academics, including database administrators (DBAs), information modelers, database consultants, and more. Virtually everyone who deals with relational databases should have at least a passing understanding of the fundamentals of working with relational models. Author C.J. Date has been involved with the relation al model from its earliest days. An exceptionally clear-thinking writer, Date lays out principle and theory in a manner that is easily understood. Few others can speak as aut horitatively the topic of relational databases as Date can. | 29.95 | sqlhks | 32 | | sqlhks | SQL Hacks | SQL |Whether you're ru nning Access, MySQL, SQL Server, Oracle, or PostgreSQL, this book will help you push th e limits of traditional SQL to squeeze data effectively from your database. The book of fers 100 hacks -- unique tips and tools -- that bring you the knowledge of experts who apply what they know in the real world to help you take full advantage of the expressiv e power of SQL. You'll find practical techniques to address complex data manipulation p roblems. Learn how to: * Wrangle data in the most efficient way possible * Aggregate an d organize your data for meaningful and accurate reporting * Make the most of subquerie s, joins, and unions * Stay on top of the performance of your queries and the server th at runs them * Avoid common SQL security pitfalls, including the dreaded SQL injection attack Let SQL Hacks serve as your toolbox for digging up and manipulating data. If you love to tinker and optimize, SQL is the perfect technology and SQL Hacks is the must-h ave book for you. | 29.99 | sqlhks | 32 | | artofsql | The Art of SQL | Database Theory |For all the buzz about trendy IT techniques, data processing is still at the core of our systems, especi ally now that enterprises all over the world are confronted with exploding volumes of d ata. Database performance has become a major headache, and most IT departments believe that developers should provide simple SQL code to solve immediate problems and let DBAs tune any "bad SQL" later. In The Art of SQL, author and SQL expert Stephane Faroult ar gues that this "safe approach" only leads to disaster. His insightful book, named after Art of War by Sun Tzu, contends that writing quick inefficient code is sweeping the di rt under the rug. SQL code may run for 5 to 10 years, surviving several major releases of the database management system and on several generations of hardware. The code must be fast and sound from the start, and that requires a firm understanding of SQL and re lational theory. The Art of SQL offers best practices that teach experienced SQL users to focus on strategy rather than specifics. Faroult's approach takes a page from Sun Tz u's classic treatise by viewing database design as a military campaign. You need knowle dge, skills, and talent. Talent can't be taught, but every strategist from Sun Tzu to m odern-day generals believed that it can be nurtured through the experience of others. T hey passed on their experience acquired in the field through basic principles that serv ed as guiding stars amid the sound and fury of battle. This is what Faroult does with S QL. Like a successful battle plan, good architectural choices are based on contingencie s. What if the volume of this or that table increases unexpectedly? What if, following a merger, the number of users doubles? What if you want to keep several years of data o nline? Faroult's way of looking at SQL performance may be unconventional and unique, bu t he's deadly serious about writing good SQL and using SQL well. The Art of SQL is not a cookbook, listing problems and giving recipes. The aim is to get you-and your manager -to raise good questions. | 44.99 | sqlhks | 32 | | sqltuning | SQL Tuning | Database Theory |A poorly performi ng database application not only costs users time, but also has an impact on other appl ications running on the same computer or the same network. SQL Tuning provides an essen tial next step for SQL developers and database administrators who want to extend their SQL tuning expertise and get the most from their database applications. There are two b asic issues to focus on when tuning SQL: how to find and interpret the execution plan o f an SQL statement and how to change SQL to get a specific alternate execution plan. SQ L Tuning provides answers to these questions and addresses a third issue that's even mo re important: how to find the optimal execution plan for the query to use. Author Dan T ow outlines a timesaving method he's developed for finding the optimum execution plan-- rapidly and systematically--regardless of the complexity of the SQL or the database pla tform being used. You'll learn how to understand and control SQL execution plans and ho w to diagram SQL queries to deduce the best execution plan for a query. Key chapters in the book include exercises to reinforce the concepts you've learned. SQL Tuning conclu des by addressing special concerns and unique solutions to "unsolvable problems." Wheth er you are a programmer who develops SQL-based applications or a database administrator or other who troubleshoots poorly tuned applications, SQL Tuning will arm you with a r eliable and deterministic method for tuning your SQL queries to gain optimal performanc e. | 39.95 | sqlhks | 32 | | mysqlspp | MySQL Stored Procedure Programming | MySQL |The implementatio n of stored procedures in MySQL 5.0 a huge milestone -- one that is expected to lead to widespread enterprise adoption of the already extremely popular MySQL database. If you are serious about building the web-based database applications of the future, you need to get up to speed quickly on how stored procedures work -- and how to build them the right way. This book, destined to be the bible of stored procedure development, is a re source that no real MySQL programmer can afford to do without. In the decade since MySQ L burst on the scene, it has become the dominant open source database, with capabilitie s and performance rivaling those of commercial RDBMS offerings like Oracle and SQL Serv er. Along with Linux and PHP, MySQL is at the heart of millions of applications. And no w, with support for stored procedures, functions, and triggers in MySQL 5.0, MySQL offe rs the programming power needed for true enterprise use. MySQL's new procedural languag e has a straightforward syntax, making it easy to write simple programs. But it's not s o easy to write secure, easily maintained, high-performance, and bug-free programs. Few in the MySQL world have substantial experience yet with stored procedures, but Guy Har rison and Steven Feuerstein have decades of combined expertise. In MySQL Stored Procedu re Programming, they put that hard-won experience to good use. Packed with code example s and covering everything from language basics to application building to advanced tuni ng and best practices, this highly readable book is the one-stop guide to MySQL develop ment. It consists of four major sections: * MySQL stored programming fundamentals -- tu torial, basic statements, SQL in stored programs, and error handling * Building MySQL s tored programs -- transaction handling, built-in functions, stored functions, and trigg ers * MySQL stored programs in applications -- using stored programs with PHP, Java, Pe rl, Python, and .NET (C# and VB.NET) * Optimizing MySQL stored programs -- security, ba sic and advanced SQL tuning, optimizing stored program code, and programming best pract ices A companion web site contains many thousands of lines of code, that you can put to use immediately. Guy Harrison is Chief Architect of Database Solutions at Quest Softwa re and a frequent speaker and writer on MySQL topics. Steven Feuerstein is the author o f Oracle PL/SQL Programming, the classic reference for Oracle stored programming for mo re than ten years. Both have decades of experience as database developers, and between them they have authored a dozen books. | 44.99 | sqlhks | 32 | | databaseid | Database in Depth | Database Theory |This book sheds l ight on the principles behind the relational model, which is fundamental to all databas e-backed applications--and, consequently, most of the work that goes on in the computin g world today. Database in Depth: The Relational Model for Practitioners goes beyond th e hype and gets to the heart of how relational databases actually work. Ideal for exper ienced database developers and designers, this concise guide gives you a clear view of the technology--a view that's not influenced by any vendor or product. Featuring an ext ensive set of exercises, it will help you: * understand why and how the relational mode l is still directly relevant to modern database technology (and will remain so for the foreseeable future) * see why and how the SQL standard is seriously deficient * use the best current theoretical knowledge in the design of their databases and database appli cations * make informed decisions in their daily database professional activities Datab ase in Depth will appeal not only to database developers and designers, but also to a d iverse field of professionals and academics, including database administrators (DBAs), information modelers, database consultants, and more. Virtually everyone who deals with relational databases should have at least a passing understanding of the fundamentals of working with relational models. Author C.J. Date has been involved with the relation al model from its earliest days. An exceptionally clear-thinking writer, Date lays out principle and theory in a manner that is easily understood. Few others can speak as aut horitatively the topic of relational databases as Date can. | 29.95 | sqltuning | 105 | | sqlhks | SQL Hacks | SQL |Whether you're ru nning Access, MySQL, SQL Server, Oracle, or PostgreSQL, this book will help you push th e limits of traditional SQL to squeeze data effectively from your database. The book of fers 100 hacks -- unique tips and tools -- that bring you the knowledge of experts who apply what they know in the real world to help you take full advantage of the expressiv e power of SQL. You'll find practical techniques to address complex data manipulation p roblems. Learn how to: * Wrangle data in the most efficient way possible * Aggregate an d organize your data for meaningful and accurate reporting * Make the most of subquerie s, joins, and unions * Stay on top of the performance of your queries and the server th at runs them * Avoid common SQL security pitfalls, including the dreaded SQL injection attack Let SQL Hacks serve as your toolbox for digging up and manipulating data. If you love to tinker and optimize, SQL is the perfect technology and SQL Hacks is the must-h ave book for you. | 29.99 | sqltuning | 105 | | artofsql | The Art of SQL | Database Theory |For all the buzz about trendy IT techniques, data processing is still at the core of our systems, especi ally now that enterprises all over the world are confronted with exploding volumes of d ata. Database performance has become a major headache, and most IT departments believe that developers should provide simple SQL code to solve immediate problems and let DBAs tune any "bad SQL" later. In The Art of SQL, author and SQL expert Stephane Faroult ar gues that this "safe approach" only leads to disaster. His insightful book, named after Art of War by Sun Tzu, contends that writing quick inefficient code is sweeping the di rt under the rug. SQL code may run for 5 to 10 years, surviving several major releases of the database management system and on several generations of hardware. The code must be fast and sound from the start, and that requires a firm understanding of SQL and re lational theory. The Art of SQL offers best practices that teach experienced SQL users to focus on strategy rather than specifics. Faroult's approach takes a page from Sun Tz u's classic treatise by viewing database design as a military campaign. You need knowle dge, skills, and talent. Talent can't be taught, but every strategist from Sun Tzu to m odern-day generals believed that it can be nurtured through the experience of others. T hey passed on their experience acquired in the field through basic principles that serv ed as guiding stars amid the sound and fury of battle. This is what Faroult does with S QL. Like a successful battle plan, good architectural choices are based on contingencie s. What if the volume of this or that table increases unexpectedly? What if, following a merger, the number of users doubles? What if you want to keep several years of data o nline? Faroult's way of looking at SQL performance may be unconventional and unique, bu t he's deadly serious about writing good SQL and using SQL well. The Art of SQL is not a cookbook, listing problems and giving recipes. The aim is to get you-and your manager -to raise good questions. | 44.99 | sqltuning | 105 | | sqltuning | SQL Tuning | Database Theory |A poorly performi ng database application not only costs users time, but also has an impact on other appl ications running on the same computer or the same network. SQL Tuning provides an essen tial next step for SQL developers and database administrators who want to extend their SQL tuning expertise and get the most from their database applications. There are two b asic issues to focus on when tuning SQL: how to find and interpret the execution plan o f an SQL statement and how to change SQL to get a specific alternate execution plan. SQ L Tuning provides answers to these questions and addresses a third issue that's even mo re important: how to find the optimal execution plan for the query to use. Author Dan T ow outlines a timesaving method he's developed for finding the optimum execution plan-rapidly and systematically--regardless of the complexity of the SQL or the database pla tform being used. You'll learn how to understand and control SQL execution plans and ho w to diagram SQL queries to deduce the best execution plan for a query. Key chapters in the book include exercises to reinforce the concepts you've learned. SQL Tuning conclu des by addressing special concerns and unique solutions to "unsolvable problems." Wheth er you are a programmer who develops SQL-based applications or a database administrator or other who troubleshoots poorly tuned applications, SQL Tuning will arm you with a r eliable and deterministic method for tuning your SQL queries to gain optimal performanc e. | 39.95 | sqltuning | 105 | | mysqlspp | MySQL Stored Procedure Programming | MySQL |The implementatio n of stored procedures in MySQL 5.0 a huge milestone -- one that is expected to lead to widespread enterprise adoption of the already extremely popular MySQL database. If you are serious about building the web-based database applications of the future, you need to get up to speed quickly on how stored procedures work -- and how to build them the right way. This book, destined to be the bible of stored procedure development, is a re source that no real MySQL programmer can afford to do without. In the decade since MySQ L burst on the scene, it has become the dominant open source database, with capabilitie s and performance rivaling those of commercial RDBMS offerings like Oracle and SQL Serv er. Along with Linux and PHP, MySQL is at the heart of millions of applications. And no w, with support for stored procedures, functions, and triggers in MySQL 5.0, MySQL offe rs the programming power needed for true enterprise use. MySQL's new procedural languag e has a straightforward syntax, making it easy to write simple programs. But it's not s o easy to write secure, easily maintained, high-performance, and bug-free programs. Few in the MySQL world have substantial experience yet with stored procedures, but Guy Har rison and Steven Feuerstein have decades of combined expertise. In MySQL Stored Procedu re Programming, they put that hard-won experience to good use. Packed with code example s and covering everything from language basics to application building to advanced tuni ng and best practices, this highly readable book is the one-stop guide to MySQL develop ment. It consists of four major sections: * MySQL stored programming fundamentals -- tu torial, basic statements, SQL in stored programs, and error handling * Building MySQL s tored programs -- transaction handling, built-in functions, stored functions, and trigg ers * MySQL stored programs in applications -- using stored programs with PHP, Java, Pe rl, Python, and .NET (C# and VB.NET) * Optimizing MySQL stored programs -- security, ba sic and advanced SQL tuning, optimizing stored program code, and programming best pract ices A companion web site contains many thousands of lines of code, that you can put to use immediately. Guy Harrison is Chief Architect of Database Solutions at Quest Softwa re and a frequent speaker and writer on MySQL topics. Steven Feuerstein is the author o f Oracle PL/SQL Programming, the classic reference for Oracle stored programming for mo re than ten years. Both have decades of experience as database developers, and between them they have authored a dozen books. | 44.99 | sqltuning | 105 | +-------------+------------------------------------+-----------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------+-------------+-----------------+ 25 rows in set (0.00 sec) mysql> The database gave yo u the exact info rmatio n yo u requested—it matched every ro w in the Pro ducts table with every ro w in the Invento ry table. Five ro ws in Pro ducts times five ro ws in Invento ry (5 x 5) = 25 ro ws. This is the cartesian product o f tho se two tables. Graphically, a cartesian pro duct lo o ks like this: Fo r jo ins to be effective, yo u need to specify ho w to link tables to gether. Yo u do this by specifying the join columns. Note Yo u can jo in nearly any co lumn, with nearly any data type. Usually, fo r perfo rmance reaso ns, we o nly want to jo in o n o ur primary key (o r ano ther key). We kno w that the Pro ducts and Invento ry tables have a co mmo n co lumn: Pro ductCo de. We'll jo in o n this co lumn. We'll also specify the co lumns we want to view instead o f requesting all co lumns. Type the fo llo wing at the MySQL pro mpt: mysql> SELECT Products.ProductCode, Products.Title, Products.Price, I.QuantityInStock a s Qty -> FROM Products -> JOIN Inventory as I on (Products.ProductCode = I.ProductCode); +-------------+------------------------------------+-------+-----+ | ProductCode | Title | Price | Qty | +-------------+------------------------------------+-------+-----+ | artofsql | The Art of SQL | 44.99 | 52 | | databaseid | Database in Depth | 29.95 | 0 | | mysqlspp | MySQL Stored Procedure Programming | 44.99 | 5 | | sqlhks | SQL Hacks | 29.99 | 32 | | sqltuning | SQL Tuning | 39.95 | 105 | +-------------+------------------------------------+-------+-----+ 5 rows in set (0.00 sec) mysql> Yo u see the five ro ws fro m the Invento ry and Pro ducts tables that have the same Pro ductCo de. Yo ur results might be in a different o rder, because we didn't ask the database to return the results in any particular o rder. Let's lo o k a little clo ser. OBSERVE: mysql> SELECT Products.ProductCode, Products.Title, Products.Price, I.QuantityInStock a s Qty -> FROM Products -> JOIN Inventory as I on (Products.ProductCode = I.ProductCode); No tice that we listed the Pro ductCo de co lumn as Pro duct s.Pro ductCo de? Different tables might have co lumns with the same names, so SQL requires us to reference a specific table and co lumn. We do this by using the TableName.ColumnName syntax. There is a sho rtcut available. Yo u can specify a sho rter name fo r a table as a table alias. In o ur example we created an alias fo r Invento ry called I by typing Inve nt o ry as I. Yo u can also specify a column alias using the same syntax. See ho w we renamed the Quant it yInSt o ck co lumn? Finally, we specify the co lumns we want to jo in o n by using the o n keywo rd: o n (Pro duct s.Pro duct Co de = I.Pro duct Co de ). Graphically, a jo in co uld lo o k so mething like this: Co ngratulatio ns, yo u've written o ne query to get yo ur pro duct and invento ry info rmatio n! Other Joins Left Joins What happens if so meo ne at the bo o ksto re has created a ro w in the Pro ducts table fo r a new bo o k, but hasn't entered a co rrespo nding ro w in Invento ry? Let's see fo r o urselves by adding o ne mo re bo o k to the Pro duct table. We'll do wnlo ad this o ne as well. Type the fo llo wing at the MySQL pro mpt: mysql> exit; Bye cold1:~$ curl -L http://courses.oreillyschool.com/dba1/downloads/products-1.sql > products-1.sql % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 101 1219 101 1219 0 0 9718 0 --:--:-- --:--:-- --:--:-- 1190k cold1:~$ Once that file has do wnlo aded, use the m ysql co mmand to impo rt the pro ducts. Type the fo llo wing at the Unix pro mpt: cold1:~$ mysql -h sql -p -u username username < products-1.sql Enter password: cold1:~$ Again, if the impo rt is successful, yo u see no results. This added a reco rd to the Pro ducts table fo r relatio naldb, "The Relatio nal Database Dictio nary." Once yo u have that data impo rted, reco nnect to MySQL. Be sure to set sql_m o de ='t radit io nal' again. No w run yo ur previo us query to retrieve the pro duct quantities. Here it is again (using table aliases this time): Type the fo llo wing at the MySQL pro mpt: mysql> SELECT P.ProductCode, P.Title, P.Price, I.QuantityInStock as Qty -> FROM Products as P -> JOIN Inventory as I on (P.ProductCode = I.ProductCode); +-------------+------------------------------------+-------+-----+ | ProductCode | Title | Price | Qty | +-------------+------------------------------------+-------+-----+ | artofsql | The Art of SQL | 44.99 | 52 | | databaseid | Database in Depth | 29.95 | 0 | | mysqlspp | MySQL Stored Procedure Programming | 44.99 | 5 | | sqlhks | SQL Hacks | 29.99 | 32 | | sqltuning | SQL Tuning | 39.95 | 105 | +-------------+------------------------------------+-------+-----+ 5 rows in set (0.00 sec) mysql> Yo u ran the insert statement, but yo ur results are the same as befo re! The database is do ing exactly what yo u asked it to do —it's sho wing yo u every ro w fro m Invento ry and Pro ducts where the pro duct co de is the same. Since the invento ry table do esn't have a ro w with Pro duct Co de ='re lat io naldb', no ro w is returned fo r that bo o k. It wo uld be nice to see such a ro w, tho ugh. Fo rtunately there is a way we can make this happen—the LEFT JOIN. The left jo in tells the database to return all ro ws fro m the first o r LEFT table, even if a co rrespo nding ro w do esn't exist in the seco nd o r RIGHT table. Graphically, a left jo in lo o ks like this: Let's try a left jo in. Type the fo llo wing at the MySQL pro mpt: mysql> SELECT P.ProductCode, P.Title, P.Price, I.QuantityInStock as Qty -> FROM Products as P -> LEFT JOIN Inventory as I on (P.ProductCode = I.ProductCode); +--------------+------------------------------------+-------+------+ | ProductCode | Title | Price | Qty | +--------------+------------------------------------+-------+------+ | artofsql | The Art of SQL | 44.99 | 52 | | databaseid | Database in Depth | 29.95 | 0 | | mysqlspp | MySQL Stored Procedure Programming | 44.99 | 5 | | relationaldb | The Relational Database Dictionary | 14.99 | NULL | | sqlhks | SQL Hacks | 29.99 | 32 | | sqltuning | SQL Tuning | 39.95 | 105 | +--------------+------------------------------------+-------+------+ 6 rows in set (0.00 sec) mysql> No w the missing ro w fro m Pro ducts is returned, alo ng with a NULL quantity since no co rrespo nding ro w exists in the Invento ry table. Yo ur results may be so rted differently—that is OK. Full Outer Joins / Union What if yo u wanted to jo in the Pro ducts and Invento ry tables, sho wing ro ws fro m Pro ducts that do n't match ro ws in Invento ry, and ro ws in Invento ry that do n't match ro ws in Pro ducts? This is called a FULL OUTER JOIN. Graphically, a full outer join lo o ks like this: Befo re we try o ut a full o uter jo in, let's create an entry in Invento ry that do esn't match anything in Pro ducts. Type the fo llo wing at the MySQL pro mpt: mysql> INSERT INTO Inventory VALUES ('Q4440', 14); Query OK, 1 row affected (0.01 sec) mysql> Note Usually yo u wo uldn't want a ro w to be in invento ry unless there was already a co rrespo nding ro w in Pro ducts. The database has a way yo u can enfo rce this rule, called a foreign key constraint. We'll discuss this in a future co urse. No w let's try to query o ur tables. Type the fo llo wing at the MySQL pro mpt: mysql> SELECT P.ProductCode, I.QuantityInStock, P.Title, P.Price -> FROM Products as P -> FULL OUTER JOIN Inventory as I on (P.ProductCode = I.ProductCode); ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FULL OUTER JOIN Inventory as I on (P.ProductCode = I.ProductCode)' at line 3 mysql> Unfo rtunately, MySQL do esn't suppo rt full o uter jo ins. As with mo st pro gramming languages, there is ano ther way to perfo rm this query. Fo rtunately, MySQL do es suppo rt the UNION keywo rd. A union will co mbine two select statements into o ne resulting data set. The o nly restrictio n is that the two queries must return the same number o f co lumns o f the same data type. Fo r o ur full o uter jo in pro blem, we can use o ur previo us LEFT JOIN query to retrieve Pro ducts and Invento ry, and unio n tho se results with a new query that is just the o ppo site: a LEFT JOIN o f Invento ry o n Pro ducts. First, let's write a LEFT JOIN query o f Invento ry o n Pro ducts. We'll make sure to specify exactly the same co lumns as o ur previo us query, except ProductCode. We'll reference the ProductCode fro m Invento ry instead o f Pro ducts this time. Type the fo llo wing at the MySQL pro mpt: mysql> SELECT I.ProductCode, I.QuantityInStock, P.Title, P.Price -> FROM Inventory as I -> LEFT JOIN Products as P on (P.ProductCode = I.ProductCode) -> WHERE P.ProductCode IS NULL; +-------------+-----------------+-------+-------+ | ProductCode | QuantityInStock | Title | Price | +-------------+-----------------+-------+-------+ | Q4440 | 14 | NULL | NULL | +-------------+-----------------+-------+-------+ 1 row in set (0.00 sec) mysql> Fo r this query we added a WHERE clause that limits o ur data set to ro ws fro m Invento ry that do n't have co rrespo nding ro ws in Pro ducts. If we didn't include this WHERE clause, we wo uld get duplicates in o ur UNIONed data set because o ur previo us query includes matching ro ws. This is exactly what we want—o nly the ro ws fro m Invento ry that do n't co rrespo nd to ro ws in Pro ducts. No w we can co mbine o ur two queries. Type the fo llo wing at the MySQL pro mpt: mysql> SELECT P.ProductCode, I.QuantityInStock, P.Title, P.Price -> FROM Products as P -> LEFT JOIN Inventory as I on (P.ProductCode = I.ProductCode) -> UNION ALL -> SELECT I.ProductCode, I.QuantityInStock, P.Title, P.Price -> FROM Inventory as I -> LEFT JOIN Products as P on (P.ProductCode = I.ProductCode) -> WHERE P.ProductCode IS NULL; +--------------+-----------------+------------------------------------+-------+ | ProductCode | QuantityInStock | Title | Price | +--------------+-----------------+------------------------------------+-------+ | artofsql | 52 | The Art of SQL | 44.99 | | databaseid | 0 | Database in Depth | 29.95 | | mysqlspp | 5 | MySQL Stored Procedure Programming | 44.99 | | relationaldb | NULL | The Relational Database Dictionary | 14.99 | | sqlhks | 32 | SQL Hacks | 29.99 | | sqltuning | 105 | SQL Tuning | 39.95 | | Q4440 | 14 | NULL | NULL | +--------------+-----------------+------------------------------------+-------+ 7 rows in set (0.02 sec) mysql> Take a clo ser lo o k at the co mmand and the results: OBSERVE: mysql> SELECT P.ProductCode, I.QuantityInStock, P.Title, P.Price -> FROM Products as P -> LEFT JOIN Inventory as I on (P.ProductCode = I.ProductCode) -> UNION ALL -> SELECT I.ProductCode, I.QuantityInStock, P.Title, P.Price -> FROM Inventory as I -> LEFT JOIN Products as P on (P.ProductCode = I.ProductCode) -> WHERE P.ProductCode IS NULL; +--------------+-----------------+------------------------------------+-------+ | ProductCode | QuantityInStock | Title | Price | +--------------+-----------------+------------------------------------+-------+ | artofsql | 52 | The Art of SQL | 44.99 | | databaseid | 0 | Database in Depth | 29.95 | | mysqlspp | 5 | MySQL Stored Procedure Programming | 44.99 | | relationaldb | NULL | The Relational Database Dictionary | 14.99 | | sqlhks | 32 | SQL Hacks | 29.99 | | sqltuning | 105 | SQL Tuning | 39.95 | | Q4440 | 14 | NULL | NULL | +--------------+-----------------+------------------------------------+-------+ 7 rows in set (0.02 sec) First yo u see o ur pre vio us que ry, then the UNION ALL keywo rd, and then o ur ne w que ry. This is o ur full o uter jo in—ro ws in Pro ducts that do n't match ro ws in Invento ry, and ro ws in Invento ry that do n't match ro ws in Pro ducts. The f irst six ro ws are fro m the first query, and the last ro w is fro m the seco nd query. Yo u've learned a lo t in this lesso n! In the next lesso n yo u'll learn ho w to further co mbine yo ur data in meaningful ways to answer many new business questio ns. See yo u there! Copyright © 1998-2014 O'Reilly Media, Inc. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License. See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information. Aggregates, Functions, and Conditionals In this lesso n yo u'll learn several mo re ways yo u can query yo ur data. Aggregating Data Aggregate functio ns create summaries fro m yo ur ro ws and co lumns o f data. The simplest aggregate functio n is COUNT, which is a ro w co unt. Let's try it o ut by retrieving the number o f ro ws (pro ducts) ro ws in the Pro ducts table. Type the fo llo wing at the MySQL pro mpt: mysql> SELECT COUNT(*) FROM Products; +----------+ | COUNT(*) | +----------+ | 6 | +----------+ 1 row in set (0.00 sec) mysql> Note If yo u've changed the Pro ducts table fro m the last lesso n, yo u'll see a different number. Here, the COUNT aggregate has given us the number o f ro ws in the Pro ducts table. It wo uld be nice to be able to answer mo re co mplex questio ns, such as "Ho w many pro ducts are in each catego ry?" To answer that questio n, we must GROUP BY the Catego ry co lumn o n the Pro ducts table. Type the fo llo wing at the MySQL pro mpt: mysql> SELECT Category, COUNT(*) as NumberOfProducts -> FROM Products -> GROUP BY Category; +-----------------+------------------+ | Category | NumberOfProducts | +-----------------+------------------+ | Database Theory | 3 | | MySQL | 1 | | SQL | 2 | +-----------------+------------------+ 3 rows in set (0.00 sec) mysql> There are three bo o ks in the "Database Theo ry" catego ry, o ne in "MySQL," and two in "SQL." What if yo u want to find the average price and the maximum price o f the pro ducts in each catego ry? Yo u can use multiple aggregates in the same query. Type the fo llo wing at the MySQL pro mpt: mysql> SELECT Category, AVG(Price) as AveragePrice, MAX(Price) as MaximumPrice -> FROM Products -> GROUP BY Category; +-----------------+--------------+--------------+ | Category | AveragePrice | MaximumPrice | +-----------------+--------------+--------------+ | Database Theory | 38.296667 | 44.99 | | MySQL | 44.990000 | 44.99 | | SQL | 22.490000 | 29.99 | +-----------------+--------------+--------------+ 3 rows in set (0.00 sec) mysql> OBSERVE: mysql> SELECT Category, AVG(Price) as AveragePrice, MAX(Price) as MaximumPrice -> FROM Products -> GROUP BY Category; In this query, we specified the co lumns o n which we wo uld like to apply the aggregate. The AVG aggregate is o ver the Price co lumn, and so is the MAX aggregate. MySQL allo ws yo u to o mit the GROUP BY clause in so me queries, but if yo u o mit GROUP BY, yo ur query may no t return the same results. Try it: Type the fo llo wing at the MySQL pro mpt: mysql> SELECT Category, AVG(Price) as AveragePrice, MAX(Price) as MaximumPrice -> FROM Products; +-----------------+--------------+--------------+ | Category | AveragePrice | MaximumPrice | +-----------------+--------------+--------------+ | Database Theory | 34.143333 | 44.99 | +-----------------+--------------+--------------+ 1 row in set (0.00 sec) mysql> Yo u o nly see o ne result ro w. If yo u want, yo u can disable this MySQL-specific behavio r by changing the SQL_MODE. Type the fo llo wing at the MySQL pro mpt: mysql> set SQL_MODE='ONLY_FULL_GROUP_BY'; Query OK, 0 rows affected (0.00 sec) mysql> No w when yo u run a query witho ut a GROUP BY yo u will see an erro r (assuming yo ur sql_mo de is still set to 'ONLY_FULL_GROUP_BY'). Type the fo llo wing at the MySQL pro mpt: mysql> SELECT Category, AVG(Price) as AveragePrice, MAX(Price) as MaximumPrice -> FROM Products; ERROR 1140 (42000): Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP col umns is illegal if there is no GROUP BY clause Fo r mo re info rmatio n abo ut MySQL's use o f GROUP BY, see MySQL's web site. There are many mo re useful aggregate functio ns, such as SUM and MIN. See MySQL's web site fo r additio nal aggregate functio ns. Be sure to take so me time and experiment with these! Functions While aggregates allo w yo u to summarize many ro ws o f info rmatio n, functio ns allo w yo u to create brand-new co lumns o f data. The sto re keeps track o f pro ducts, and the number o f pro ducts in invento ry. Suppo se yo ur manager wants to kno w the do llar value o f the pro ducts in sto ck. In the last lesso n we used a jo in to sho w the pro ducts alo ng with the quantity in sto ck. Let's write that query again. Type the fo llo wing at the MySQL pro mpt: mysql> SELECT P.ProductCode, P.Price, I.QuantityInStock as Qty -> FROM Products as P -> LEFT JOIN Inventory as I on (P.ProductCode = I.ProductCode); +--------------+-------+------+ | ProductCode | Price | Qty | +--------------+-------+------+ | artofsql | 44.99 | 52 | | databaseid | 29.95 | 0 | | mysqlspp | 44.99 | 5 | | relationaldb | 14.99 | NULL | | sqlhks | 29.99 | 32 | | sqltuning | 39.95 | 105 | +--------------+-------+------+ 6 rows in set (0.00 sec) mysql> The do llar value fo r a pro duct is the Price times the Quantity. Let's add this "Do llar Value" to o ur query. Type the fo llo wing at the MySQL pro mpt: mysql> SELECT P.ProductCode, P.Price, I.QuantityInStock as Qty, P.Price * I.QuantityInS tock as DollarValue -> FROM Products as P -> LEFT JOIN Inventory as I on (P.ProductCode = I.ProductCode); +--------------+-------+------+-------------+ | ProductCode | Price | Qty | DollarValue | +--------------+-------+------+-------------+ | artofsql | 44.99 | 52 | 2339.48 | | databaseid | 29.95 | 0 | 0.00 | | mysqlspp | 44.99 | 5 | 224.95 | | relationaldb | 14.99 | NULL | NULL | | sqlhks | 29.99 | 32 | 959.68 | | sqltuning | 39.95 | 105 | 4194.75 | +--------------+-------+------+-------------+ 6 rows in set (0.00 sec) mysql> OBSERVE: P.Price * I.QuantityInStock as DollarValue The result includes has a new Do llarValue co lumn which is the pro duct o f Price and Quant it y. It might seem strange to have a NULL Do llarValue. But it is the desired result, since Qty is NULL fo r that ro w. So ho w can we find the to tal do llar value fo r o ur pro ducts? Let's co mbine o ur functio n with the SUM aggregate! Type the fo llo wing at the MySQL pro mpt: mysql> SELECT P.ProductCode, P.Price, I.QuantityInStock as Qty, SUM(P.Price * I.Quantit yInStock) as DollarValue -> FROM Products as P -> LEFT JOIN Inventory as I on (P.ProductCode = I.ProductCode); ERROR 1140 (42000): Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP col umns is illegal if there is no GROUP BY clause mysql> We are asking fo r a summary o f all ro ws in the Pro ducts and Invento ry tables, alo ng with the Pro ductCo de, Price, and QuantityInSto ck. This do esn't make sense—what is the Pro ductCo de fo r the total sum? The database canno t give yo u a co rrect answer, so yo u get the no nsensical result. To co rrect this pro blem, yo u have two o ptio ns: yo u can remo ve the extra co lumns fro m yo ur query, o r yo u can GROUP BY tho se co lumns. Since we are lo o king fo r the to tal o f all ro ws, let's remo ve the co lumns. Type the fo llo wing at the MySQL pro mpt: mysql> SELECT SUM(P.Price * I.QuantityInStock) as TotalDollarValue -> FROM Products as P -> LEFT JOIN Inventory as I on (P.ProductCode = I.ProductCode); +------------------+ | TotalDollarValue | +------------------+ | 7718.86 | +------------------+ 1 row in set (0.00 sec) mysql> This query is much better, and gives us the desired result. MySQL has many functio ns that o perate o n strings, numbers, and dates. Yo u can find mo re info rmatio n abo ut these functio ns at the MySQL web site. Conditionals No w that yo u kno w abo ut aggregates and functio ns, yo u're able to answer so me interesting questio ns! Suppo se yo ur bo ss has a new invento ry pro blem fo r yo u to so lve. If there are less than 10 pro ducts in the sto re, she wants the sto re manager to reo rder. If there are between 10 and 50 pro ducts, the invento ry level is fine. If there are 50 o r mo re pro ducts, the manager needs to send the extra sto ck to the wareho use. Ho w do we query the database to find the details abo ut the invento ry? One way is to use a CASE statement. Type the fo llo wing at the MySQL pro mpt: mysql> SELECT P.ProductCode, P.Title, I.QuantityInStock as Qty, -> CASE WHEN I.QuantityInStock < 10 THEN 'Reorder' -> WHEN I.QuantityInStock >= 10 AND I.QuantityInStock < 50 THEN 'In Stock' -> WHEN I.QuantityInStock >= 50 THEN 'Extra to Warehouse' -> END as Action -> FROM Products as P -> LEFT JOIN Inventory as I on (P.ProductCode = I.ProductCode); +--------------+------------------------------------+------+--------------------+ | ProductCode | Title | Qty | Action | +--------------+------------------------------------+------+--------------------+ | artofsql | The Art of SQL | 52 | Extra to Warehouse | | databaseid | Database in Depth | 0 | Reorder | | mysqlspp | MySQL Stored Procedure Programming | 5 | Reorder | | relationaldb | The Relational Database Dictionary | NULL | NULL | | sqlhks | SQL Hacks | 32 | In Stock | | sqltuning | SQL Tuning | 105 | Extra to Warehouse | +--------------+------------------------------------+------+--------------------+ 6 rows in set (0.01 sec) OBSERVE: mysql> -> -> -> -> -> -> SELECT P.ProductCode, P.Title, I.QuantityInStock as Qty, CASE WHEN I.QuantityInStock < 10 THEN 'Reorder' WHEN I.QuantityInStock >= 10 AND I.QuantityInStock < 50 THEN 'In Stock' WHEN I.QuantityInStock >= 50 THEN 'Extra to warehouse' END as Action FROM Products as P LEFT JOIN Inventory as I on (P.ProductCode = I.ProductCode); CASE statements have two parts—co m pariso ns and re sult s. Co m pariso ns are checked in o rder. As so o n as a TRUE co mpariso n is fo und, the co rrespo nding re sult is returned. This is almo st the result we are lo o king fo r; ho wever, that NULL fo r "The Relatio nal Database Dictio nary" is tro ubling. Since we have never had invento ry fo r that bo o k, we sho uld set the actio n to be "Place Initial Order." But remember, we're dealing with NULLs so we have to be careful. Type the fo llo wing at the MySQL pro mpt: mysql> SELECT P.ProductCode, P.Title, IFNULL(I.QuantityInStock, 0) as Qty, -> CASE WHEN I.QuantityInStock IS NULL THEN 'Place Initial Order' -> WHEN I.QuantityInStock < 10 THEN 'Reorder' -> WHEN I.QuantityInStock >= 10 AND I.QuantityInStock < 50 THEN 'In Stock' -> WHEN I.QuantityInStock >= 50 THEN 'Extra to warehouse' -> END as Action -> FROM Products as P -> LEFT JOIN Inventory as I on (P.ProductCode = I.ProductCode); +--------------+------------------------------------+-----+---------------------+ | ProductCode | Title | Qty | Action | +--------------+------------------------------------+-----+---------------------+ | artofsql | The Art of SQL | 52 | Extra to warehouse | | databaseid | Database in Depth | 0 | Reorder | | mysqlspp | MySQL Stored Procedure Programming | 5 | Reorder | | relationaldb | The Relational Database Dictionary | 0 | Place Initial Order | | sqlhks | SQL Hacks | 32 | In Stock | | sqltuning | SQL Tuning | 105 | Extra to warehouse | +--------------+------------------------------------+-----+---------------------+ 6 rows in set (0.00 sec) OBSERVE: mysql> SELECT P.ProductCode, P.Title, IFNULL(I.QuantityInStock, 0) as Qty, -> CASE WHEN I.QuantityInStock IS NULL THEN 'Place Initial Order' We used the IFNULL co nditio nal to check the QuantityInSto ck co lumn. NULLs in that co lumn are replaced by zero s (0 ). We also added a co mpariso n to the CASE statement—I.Quant it yInSt o ck IS NULL—to display the actio n "Place Initial Order." In this lesso n, yo u learned ho w to co mbine data fro m yo ur co lumns in meaningful ways to create new co lumns o f data and summaries o f ro ws. In the next lesso n, yo u'll learn o ne way to sto re yo ur new queries in the database fo r future use. See yo u then! Copyright © 1998-2014 O'Reilly Media, Inc. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License. See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information. Subqueries and Views In the past few lesso ns, we've learned mo re co mplex ways to query o ur databases. In this lesso n we'll examine o ne mo re way to query o ur databases, as well as a way to save o ur co mplex queries. Querying Queries Yo ur small bo o k sto re do esn't have a lo t o f sto rage ro o m. Yo u o ccasio nally need to query the database to find o ut which pro ducts yo u have the highest quantity o f in invento ry. Remember when we wro te a query to return the invento ry levels fo r each pro duct in o ur catalo g? Let's try it again, just in case yo u fo rgo t. Type the fo llo wing at the MySQL pro mpt: mysql> SELECT P.ProductCode, I.QuantityInStock as Qty, P.Title, P.Price -> FROM Products as P -> LEFT JOIN Inventory as I on (P.ProductCode = I.ProductCode); +--------------+------+------------------------------------+-------+ | ProductCode | Qty | Title | Price | +--------------+------+------------------------------------+-------+ | artofsql | 52 | The Art of SQL | 44.99 | | databaseid | 0 | Database in Depth | 29.95 | | mysqlspp | 5 | MySQL Stored Procedure Programming | 44.99 | | relationaldb | NULL | The Relational Database Dictionary | 14.99 | | sqlhks | 32 | SQL Hacks | 29.99 | | sqltuning | 105 | SQL Tuning | 39.95 | +--------------+------+------------------------------------+-------+ 6 rows in set (0.00 sec) mysql> Yo u co uld scan all o f the returned items to find the o ne with the largest quantity. But it wo uld be even better to return a single ro w. We learned earlier abo ut aggregate functio ns such as MAX. Let's try using it to return the desired result. Type the fo llo wing at the MySQL pro mpt: mysql> SELECT P.ProductCode, MAX(I.QuantityInStock) as Qty, P.Title, P.Price -> FROM Products as P -> LEFT JOIN Inventory as I on (P.ProductCode = I.ProductCode) -> GROUP BY I.ProductCode, P.Title, P.Price; +-------------+------+------------------------------------+-------+ | ProductCode | Qty | Title | Price | +-------------+------+------------------------------------+-------+ | artofsql | 52 | The Art of SQL | 44.99 | | databaseid | 0 | Database in Depth | 29.95 | | mysqlspp | 5 | MySQL Stored Procedure Programming | 44.99 | | relationaldb| NULL | The Relational Database Dictionary | 14.99 | | sqlhks | 32 | SQL Hacks | 29.99 | | sqltuning | 105 | SQL Tuning | 39.95 | +-------------+------+------------------------------------+-------+ 6 rows in set (0.00 sec) mysql> OBSERVE: mysql> -> -> -> SELECT P.ProductCode, MAX(I.QuantityInStock) as Qty, P.Title, P.Price FROM Products as P LEFT JOIN Inventory as I on (P.ProductCode = I.ProductCode) GROUP BY I.ProductCode, P.Title, P.Price; Since we're using the MAX aggregate with no n-aggregate co lumns, we need to use a co rrespo nding GROUP BY clause. In English, the GROUP BY wo uld ro ughly translate to "fo r each Pro ductCo de, Title, and Price co mbinatio n GROUP, sho w me the MAX(Price)." The o rder may no t be the same, but the same six ro ws are returned. And as it turns o ut we answered a different questio n—fo r each ro w in Pro ducts, we returned the co rrespo nding MAX quantity fro m Invento ry. We really just wanted the single pro duct with the maximum quantity in Invento ry. In o rder to return this info rmatio n, let's try to restrict o ur query with a WHERE clause: Type the fo llo wing at the MySQL pro mpt: mysql> SELECT P.ProductCode, I.QuantityInStock as Qty, P.Title, P.Price -> FROM Products as P -> LEFT JOIN Inventory as I on (P.ProductCode = I.ProductCode) -> WHERE I.QuantityInStock = MAX(I.QuantityInStock); ERROR 1111 (HY000): Invalid use of group function mysql> This query isn't quite right either. Fear no t, there is ho pe! We can co rrect this erro r if we use a subquery. If yo u think abo ut tables and query results, yo u'll realize that they are essentially the same. Bo th co ntain ro ws and co lumns o f data. It wo uld seem lo gical to be able to query the results fro m a query. And as the pro gramming go ds wo uld have it, yo u can! Yo u do this using a subquery. In o rder to return the pro duct with the greatest quantity, let's query the results o f a query. But befo re we do that, let's make sure that the subquery is co rrect. First, find the maximum QuantityInSto ck in Invento ry. Type the fo llo wing at the MySQL pro mpt: mysql> SELECT MAX(QuantityInStock) FROM Inventory; +----------------------+ | MAX(QuantityInStock) | +----------------------+ | 105 | +----------------------+ 1 row in set (0.00 sec) mysql> That lo o ks go o d! No w that we kno w the MAX(Quant it yinSt o ck) fro m Invento ry, the query co uld essentially be rewritten like so : OBSERVE: SELECT P.ProductCode, I.QuantityInStock as Qty, P.Title, P.Price FROM Products as P LEFT JOIN Inventory as I on (P.ProductCode = I.ProductCode) WHERE I.QuantityInStock = 105; While this query might return the desired result no w, o n a live system it wo n't wo rk reliably. After all, the QuantityInSto ck might change befo re we get a chance to run the query. Instead let's use a subquery. Type the fo llo wing query into the edito r: Type the fo llo wing at the MySQL pro mpt: mysql> SELECT P.ProductCode, I.QuantityInStock as Qty, P.Title, P.Price -> FROM Products as P -> LEFT JOIN Inventory as I on (P.ProductCode = I.ProductCode) -> WHERE I.QuantityInStock = (SELECT MAX(QuantityInStock) FROM Inventory); +-------------+------+------------+-------+ | ProductCode | Qty | Title | Price | +-------------+------+------------+-------+ | sqltuning | 105 | SQL Tuning | 39.95 | +-------------+------+------------+-------+ 1 row in set (0.02 sec) mysql> There yo u have it! Exactly the results we wanted. Views We've learned a lo t o f co mplex ways to write queries. It can be cumberso me to rewrite these queries. Since query results lo o k just like a table, wo uldn't it be nice to be able to sto re a query definitio n in the database, and access it just like a table? Views so lve o ur pro blem. Views are a great way to tuck away co mplex query lo gic into the database. Database Administrato rs lo ve views because they can be used to hide sensitive co lumns o f data (such as so cial security numbers) fro m certain users. Creating a View Remember when yo u used a jo in to query the pro ducts and invento ry tables? Let's run that query again. Type the fo llo wing at the MySQL pro mpt: mysql> SELECT P.ProductCode, P.Title, P.Price, I.QuantityInStock as Qty -> FROM Products as P -> LEFT JOIN Inventory as I on (P.ProductCode = I.ProductCode); +--------------+------------------------------------+-------+------+ | ProductCode | Title | Price | Qty | +--------------+------------------------------------+-------+------+ | artofsql | The Art of SQL | 44.99 | 52 | | databaseid | Database in Depth | 29.95 | 0 | | mysqlspp | MySQL Stored Procedure Programming | 44.99 | 5 | | relationaldb | The Relational Database Dictionary | 14.99 | NULL | | sqlhks | SQL Hacks | 29.99 | 32 | | sqltuning | SQL Tuning | 39.95 | 105 | +--------------+------------------------------------+-------+------+ 6 rows in set (0.00 sec) mysql> (Of co urse, if the data in yo ur tables has changed, yo ur results will be different.) This data is very useful, but typing that query is cumberso me. We'll sto re the query in a new view called ProdInventory. The syntax fo r creating a view is pretty straightfo rward: CREAT E VIEW name AS query. Type the fo llo wing at the MySQL pro mpt: mysql> CREATE VIEW ProdInventory AS -> SELECT P.ProductCode, P.Title, P.Price, I.QuantityInStock as Qty -> from Products as P -> LEFT JOIN Inventory as I on (P.ProductCode = I.ProductCode); Query OK, 0 rows affected (0.07 sec) mysql> That's it! Yo u created the view. Since a view is mo re o r less like a table, yo u can query it like a table. Type the fo llo wing at the MySQL pro mpt: mysql> SELECT * FROM ProdInventory; +--------------+------------------------------------+-------+------+ | ProductCode | Title | Price | Qty | +--------------+------------------------------------+-------+------+ | artofsql | The Art of SQL | 44.99 | 52 | | databaseid | Database in Depth | 29.95 | 0 | | mysqlspp | MySQL Stored Procedure Programming | 44.99 | 5 | | relationaldb | The Relational Database Dictionary | 14.99 | NULL | | sqlhks | SQL Hacks | 29.99 | 32 | | sqltuning | SQL Tuning | 39.95 | 105 | +--------------+------------------------------------+-------+------+ 6 rows in set (0.00 sec) mysql> Restrictions on Views Views are nearly identical to tables, ho wever, there are so me impo rtant differences. First, yo u canno t always INSERT into a view. If yo ur view co ntains jo ins, yo u wo n't be able to insert data into all o f the jo ined tables. Yo u may be able to insert into o ne o f the tables, but it's usually best to avo id INSERTs to views. Seco nd, views are sensitive to changes in the database. Fo r example, in the Pro dInvento ry view, if the Title co lumn is changed to "Pro ductTitle," the view will give an erro r. Dropping a View The view we created befo re is nice; ho wever, the name is a little co nfusing. Instead o f calling it Pro dInve nt o ry (which might be interpreted as Pro duct io n Inve nt o ry), let's call it Pro duct Inve nt o ry. Remo ving a view fro m the database is similar to remo ving a table—yo u use the DROP VIEW IF EXIST S co mmand. Type the fo llo wing at the MySQL pro mpt: mysql> DROP VIEW IF EXISTS ProdInventory; Query OK, 0 rows affected (0.00 sec) mysql> We are no w free to add o ur view called Pro duct Inve nt o ry. Type the fo llo wing at the MySQL pro mpt: mysql> CREATE VIEW ProductInventory AS SELECT P.ProductCode, P.Title, P.Price, I.QuantityInStock as Qty FROM Products as P LEFT JOIN Inventory as I on (P.ProductCode = I.ProductCode); Query OK, 0 rows affected (0.00 sec) mysql> No w yo u've learned ano ther way to query yo ur data. Yo u've also learned abo ut the po wer o f views—ano ther way the database wo rks fo r yo u, instead o f yo u wo rking fo r yo ur database. In the next lesso n we'll expand o n that idea and learn ho w to sto re co mplex lo gic in the database. Stay tuned! Copyright © 1998-2014 O'Reilly Media, Inc. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License. See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information. Stored Procedures In the last lesso n we learned ho w to use a view to save co mplex query lo gic in the database. While views are really useful, they can't be used to sto re a sequence o f steps that so metimes need to be perfo rmed with data. In this lesso n yo u'll learn ho w to use stored procedures. Using Stored Procedures Motivations Sto red pro cedures are like functio ns fo r the database. They have a set o f parameters, perfo rm a set o f tasks, and may return a set o f results. Co de reuse is impo rtant, and sto red pro cedures pro vide a kind o f co de reuse that is similar to what functio ns and classes do in o ther languages. Techno lo gies (especially web techno lo gies) co me and go , but data do esn't change much. The pro cess o f tracking sto re invento ry is essentially the same to day as it was in 19 9 8 , 19 8 8 , o r 19 78 . But the techno lo gy has changed pretty dramatically—invento ry tracking was do ne o n paper in 19 78 , then maybe o n a greenscreen co mputer in 19 8 8 , and then in a Windo ws applicatio n in 19 9 8 , but to day, invento ry tracking is likely to be do ne using a web bro wser and a Windo ws applicatio n . Sto red pro cedures created back in 19 8 8 wo uld still functio n to day, twenty-plus years and three user interfaces later because data itself hasn't change much, but the fro nt-end techno lo gy sure did! Sto red pro cedures, in additio n to helping us track data, are also used to secure data. In business, fo r example, access to database tables co uld be disallo wed specifically to make sure that access is gained o nly thro ugh a sto red pro cedures. Since the database user is kno wn to the server, sensitive info rmatio n (such as ho urly salary rates) wo uldn't be returned to users o utside o f the human reso urces staff. This security applies to all access thro ugh a Windo ws applicatio n, thro ugh a web site, o r thro ugh co mmand-line to o ls. Sto red pro cedures have yet ano ther advantage: speed. By keeping lo gic next to the data, database servers do n't have to send massive amo unts o f info rmatio n to applicatio ns (and back) fo r pro cessing. This might no t matter fo r small databases with o nly a few hundred ro ws, but it is critical fo r databases that co ntain millio ns o r billio ns o f ro ws. Creating Stored Procedures Setup Befo re we can create a pro cedure we'll have to make a small change to o ur MySQL enviro nment. MySQL usually expects a semico lo n at the end o f a statement. Since sto red pro cedures can encapsulate many statements, we'll have to tell MySQL to use so mething else to separate statements as we enter them. To do this we'll use the special de lim it e r keywo rd. Type the fo llo wing at the MySQL pro mpt: mysql> DELIMITER // mysql> This co mmand do esn't return anything, but yo u'll no tice a difference after yo u run a query. Type the fo llo wing at the MySQL pro mpt: mysql> SELECT ProductCode,Title FROM Products; -> To submit the query to the server, yo u need to enter the delimiter, //. Once yo u do , yo ur query will be evaluated, and yo u'll see results. Type the fo llo wing at the MySQL pro mpt: -> // +--------------+------------------------------------+ | ProductCode | Title | +--------------+------------------------------------+ | artofsql | The Art of SQL | | databaseid | Database in Depth | | mysqlspp | MySQL Stored Procedure Programming | | relationaldb | The Relational Database Dictionary | | sqlhks | SQL Hacks | | sqltuning | SQL Tuning | +--------------+------------------------------------+ 6 rows in set (0.00 sec) mysql> Duplicating our View A perfectly valid use o f a sto red pro cedure is to sto re a query fo r repeated use. A view co uld be used fo r this use as well, ho wever mo st databases can o ptimize sto red pro cedures in ways that are no t po ssible with view o r ad-ho c queries. Let's take o ur Pro ductInvento ry view and turn it into a basic sto red pro cedure. Belo w is the query behind that view. Try it o ut to refresh yo ur memo ry. INTERACTIVE SESSION: mysql> SELECT P.ProductCode, P.Title, P.Price, I.QuantityInStock as Qty -> FROM Products as P -> LEFT JOIN Inventory as I on (P.ProductCode = I.ProductCode)// +--------------+------------------------------------+-------+------+ | ProductCode | Title | Price | Qty | +--------------+------------------------------------+-------+------+ | artofsql | The Art of SQL | 44.99 | 52 | | databaseid | Database in Depth | 29.95 | 0 | | mysqlspp | MySQL Stored Procedure Programming | 44.99 | 5 | | relationaldb | The Relational Database Dictionary | 14.99 | NULL | | sqlhks | SQL Hacks | 29.99 | 32 | | sqltuning | SQL Tuning | 39.95 | 105 | +--------------+------------------------------------+-------+------+ 6 rows in set (0.00 sec) mysql> Let's dive right in and create o ur pro cedure. We'll do so by using CREATE PROCEDURE. Type the fo llo wing at the MySQL pro mpt: mysql> CREATE PROCEDURE CurrentProductInventory () -> BEGIN -> SELECT P.ProductCode, P.Title, P.Price, I.QuantityInStock as Qty -> FROM Products AS P -> LEFT JOIN Inventory as I on (P.ProductCode = I.ProductCode); -> END; -> // Query OK, 0 rows affected (0.00 sec) mysql> OBSERVE: mysql> -> -> -> -> -> -> CREATE PROCEDURE CurrentProductInventory () BEGIN SELECT P.ProductCode, P.Title, P.Price, I.QuantityInStock as Qty FROM Products AS P LEFT JOIN Inventory as I on (P.ProductCode = I.ProductCode); END; // First we used the CREAT E PROCEDURE keywo rd, fo llo wed by the name o f o ur pro cedure —Curre nt Pro duct Inve nt o ry. A pair o f empty parentheses () tells MySQL that o ur pro cedure wo n't have any parameters. Next, the BEGIN keywo rd tells MySQL that we are go ing to write o ne o r mo re statements that sho uld be treated as a blo ck. The END; keywo rd marks the end o f that blo ck. Finally, we end o ur entry with the // delimiter. No w let's run the pro cedure, using the CALL keywo rd. We still need to type in the delimiters, since we haven't reset that MySQL o ptio n. Type the fo llo wing at the MySQL pro mpt: mysql> CALL CurrentProductInventory (); -> // +--------------+------------------------------------+-------+------+ | ProductCode | Title | Price | Qty | +--------------+------------------------------------+-------+------+ | artofsql | The Art of SQL | 44.99 | 52 | | databaseid | Database in Depth | 29.95 | 0 | | mysqlspp | MySQL Stored Procedure Programming | 44.99 | 5 | | relationaldb | The Relational Database Dictionary | 14.99 | NULL | | sqlhks | SQL Hacks | 29.99 | 32 | | sqltuning | SQL Tuning | 39.95 | 105 | +--------------+------------------------------------+-------+------+ 6 rows in set (0.00 sec) Query OK, 0 rows affected (0.00 sec) mysql> Make sure yo u type the pro cedure name—Curre nt Pro duct Inve nt o ry—co rrectly, and that yo u type in an empty set o f parentheses () to tell MySQL that o ur pro cedure do esn't take any parameters. Parameters Using a sto red pro cedure to return results like a view can be helpful; ho wever, sto red pro cedures are much mo re po werful if they accept parameters. In the first few lesso ns, we designed a sto re structure to keep track o f pro ducts and invento ry in two tables, then we entered data into tho se two tables manually. While this pro cess will wo rk, it's clunky and erro r-pro ne. Instead o f adding pro ducts to the system manually into two tables, we co uld use a sto red pro cedure. Adding a pro duct requires inserting data into two tables—Pro ducts and Invento ry. Do ne separately, the queries lo o k like this: OBSERVE: INSERT INTO Products (ProductCode, Title, Category, Description, Price) VALUES ('mysqlian', 'MySQL in a Nutshell', 'MySQL', 'MySQL in a Nutshell covers all MySQL functions, as well as MySQL administration.', 39.95); INSERT INTO Inventory (ProductCode, QuantityInStock) VALUES ('mysqlian', 52); In o rder to add a pro duct, we need to kno w the fo llo wing info rmatio n: Pro duct Co de Title Catego ry Descriptio n Price Quantity Quantity These bits o f info rmatio n will beco me parameters. Here's a skeleto n fo r o ur sto red pro cedure. OBSERVE: CREATE PROCEDURE CreateProduct ( ProductCode varchar(20), Title varchar(50), Category varchar(30), Description text, Price decimal (9,2), Quantity int ) BEGIN END; // We have each o f o ur param e t e rs, fo llo wed by a dat a t ype that matches o ur table definitio n. No w let's co mplete this pro cedure by filling in o ur two queries. Type the fo llo wing at the MySQL pro mpt: mysql> CREATE PROCEDURE CreateProduct ( -> ProductCode varchar(20), -> Title varchar(50), -> Category varchar(30), -> Description text, -> Price decimal (9,2), -> Quantity int -> ) -> BEGIN -> INSERT INTO Products (ProductCode, Title, Category, Description, Price) -> VALUES (ProductCode, Title, Category, Description, Price); -> INSERT INTO Inventory (ProductCode, QuantityInStock) -> VALUES (ProductCode, Quantity); -> END; -> // Query OK, 0 rows affected (0.00 sec) mysql> Calling this pro cedure is similar to calling the last o ne. Try it witho ut any parameters: Type the fo llo wing at the MySQL pro mpt: mysql> CALL CreateProduct (); -> // ERROR 1318 (42000): Incorrect number of arguments for PROCEDURE certjosh.CreateP roduct; expected 6, got 0 mysql> This pro cedure has six parameters, and requires all six. Note We just created the pro cedure, so we kno w the names and data types o f the parameters fo r o ur pro cedure. If yo u need to check the definitio n o f a pro cedure, yo u can do so by using sho w cre at e pro ce dure procedure name. Let's call the pro cedure with parameters this time. The example belo w has o ne parameter per line to facilitate o ur discussio n, but yo u can enter all parameters o n o ne line if yo u like. Type the fo llo wing at the MySQL pro mpt: mysql> CALL CreateProduct ( -> "mysqlian", -> "MySQL in a Nutshell", -> "MySQL", -> "MySQL in a Nutshell covers all MySQL functions, as well as MySQL admin istration.", -> 39.95, -> 52 -> ); -> // Query OK, 1 row affected (0.00 sec) mysql> But wait ! Didn't the sto red pro cedure create two ro ws—o ne in Pro duct and o ne in Invento ry? Check by running the previo us Curre nt Pro duct Inve nt o ry sto red pro cedure. Type the fo llo wing at the MySQL pro mpt: mysql> CALL CurrentProductInventory (); -> // +--------------+------------------------------------+-------+------+ | ProductCode | Title | Price | Qty | +--------------+------------------------------------+-------+------+ | artofsql | The Art of SQL | 44.99 | 52 | | databaseid | Database in Depth | 29.95 | 0 | | mysqlian | MySQL in a Nutshell | 39.95 | 52 | | mysqlspp | MySQL Stored Procedure Programming | 44.99 | 5 | | relationaldb | The Relational Database Dictionary | 14.99 | NULL | | sqlhks | SQL Hacks | 29.99 | 32 | | sqltuning | SQL Tuning | 39.95 | 105 | +--------------+------------------------------------+-------+------+ 7 rows in set (0.00 sec) Query OK, 0 rows affected (0.00 sec) mysql> It seems that two ro ws were inserted after all. MySQL's respo nses can so metimes be misleading. Variables Mo st pro gramming languages have so me co ncept o f a variable; SQL is no different. Variables can be very useful in sto red pro cedures, where they can be used to sto re intermediate results. Variables in MySQL are not case-sensitive, so a variable named m yVariable is the same as o ne named MyVARIABLE. Our Inve nt o ry table currently has two co lumns: Pro ductCo de and QuantityInSto ck. Suppo se yo ur manager wants to update invento ry by title instead o f by Pro ductCo de. We co uld make a sto red pro cedure to make this task easier. First, let's write so me co de to capture a Pro ductCo de fo r a pro duct. Type the fo llo wing at the MySQL pro mpt: mysql> CREATE PROCEDURE GetProductCode ( -> product_title varchar(50) -> ) -> BEGIN -> DECLARE product_code varchar(20); -> -> SELECT ProductCode into product_code -> FROM Products -> WHERE Title = product_title; -> -> SELECT product_code as ProductCode; -> END; -> // Query OK, 0 rows affected (0.00 sec) mysql> OBSERVE: ... -> -> -> -> -> -> -> DECLARE product_code varchar(20); SELECT ProductCode into product_code FROM Products WHERE Title = product_title; SELECT product_code as ProductCode; ... The DECLARE statement in o ur pro cedure tells MySQL that we are using a variable named pro duct _co de , who se type is varchar(20 ). Later, we use a SELECT statement to view the results. Let's try the new pro cedure. We'll lo o k up the title SQL Hacks. Type the fo llo wing at the MySQL pro mpt: mysql> call GetProductCode('SQL Hacks'); -> // +-------------+ | ProductCode | +-------------+ | sqlhks | +-------------+ 1 row in set (0.00 sec) Query OK, 0 rows affected (0.00 sec) mysql> Lo o king go o d! The pro duct co de is co rrect, so let's rewrite o ur pro cedure to accept o ne new parameter called Ne wQuant it yInSt o ck and update o ur invento ry table. Remo ve o ur o ld pro cedure befo re we co ntinue. Type the fo llo wing at the MySQL pro mpt: mysql> DROP PROCEDURE IF EXISTS GetProductCode; -> // Query OK, 0 rows affected (0.00 sec) mysql> No w, create the new pro cedure. Type the fo llo wing at the MySQL pro mpt: mysql> CREATE PROCEDURE UpdateInventory( -> product_title varchar(50), -> NewQuantityInStock int -> ) -> BEGIN -> DECLARE product_code varchar(20); -> -> SELECT ProductCode into product_code -> FROM Products -> WHERE Title = product_title; -> -> UPDATE Inventory SET QuantityInStock=NewQuantityInStock -> WHERE ProductCode = product_code; -> END; -> // Query OK, 0 rows affected (0.00 sec) mysql> There are two new bits: the Ne wQuant it yInSt o ck parameter, and the UPDAT E statement that sets the new quantity in sto ck. Befo re we try the pro cedure, let's manually reset the QuantityInSto ck fo r "sqlhks." Type the fo llo wing at the MySQL pro mpt: mysql> UPDATE Inventory SET QuantityInStock=32 -> WHERE ProductCode = 'sqlhks'; -> // Query OK, 0 rows affected (0.01 sec) Rows matched: 1 Changed: 0 Warnings: 0 mysql> With that do ne, we can test o ur pro cedure. Let's try to set o ur invento ry to 9 9 . Type the fo llo wing at the MySQL pro mpt: mysql> call UpdateInventory('SQL Hacks',99); -> // Query OK, 1 row affected (0.01 sec) mysql> Was the invento ry updated? Let's check it o ut. Type the fo llo wing at the MySQL pro mpt: mysql> SELECT * FROM Inventory WHERE ProductCode='sqlhks'; -> // +-------------+-----------------+ | ProductCode | QuantityInStock | +-------------+-----------------+ | sqlhks | 99 | +-------------+-----------------+ 1 row in set (0.00 sec) mysql> Sure eno ugh, it wo rked perfectly! Lo o ks go o d! Yo u may be asking yo urself, "what happens if there are two bo o ks with the same title?" Since the pro duct title isn't the primary key, that co uld happen. Add a pro duct to yo ur invento ry, and run Updat e Inve nt o ry to see what happens, and then think abo ut ho w yo u co uld handle this pro blem. Yo u've learned a lo t in this lesso n! Yo u're o n yo ur way to creating po werful and reliable database applicatio ns. In the next lesso n, we'll learn abo ut two co ncepts impo rtant to many end users: ho w to PIVOT and UNPIVOT yo ur data. Copyright © 1998-2014 O'Reilly Media, Inc. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License. See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information. PIVOT and UNPIVOT Welco me back! In the last few lesso ns we've been lo o king into the different ways we can write queries and pro cedures to interact with o ur data. In this lesso n we'll learn abo ut two data manipulatio n techniques—pivot and unpivot. PIVOT ing Data Pivo ting data is the pro cess o f aggregating o r mo ving ro ws o f data into co lumns. Suppo se o ur sto re keeps track o f sales data. The bo ss o nly cares abo ut Unit s So ld, and he really wants to kno w ho w many units were so ld in the No rt h and ho w many were so ld in the So ut h. Business users and pro grammers o ften view data in drastically different ways. Pro grammers might think in ro ws and co lumns o f data, such as the fo llo wing table with sales data by regio n and date: Re gio n Quart e r Unit s So ld No rth 20 0 7-0 3-31 15,0 8 9 No rth 20 0 7-0 6 -30 18 ,79 5 No rth 20 0 7-0 9 -30 19 ,0 6 5 No rth 20 0 7-12-31 So uth 20 0 7-0 3-31 20 ,0 15 So uth 20 0 7-0 6 -30 19 ,8 0 6 So uth 20 0 7-0 9 -30 21,0 53 So uth 20 0 7-12-31 19 ,9 8 7 23,0 6 8 Sho wing the data in this way is useful, especially to pro grammers, but many business users may want to co mpare the units so ld by regio n and by date. It's difficult to lo o k at the previo us table and co mpare seco nd quarter 20 0 7 sales fo r the No rth and So uth regio ns. Business users wo uld pro bably prefer to see the data this way: Re gio n Unit s So ld Unit s So ld Unit s So ld Unit s So ld 20 0 7 -Q1 20 0 7 -Q2 20 0 7 -Q3 20 0 7 -Q4 No rth 15,0 8 9 18 ,79 5 19 ,0 6 5 19 ,9 8 7 So uth 20 ,0 15 19 ,8 0 6 21,0 53 23,0 6 8 This representatio n sho ws exactly the same data, but no w it's easy fo r business users to see that fo r 20 0 7-Q2 the So uth o utso ld the No rth by 1,0 11 units. Graphically, a pivo t may lo o k like this: Majo r databases such as Oracle and SQL Server no w have PIVOT keywo rds added to their SQL dialects. While MySQL do esn't currently have that keywo rd, yo u can still pivo t yo ur data witho ut much tro uble. Let's start by adding a simple table fo r o ur demo nstratio ns. We'll use the same data and same basic structure as the first table. Note If yo u haven't clo sed the terminal sessio n since the last lesso n, set yo ur delimiter back fro m "//" to ";". Type the fo llo wing at the MySQL pro mpt: mysql> CREATE TABLE SalesAnalysis -> ( -> Region varchar(10) NOT NULL, -> Quarter date NOT NULL, -> UnitsSold integer NOT NULL -> ) ENGINE=INNODB; Query OK, 0 rows affected (0.01 sec) mysql> Once yo u have the table created, po pulate it with o ur sample data. T ip Remember yo u can use the Up arro w key to repeat a co mmand in mysql and then edit the co mmand. Fo r example, after yo u enter the first co mmand belo w, press the up arro w key and then edit the Quarter date and the UnitsSo ld integer to create the next co mmand. Type the fo llo wing at the MySQL pro mpt: mysql> INSERT INTO SalesAnalysis values ('NORTH', '2007-03-31',15089); Query OK, 0 rows affected (0.01 sec) mysql> INSERT INTO SalesAnalysis VALUES ('NORTH', '2007-06-30',18795); Query OK, 0 rows affected (0.01 sec) mysql> INSERT INTO SalesAnalysis VALUES ('NORTH', '2007-09-30',19065); Query OK, 0 rows affected (0.01 sec) mysql> INSERT INTO SalesAnalysis VALUES ('NORTH', '2007-12-31',19987); Query OK, 0 rows affected (0.01 sec) mysql> INSERT INTO SalesAnalysis VALUES ('SOUTH', '2007-03-31',20015); Query OK, 0 rows affected (0.01 sec) mysql> INSERT INTO SalesAnalysis VALUES ('SOUTH', '2007-06-30',19806); Query OK, 0 rows affected (0.01 sec) mysql> INSERT INTO SalesAnalysis VALUES ('SOUTH', '2007-09-30',21053); Query OK, 0 rows affected (0.01 sec) mysql> INSERT INTO SalesAnalysis VALUES ('SOUTH', '2007-12-31',23068); Query OK, 0 rows affected (0.01 sec) mysql> Check that yo u entered everything co rrectly: Type the fo llo wing at the MySQL pro mpt: mysql> SELECT * FROM SalesAnalysis; +--------+------------+-----------+ | Region | Quarter | UnitsSold | +--------+------------+-----------+ | NORTH | 2007-03-31 | 15089 | | NORTH | 2007-06-30 | 18795 | | NORTH | 2007-09-30 | 19065 | | NORTH | 2007-12-31 | 19987 | | SOUTH | 2007-03-31 | 20015 | | SOUTH | 2007-06-30 | 19806 | | SOUTH | 2007-09-30 | 21053 | | SOUTH | 2007-12-31 | 23068 | +--------+------------+-----------+ 8 rows in set (0.00 sec) mysql> No w that we have so me sample data, ho w do we go abo ut pivo ting the ro ws into co lumns? If yo u recall fro m the previo us lesso ns, we've already learned ho w to use the CASE statement and aggregates. We'll use bo th o f tho se features to co me up with o ur PIVOT. The co lumn we want to pivo t is Unit sSo ld, and we want to pivo t that co lumn by the Quart e r co lumn. We'll add fo ur new co lumns named 20 0 7 -Q1, 20 0 7 -Q2, 20 0 7 -Q3, and 20 0 7 -Q4 , and use a CASE statement to allo cate UnitsSo ld to each o f tho se new co lumns. Let's try it! Type the fo llo wing at the MySQL pro mpt: mysql> SELECT Region, -> CASE WHEN Quarter='2007-03-31' THEN UnitsSold -> CASE WHEN Quarter='2007-06-30' THEN UnitsSold -> CASE WHEN Quarter='2007-09-30' THEN UnitsSold -> CASE WHEN Quarter='2007-12-31' THEN UnitsSold -> FROM SalesAnalysis; +--------+---------+---------+---------+---------+ | Region | 2007-Q1 | 2007-Q2 | 2007-Q3 | 2007-Q4 | +--------+---------+---------+---------+---------+ | NORTH | 15089 | NULL | NULL | NULL | | NORTH | NULL | 18795 | NULL | NULL | | NORTH | NULL | NULL | 19065 | NULL | | NORTH | NULL | NULL | NULL | 19987 | | SOUTH | 20015 | NULL | NULL | NULL | | SOUTH | NULL | 19806 | NULL | NULL | | SOUTH | NULL | NULL | 21053 | NULL | | SOUTH | NULL | NULL | NULL | 23068 | +--------+---------+---------+---------+---------+ 8 rows in set (0.00 sec) END END END END AS AS AS AS '2007-Q1', '2007-Q2', '2007-Q3', '2007-Q4' END END END END AS AS AS AS '2007-Q1', '2007-Q2', '2007-Q3', '2007-Q4' mysql> Let's lo o k a little clo ser. OBSERVE: mysql> -> -> -> -> -> SELECT Region, CASE WHEN Quarter='2007-03-31' CASE WHEN Quarter='2007-06-30' CASE WHEN Quarter='2007-09-30' CASE WHEN Quarter='2007-12-31' FROM SalesAnalysis; THEN THEN THEN THEN UnitsSold UnitsSold UnitsSold UnitsSold Here, the UnitsSo ld in the f irst quart e r are entered into the new '20 0 7 -Q1' co lumn, the UnitsSo ld in the se co nd quart e r are put into the new '20 0 7 -Q2' co lumn, and so o n. But the results are no t exactly co rrect—they still co ntain as many ro ws as the o riginal table, with a bunch o f NULL values in between the useful values. Ho w can we co llapse this into meaningful data? We'll use an aggregate! In this example we can use SUM to add up o ur new co lumns, gro uped by the regio n. Fo r go o d practice, we sho uld also add an ELSE clause to the CASE statement. Instead o f using NULL, we'll use zero . Let's try o ur updated pivo t! Type the fo llo wing at the MySQL pro mpt: mysql> SELECT Region, -> SUM(CASE WHEN Quarter='2007-03-31' THEN UnitsSold -> SUM(CASE WHEN Quarter='2007-06-30' THEN UnitsSold -> SUM(CASE WHEN Quarter='2007-09-30' THEN UnitsSold -> SUM(CASE WHEN Quarter='2007-12-31' THEN UnitsSold -> FROM SalesAnalysis -> GROUP BY Region; +--------+---------+---------+---------+---------+ | Region | 2007-Q1 | 2007-Q2 | 2007-Q3 | 2007-Q4 | +--------+---------+---------+---------+---------+ | NORTH | 15089 | 18795 | 19065 | 19987 | | SOUTH | 20015 | 19806 | 21053 | 23068 | +--------+---------+---------+---------+---------+ 2 rows in set (0.00 sec) mysql> ELSE ELSE ELSE ELSE 0 0 0 0 END) END) END) END) AS AS AS AS '2007-Q1', '2007-Q2', '2007-Q3', '2007-Q4' This o ne lo o ks much better, and returns the co rrect results. Our business users will be very happy. UNPIVOT ing Data As yo u just saw, pivo ting data changes ro ws into co lumns. Unpivoting data changes co lumns into ro ws. This is very useful when yo ur business users give yo u a set o f data and ask yo u to impo rt it into a traditio nal database fo rmat. Unpivo ting lo o ks so mething like this: Note If yo u pivo t data, yo u canno t necessarily unpivo t the result to get back to the o riginal data. Remember that when yo u pivo t data, yo u aggregate ro ws into a single co lumn. It may no t be po ssible to deaggregate that co lumn back to several ro ws. In the pivo t example fro m earlier in the lesso n, we wo rked with sales data by regio n and quarter. Suppo se this data was impo rted fro m a system directly in that fo rmat. What wo uld that lo o k like? Let's save o ur previo us query as a view in o rder to o bserve this co nditio n. Type the fo llo wing at the MySQL pro mpt: mysql> CREATE VIEW SalesDataPivot AS -> SELECT Region, -> SUM(CASE WHEN Quarter='2007-03-31' -> SUM(CASE WHEN Quarter='2007-06-30' -> SUM(CASE WHEN Quarter='2007-09-30' -> SUM(CASE WHEN Quarter='2007-12-31' -> FROM SalesAnalysis -> GROUP BY Region; Query OK, 0 rows affected (0.01 sec) mysql> THEN THEN THEN THEN UnitsSold UnitsSold UnitsSold UnitsSold ELSE ELSE ELSE ELSE 0 0 0 0 END) END) END) END) AS AS AS AS '2007-Q1', '2007-Q2', '2007-Q3', '2007-Q4' Run a quick query using this new view to make sure yo u see the same results. No w that we have o ur view in place, we can co nstruct o ur query to unpivo t the data. Since MySQL do esn't have an UNPIVOT o perato r, we'll have to do it the o ld-fashio ned way by using a few queries and UNION statements. We'll write fo ur queries—o ne fo r each o f the co lumns to be unpivo ted. Then we'll add a new co lumn called Quart e r to each query. First let's try to unpivo t the first quarter o f data—'20 0 7-Q1'. WARNING Be sure to type the co rrect character fo r the co lumn 20 0 7 -Q1. MySQL requires co lumn names to be quo ted with a backwards apo stro phe (`) because the co lumn name starts with a number and co ntains a dash. Do n't co nfuse the backwards apo stro phe character with the plain apo stro phe (') character. The backwards apo stro phe key is usually lo cated near the Esc key o n yo ur keybo ard. Type the fo llo wing at the MySQL pro mpt: mysql> SELECT Region, -> '2007-03-31' AS Quarter, -> `2007-Q1` AS UnitsSold -> FROM SalesDataPivot; +--------+------------+-----------+ | Region | Quarter | UnitsSold | +--------+------------+-----------+ | NORTH | 2007-03-31 | 15089 | | SOUTH | 2007-03-31 | 20015 | +--------+------------+-----------+ 2 rows in set (0.00 sec) mysql> OBSERVE: mysql> -> -> -> SELECT Region, '2007-03-31' AS Quarter, `2007-Q1` AS UnitsSold FROM SalesDataPivot; Here, we added a new co lumn named Quart e r and renamed the co lumn `20 0 7 -Q1` "UnitsSo ld". Lo o ks great! No w we can co mbine this with three mo re queries, and a UNION statement to co llect all o f the results. Type the fo llo wing at the MySQL pro mpt: mysql> SELECT Region, '2007-03-31' AS -> FROM SalesDataPivot -> UNION -> SELECT Region, '2007-06-30' AS -> FROM SalesDataPivot -> UNION -> SELECT Region, '2007-09-30' AS -> FROM SalesDataPivot -> UNION -> SELECT Region, '2007-12-31' AS -> FROM SalesDataPivot; +--------+------------+-----------+ | Region | Quarter | UnitsSold | +--------+------------+-----------+ | NORTH | 2007-03-31 | 15089 | | SOUTH | 2007-03-31 | 20015 | | NORTH | 2007-06-30 | 18795 | | SOUTH | 2007-06-30 | 19806 | | NORTH | 2007-09-30 | 19065 | | SOUTH | 2007-09-30 | 21053 | | NORTH | 2007-12-31 | 19987 | | SOUTH | 2007-12-31 | 23068 | +--------+------------+-----------+ 8 rows in set (0.00 sec) mysql> Quarter, `2007-Q1` AS UnitsSold Quarter, `2007-Q2` AS UnitsSold Quarter, `2007-Q3` AS UnitsSold Quarter, `2007-Q4` AS UnitsSold This is exactly the same data that is sto red in the SalesAnalysis table! We did it! We successfully pivo ted the data, then unpivo ted it to its o riginal fo rm. Yo u've learned yet ano ther way to query the data in yo ur database. MySQL o ffers additio nal ways to facilitate yo ur database applicatio ns—user defined types, functio ns, and extensio ns are all ways to expand the ways yo u sto re and interact with yo ur data. See yo u in the next lesso n! Copyright © 1998-2014 O'Reilly Media, Inc. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License. See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information. Full Text We've co vered a lo t o f info rmatio n in the co urse so far, and learned many ways to sto re and interact with yo ur data. In this lesso n we'll co ver o ne mo re to o l in the SQL to o l bo x: full-text indexes. Creating Full-T ext Indexes Yo u may want to create a full-text index to enable quick searches thro ugh large amo unts o f text. Staff wo rking in a bo o ksto re are usually kno wledgeable abo ut many autho rs and to pics, but they can benefit fro m the use an efficient search to o l. We can help them by pro viding a text search o f all info rmatio n asso ciated with each bo o k including the title, autho r, bo o k descriptio n, and catego ry. Instead o f creating a co mplex search o n all o f the database fields, a full-text index lets yo u query all included fields at o nce. Note Full-text indexes are no t a replacement fo r no rmal indexes and queries. Like the name suggests, they are o nly go o d at o ne thing: searching full-text. The versio n o f MySQL we currently use has so me restrictio ns o n full-text indexes. The mo st impo rtant restrictio n is that full-text indexes can o nly be used with the MyISAM engine. Befo re we can use this index o n o ur Pro ducts table, we'll have to make sure the table type is MyISAM. MySQL versio n 5.6 .4 and later can use full-text indexes o n Inno DB tables to o . Type the fo llo wing at the MySQL pro mpt: mysql> ALTER TABLE Products ENGINE=MyISAM; Query OK, 7 rows affected (0.01 sec) Records: 7 Duplicates: 0 Warnings: 0 mysql> (It's OK if yo u get a warning here.) Befo re we start experimenting with full-text indexes, we'll add so me pro ducts with lo ng descriptio ns. First, delete existing ro ws fro m the Pro ducts and Invento ry tables. Type the fo llo wing at the MySQL pro mpt: mysql> DELETE FROM Products; Query OK, 7 rows affected (0.00 sec) mysql> DELETE FROM Inventory; Query OK, 7 rows affected (0.01 sec) mysql> To avo id a lo t o f typing, we'll do wnlo ad an SQL file that co ntains new pro ducts with lo ng descriptio ns. Open a seco nd Unix Terminal to do wnlo ad a special SQL file fo r this lesso n. Type the fo llo wing at the Unix pro mpt in the seco nd Unix Terminal: cold1:~$ curl http://courses.oreillyschool.com/dba1/downloads/products-10.sql > product s-10.sql % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 11829 100 11829 0 0 94214 0 --:--:-- --:--:-- --:--:-- 5775k cold1:~$ Once yo u have do wnlo aded the file, use the mysql co mmand to impo rt the pro ducts. Type the fo llo wing at the Unix pro mpt in the seco nd Unix Terminal: cold1:~$ mysql -h sql -p -u username username < products-10.sql Enter password: cold1:~$ If the impo rt is successful, yo u see no results. No w that we have so me data, let's create o ur full-text index. We need to tell the database server which co lumns we are interested in searching. We co uld search thro ugh all char, varchar, and text co lumns, but o ur users will primarily search o n title and descriptio n. Switch back to the first terminal sessio n. Type the fo llo wing at the MySQL pro mpt: mysql> ALTER TABLE Products ADD FULLTEXT (Title, Description); Query OK, 7 rows affected (0.01 sec) Records: 7 Duplicates: 0 Warnings: 0 mysql> OBSERVE: mysql> ALTER TABLE Products ADD FULLTEXT (Title, Description); We added FULLT EXT to the T it le and De script io n co lumns. That's all there is to it! No w yo u're ready to write so me queries. Querying Full-T ext Indexes The syntax to use a full-text index in a query is straightfo rward. The magic is in the WHERE clause. OBSERVE: WHERE MATCH(column 1, column 2...column n) AGAINST('comma-separated list of search criteria'); Since the bo o ks in the Pro ducts table are all o n the to pic o f databases, try searching fo r "relatio nal database." Type the fo llo wing at the MySQL pro mpt: mysql> SELECT ProductCode, Title, Price FROM Products -> WHERE MATCH(Title,Description) -> AGAINST('relational databases'); +--------------+------------------------------------+-------+ | ProductCode | Title | Price | +--------------+------------------------------------+-------+ | databaseid | Database in Depth | 29.95 | | relationaldb | The Relational Database Dictionary | 14.99 | | artofsql | The Art of SQL | 44.99 | +--------------+------------------------------------+-------+ 3 rows in set (0.02 sec) mysql> Take a peek at the descriptio ns fo r these bo o ks—all have so me mentio n o f the phrase "relatio nal database." Let's co mpare the query we just executed to the o ther way o f searching fo r this info rmatio n—using the LIKE o perato r. Yo u pro bably remember that the % percent symbo l matches anything when using the LIKE o perato r. Type the fo llo wing at the MySQL pro mpt: mysql> select ProductCode, Title, Price FROM Products -> WHERE title like '%relational%databases%' OR description like '%relational%datab ases%'; +--------------+------------------------------------+-------+ | ProductCode | Title | Price | +--------------+------------------------------------+-------+ | relationaldb | The Relational Database Dictionary | 14.99 | | databaseid | Database in Depth | 29.95 | +--------------+------------------------------------+-------+ 2 rows in set (0.00 sec) mysql> Only two ro ws were returned! If yo u suspect that the full-text index is do ing so me extra wo rk, yo u are co rrect. Full-text indexes take the language being indexed into acco unt in o rder to return relevant results. By default, a natural language search is perfo rmed, meaning similar wo rds such as "database" and "databases" wo uld be co nsidered a match. While that type o f match is po ssible when using LIKE, it leads to so me tricky SQL co de! The full-text index has these o ptimizatio ns to help perfo rmance: Wo rds less than five characters in length are igno red. (This minimum length can be changed.) Sto p wo rds such as "the" and even "co nsidering" are igno red by default. (The list o f sto p wo rds can be o verridden.) Fo r a list o f default sto p wo rds, check o ut MySQL's web site. Note Since o ur Pro ducts table is small, using full-text index pro bably do esn't affect speed and efficiency much. Ho wever, o n a large table with a pro perly planned full-text index, the impact o n perfo rmance can be significant. Try expanding the criteria—add "o racle" to the search. Type the fo llo wing at the MySQL pro mpt: mysql> SELECT ProductCode, Title, Price FROM Products -> WHERE MATCH(Title,Description) -> AGAINST('relational databases, oracle'); +--------------+------------------------------------+-------+ | ProductCode | Title | Price | +--------------+------------------------------------+-------+ | databaseid | Database in Depth | 29.95 | | relationaldb | The Relational Database Dictionary | 14.99 | | mysqlspp | MySQL Stored Procedure Programming | 44.99 | | sqlhks | SQL Hacks | 29.99 | | artofsql | The Art of SQL | 44.99 | +--------------+------------------------------------+-------+ 5 rows in set (0.00 sec) mysql> This time five bo o ks matched the criteria. The next questio n yo u might ask is ho w can I rank m y m at che s in o rde r o f re le vance ? The answer: include MAT CH...AGAINST in the selected co lumns: Type the fo llo wing at the MySQL pro mpt: mysql> SELECT ProductCode, Title, Price, -> MATCH(Title,Description) AGAINST('relational databases') as Relevance -> FROM Products -> WHERE MATCH(Title,Description) AGAINST('relational databases'); +--------------+------------------------------------+-------+-------------------+ | ProductCode | Title | Price | Relevance | +--------------+------------------------------------+-------+-------------------+ | databaseid | Database in Depth | 29.95 | 1.31360828876495 | | relationaldb | The Relational Database Dictionary | 14.99 | 0.812412083148956 | | artofsql | The Art of SQL | 44.99 | 0.108494639396667 | +--------------+------------------------------------+-------+-------------------+ 3 rows in set (0.00 sec) mysql> No w yo u can see ho w well yo ur search criteria matches the full-text index. Fo r MySQL, relevance numbers are always flo ating-po int numbers, greater than o r equal to zero . A relevance o f zero indicates no match. Note It may seem like MySQL wo uld execute the full-text search twice in the previo us query. As lo ng as bo th MAT CH...AGAINST sectio ns are exactly the same, o nly o ne query will execute. Yo u've just learned ho w yo u can use full-text indexes to pro vide a fast and po werful way to search yo ur data. In the next lesso n, yo u'll learn ho w to peek into the INFORMATION_SCHEMA tables MySQL maintains to learn mo re abo ut yo ur tables and co lumns. See yo u there! Copyright © 1998-2014 O'Reilly Media, Inc. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License. See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information. Information About the Database Welco me back! So far, we've learned ho w to create and po pulate tables, use views, and create sto red pro cedures. Tables are made up o f ro ws and co lumns. A view is a sto red versio n o f a query, and a sto red pro cedure is a sequence o f steps kept in the database. All o f this info rmatio n is metadata—data abo ut data—extra info rmatio n that describes o ur database. INFORMAT ION_SCHEMA A descriptio n o f o ur database co uld be written in English like this: "tables and pro cedures used to keep track o f bo o k invento ry in o ur sto re." It also co uld be co mpo sed in the fo rm o f a list: Invento ry Pro ducts CreatePro duct ... When yo u think abo ut it, this data co uld be o rganized in ro ws and co lumns, just like a database table itself! This is useful because we can use o ur standard query to o ls to access all aspects o f o ur database. MySQL and o ther databases (at least tho se that claim to suppo rt so me SQL:20 0 3 features) pro vide a windo w into database metadata thro ugh the INFORMAT ION_SCHEMA. A schema is a co llectio n o f tables, fields, and the relatio nships between fields and tables. In MySQL, an INFORMAT ION_SCHEMA is a pseudo -database. It do esn't physically exist, but yo u are able to co nnect to it. Yo u can query any table in the INFORMATION_SCHEMA, but yo u can't update, alter, o r delete anything. T ABLES Suppo se yo ur bo ss sto ps by yo ur desk o ne afterno o n. He heard abo ut the fancy full-text indexes yo u used in the previo us lesso n, and he wants to kno w which tables use the MyISAM engine and which o nes use the Inno DB engine. INFORMAT ION_SCHEMA enables yo u to answer this questio n quickly. Let's take a peek at o ur tables by querying the TABLES table in INFORMATION_SCHEMA. In the fo llo wing list, be sure to replace username with yo ur o wn username. Type the fo llo wing at the MySQL pro mpt: mysql> SELECT table_name, table_type, engine -> FROM INFORMATION_SCHEMA.TABLES -> WHERE table_schema='username'; +-------------------+------------+--------+ | table_name | table_type | engine | +-------------------+------------+--------+ | Customers | BASE TABLE | InnoDB | | Inventory | BASE TABLE | InnoDB | | OrderLine | BASE TABLE | InnoDB | | Orders | BASE TABLE | InnoDB | | ProductInventory | VIEW | NULL | | Products | BASE TABLE | MyISAM | | SalesAnalysis | BASE TABLE | MyISAM | | SalesDataPivot | VIEW | NULL | ... | test | BASE TABLE | MyISAM | +-------------------+------------+--------+ 31 rows in set (1.29 sec) mysql> So me o f the ro ws have been o mitted fo r clarity, and yo u may see a different number o f ro ws. With o ne sho rt query we were able to get the exact info rmatio n we needed. No w, suppo se yo ur bo ss o nly wants the names o f the tables that do not suppo rt full-text indexes. We can easily add to the WHERE clause to o ur previo us query to answer that questio n: Type the fo llo wing at the MySQL pro mpt: mysql> SELECT table_name, table_type, engine -> FROM INFORMATION_SCHEMA.TABLES -> WHERE table_schema='username' AND engine='InnoDB'; +------------+------------+--------+ | table_name | table_type | engine | +------------+------------+--------+ | Customers | BASE TABLE | InnoDB | | Inventory | BASE TABLE | InnoDB | | OrderLine | BASE TABLE | InnoDB | | Orders | BASE TABLE | InnoDB | +------------+------------+--------+ 4 rows in set (1.00 sec) We have fo ur tables that do no t suppo rt full-text indexing, and o ur bo ss has his answer in abo ut o ne seco nd! COLUMNS Well, yo ur bo ss was very impressed with ho w quickly yo u were able to pro vide the info rmatio n he requested, so he's co me directly to yo u with his next query request. It seems he is wo rried that certain co lumns in the Pro ducts table are no t large eno ugh to ho ld all o f the data fo r a new bo o k—St e al T his Co m put e r Bo o k 4 .0 : What T he y Wo n't T e ll Yo u Abo ut t he Int e rne t . He may be right—that title is very lo ng! To find this info rmatio n fast, we'll peek into the COLUMNS table o f INFORMATION_SCHEMA. Type the fo llo wing at the MySQL pro mpt: mysql> SELECT column_name, data_type, character_maximum_length -> FROM INFORMATION_SCHEMA.COLUMNS -> WHERE table_name='Products' AND table_schema='username'; +-------------+-----------+--------------------------+ | column_name | data_type | character_maximum_length | +-------------+-----------+--------------------------+ | ProductCode | char | 20 | | Title | varchar | 50 | | Category | varchar | 30 | | Description | text | 65535 | | Price | decimal | NULL | +-------------+-----------+--------------------------+ 5 rows in set (1.36 sec) mysql> A quick visual inspectio n sho ws that the T it le co lumn may no t be lo ng eno ugh. Let's refine o ur query to return all co lumns that aren't lo ng eno ugh to co ntain the title. To do this, we'll use the length functio n—it returns an integer co unt o f a string's length. Note Be sure to include a backslash (\) befo re the apo stro phe (') in the title. The backslash "escapes" the apo stro phe so MySQL wo n't think it's the end o f the title. Type the fo llo wing at the MySQL pro mpt: mysql> SELECT column_name, data_type, character_maximum_length -> FROM INFORMATION_SCHEMA.COLUMNS -> WHERE table_name='Products' -> AND character_maximum_length < length('Steal This Computer Book 4.0: What They Won\'t Tell You About the Internet'); +-------------+-----------+--------------------------+ | column_name | data_type | character_maximum_length | +-------------+-----------+--------------------------+ | ProductCode | char | 20 | | Title | varchar | 50 | | Category | varchar | 30 | +-------------+-----------+--------------------------+ 3 rows in set (0.99 sec) mysql> The title co lumn was way to o sho rt. The Pro ductCo de and Catego ry may also need to be increased. Yo ur bo ss is extremely happy with yo ur wo rk! VIEWS Later in the day yo ur bo ss sto ps by yet again. This time he is co ncerned abo ut the views being used in the applicatio n. He wants to kno w exactly which views have been created, and which views allo w UPDATE, DELETE, and perhaps INSERT queries. Once again yo u turn to INFORMATION_SCHEMA—this time to the VIEWS table. Type the fo llo wing at the MySQL pro mpt: mysql> SELECT table_name, is_updatable, view_definition -> FROM INFORMATION_SCHEMA.VIEWS WHERE table_schema='username'; +------------------+--------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | table_name | is_updatable | view_definition | +------------------+--------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | ProductInventory | NO | /* ALGORITHM=UNDEFINED */ select `P`.`Produc tCode` AS `ProductCode`,`P`.`Title` AS `Title`,`P`.`Price` AS `Price`,`I`.`Quant ityInStock` AS `Qty` from (`certjosh`.`Products` `P` left join `certjosh`.`Inven tory` `I` on((`P`.`ProductCode` = `I`.`ProductCode`))) | | SalesDataPivot | NO | /* ALGORITHM=UNDEFINED */ select `certjosh`. `SalesAnalysis`.`Region` AS `Region`,sum((case when (`certjosh`.`SalesAnalysis`. `Quarter` = _latin1'2007-03-31') then `certjosh`.`SalesAnalysis`.`UnitsSold` els e 0 end)) AS `2007-Q1`,sum((case when (`certjosh`.`SalesAnalysis`.`Quarter` = _l atin1'2007-06-30') then `certjosh`.`SalesAnalysis`.`UnitsSold` else 0 end)) AS ` 2007-Q2`,sum((case when (`certjosh`.`SalesAnalysis`.`Quarter` = _latin1'2007-0930') then `certjosh`.`SalesAnalysis`.`UnitsSold` else 0 end)) AS `2007-Q3`,sum(( case when (`certjosh`.`SalesAnalysis`.`Quarter` = _latin1'2007-12-31') then `cer tjosh`.`SalesAnalysis`.`UnitsSold` else 0 end)) AS `2007-Q4` from `certjosh`.`Sa lesAnalysis` group by `certjosh`.`SalesAnalysis`.`Region` | +------------------+--------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 2 rows in set (1.02 sec) mysql> Yo u kno w yo u'll have to make this o utput mo re readable befo re yo u hand it o ver to yo ur bo ss. Fo rtunately, he do esn't need to see the who le view definitio n, just the first several characters. We can use substring to skip the first few characters and limit the descriptio n to a to tal o f 50 characters. Type the fo llo wing at the MySQL pro mpt: mysql> SELECT table_name, is_updatable, -> substring(view_definition,27,50) AS definition -> FROM INFORMATION_SCHEMA.VIEWS -> WHERE table_schema='username'; +------------------+--------------+---------------------------------------------------+ | table_name | is_updatable | definition | +------------------+--------------+---------------------------------------------------+ | ProductInventory | YES | S `ProductCode`,`P`.`Title` AS `Title`,`P`.` Price` | | SalesDataPivot | NO | lysis`.`Region` AS `Region`,sum((case when ( `smill | +------------------+--------------+---------------------------------------------------+ 2 rows in set (0.99 sec) mysql> That's much easier o n the eyes! Yo u give the results to yo ur bo ss, who is still very impressed with yo ur wo rk, and pro mises to have a talk with yo u so o n abo ut yo ur future with the co mpany. ROUT INES It's nearing 5:0 0 PM, and yo ur bo ss co mes by yo ur desk fo r o ne last piece o f info rmatio n. A lazy develo per really wants to rename the "QuantityInSto ck" co lumn to "Qty" to save typing. Yo ur bo ss wants to kno w ho w many pro cedures will have to be changed if the co lumn is renamed. Yo u tell him yo u'll lo o k into it, and will give him an answer by the end o f the day. Fo r this task yo u'll use the ROUTINES table fro m INFORMATION_SCHEMA. So me o f the pro cedures can be quite lo ng, so let's end o ur query with \G to request the "lo ng" o utput fro m MySQL instead o f the "wide" o utput. Type the fo llo wing at the MySQL pro mpt: mysql> SELECT routine_name, routine_type, routine_definition -> FROM INFORMATION_SCHEMA.ROUTINES \G *************************** 1. row *************************** routine_name: CreateProduct routine_type: PROCEDURE routine_definition: BEGIN insert into Products (ProductCode, Title, Category, Description, Price) values (ProductCode, Title, Category, Description, Price); insert into Inventory (ProductCode, QuantityInStock) values (ProductCode, Quantity); END *************************** 2. row *************************** routine_name: CurrentProductInventory routine_type: PROCEDURE routine_definition: BEGIN select P.ProductCode, P.Title, P.Price, I.QuantityInStock as Qty from Products as P LEFT JOIN Inventory as I on (P.ProductCode = I.ProductCode); END 2 rows in set (0.00 sec) mysql> Yo ur results might be slightly different, but they sho uld lo o k similar. These are exactly the results we want. Our bo ss do esn't want to spend a lo t o f time reading thro ugh the pro cedure definitio ns to see where "QuantityInSto ck" is being used, so we'll add a calculated co lumn to pro vide that info rmatio n. Type the fo llo wing at the MySQL pro mpt: mysql> SELECT routine_name, routine_type, -> CASE WHEN routine_definition LIKE '%QuantityInStock%' THEN 1 ELSE 0 END -> AS Uses_QuantityInStock -> FROM INFORMATION_SCHEMA.ROUTINES; +-------------------------+--------------+----------------------+ | routine_name | routine_type | Uses_QuantityInStock | +-------------------------+--------------+----------------------+ | CreateProduct | PROCEDURE | 1 | | CurrentProductInventory | PROCEDURE | 1 | +-------------------------+--------------+----------------------+ 2 rows in set (0.00 sec) mysql> It lo o ks like we have so me wo rk to do if we decide to rename the co lumn, but o nce again yo u've given yo ur bo ss the info rmatio n he needs. It might be time to ask fo r a raise! Fo r additio nal info rmatio n o n the INFORMATION_SCHEMA tables in MySQL, check o ut MySQL's web site. That's it! Yo u've go tten a go o d start o n yo ur database applicatio ns. But yo u pro bably do n't want to sto p no w. This co urse is just the first in a series designed to give yo u the co nfidence and kno wledge yo u need to use databases effectively. The next lesso n will be a descriptio n o f yo ur final pro ject. See yo u there! Copyright © 1998-2014 O'Reilly Media, Inc. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License. See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information. Final Project Wo w! Yo u've co me a lo ng way. We've co vered a lo t, and no w it's time fo r yo u to apply yo ur new kno wledge to the final pro ject. Final Project Specification Yo u've do ne a go o d jo b at ATunes, and learned a lo t. In o rder to co ntinue yo ur learning, and to share tips and experiences with databases, yo u decide to create a blo g just fo r databases. Yo u'll publish articles written by many different peo ple, and allo w visito rs to co mment o n tho se articles. Yo u have a friend who will make a web site fo r yo u, so the o nly aspect o f the blo g yo u'll have to wo rry abo ut is the database. Yo u need to create all o f the database o bjects needed to suppo rt the blo g. To co mplete the pro ject, yo u'll need to create the fo llo wing tables: 1. Art icle Aut ho rs: names, email addresses, so me bio graphical info rmatio n 2. Art icle s: title, sho rt descriptio n (blurb), article text, date (use a full text index o n the blurb) 3. Art icle Cat e go rie s: catego ries are like MySQL, Oracle, SQL Server, Queries, Sto red Pro cedures, etc. 4. Co m m e nt e rs: names, email addresses o f co mmenters 5. Co m m e nt s: No tes left by co mmenters regarding an article 6 . Art icle Vie ws: Lo gs the date and time an article was viewed Feel free to add additio nal co lumns as yo u see necessary. Make sure yo u use appro priate data types. After yo u create the tables, po pulate them all with sample data. Create at least five articles. Yo u do n't have to write all o f the co ntent yo urself—test data is fine. Note Make sure yo u created a full text index o n the Article blurb. Next, write a sto red pro cedure named AddCo m m e nt to add a co mment o n an article, creating an entry in Co mmenters if it do esn't exist. Create a view named Art icle Display that displays autho r, the article, and catego ry fo r the article. This view will be used to display the article o n the web page. Write the fo llo wing queries: 1. Demo nstrate the use o f the full text index o n the Articles table. One query sho uld sho w successful matches with a ranking, ano ther query sho uld sho w no matches. 2. Pivo t ArticleViews to display the number o f times an article was viewed in the last 10 , 20 , and 30 days. The o utput sho uld lo o k so mething like this: OBSERVE: Article New Features in MySQL Views in Oracle D10 5 2 D20 10 4 D30 7 1 3. Write a query that sho ws the mo st po pular article—the article that has the mo st ro ws in ArticleViews. Make sure yo u name yo ur o bjects carefully—yo ur mento r will be lo o king fo r specific names. Sto re all o f yo ur CREATE, INSERT, and SELECT statements in a file called dba1f inalpro je ct .sql. When yo u finish hand in this SQL file. GOOD LUCK! Copyright © 1998-2014 O'Reilly Media, Inc. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License. See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information.