Download Full MySQL Crash Course 2nd Edition Forta PDF All Chapters
Download Full MySQL Crash Course 2nd Edition Forta PDF All Chapters
com
https://textbookfull.com/product/mysql-crash-course-2nd-
edition-forta/
OR CLICK BUTTON
DOWNLOAD NOW
https://textbookfull.com/product/ap-chemistry-crash-course-2nd-
edition-adrian-dingle/
textboxfull.com
https://textbookfull.com/product/electrochemistry-crash-course-for-
engineers-slobodan-petrovic/
textboxfull.com
https://textbookfull.com/product/excel-crash-course-for-engineers-
eklas-hossain/
textboxfull.com
https://textbookfull.com/product/python-crash-course-a-hands-on-
project-based-introduction-to-programming-2nd-edition-eric-matthes/
textboxfull.com
C Crash Course A Fast Paced Introduction Josh Lospinoso
https://textbookfull.com/product/c-crash-course-a-fast-paced-
introduction-josh-lospinoso/
textboxfull.com
https://textbookfull.com/product/paramedic-crash-course-with-online-
practice-test-1st-edition-christopher-coughlin-ph-d/
textboxfull.com
https://textbookfull.com/product/memory-crash-2nd-edition-georgiy-
kasianov/
textboxfull.com
Crash Course for the GRE Your Last Minute Guide to Scoring
High 6th Edition Coll.
https://textbookfull.com/product/crash-course-for-the-gre-your-last-
minute-guide-to-scoring-high-6th-edition-coll/
textboxfull.com
MySQL Crash
Course
This page intentionally left blank
MySQL Crash
Course
Second Edition
Ben Forta
Many of the designations used by manufacturers and sellers to distinguish their Vice President, IT Professional
products are claimed as trademarks. Where those designations appear in this book, and Mark Taub
the publisher was aware of a trademark claim, the designations have been printed with
initial capital letters or in all capitals. Acquisitions Editor
Kim Spenceley
The author and publisher have taken care in the preparation of this book, but make
no expressed or implied warranty of any kind and assume no responsibility for errors Development Editor
or omissions. No liability is assumed for incidental or consequential damages in Chris Zahn
connection with or arising out of the use of the information or programs contained
herein.
Managing Editor
Sandra Schroeder
For information about buying this title in bulk quantities, or for special sales
opportunities (which may include electronic versions; custom cover designs; and
content particular to your business, training goals, marketing focus, or branding Senior Project Editor
interests), please contact our corporate sales department at [email protected] Tonya Simpson
or (800) 382-3419.
Copy Editor
For government sales inquiries, please contact [email protected]. Kitty Wilson
For questions about sales outside the U.S., please contact [email protected]. Indexer
Timothy Wright
Visit us on the Web: informit.com/aw
Proofreader
Library of Congress Control Number: 2023943569 Jennifer Hinchliffe
ISBN-13: 978-0-13-822302-1
ISBN-10: 0-13-822302-5
$PrintCode
Pearson’s Commitment to Diversity, Equity, and Inclusion
Pearson is dedicated to creating bias-free content that reflects the diversity of all learners.
We embrace the many dimensions of diversity, including but not limited to race, ethnicity,
gender, socioeconomic status, ability, age, sexual orientation, and religious or political beliefs.
Education is a powerful force for equity and change in our world. It has the poten-
tial to deliver opportunities that improve lives and enable economic mobility. As we
work with authors to create content for every product and service, we acknowledge
our responsibility to demonstrate inclusivity and incorporate diverse scholarship so that
everyone can achieve their potential through learning. As the world’s leading learning
company, we have a duty to help drive change and live up to our purpose to help more
people create a better life for themselves and to create a better world.
Our ambition is to purposefully contribute to a world where
Q Everyone has an equitable and lifelong opportunity to succeed through learning
Q Our educational products and services are inclusive and represent the rich diversity
of learners
Q Our educational content accurately reflects the histories and experiences of the
learners we serve
Q Our educational content prompts deeper discussions with learners and motivates
them to expand their own learning (and worldview)
While we work hard to present unbiased content, we want to hear from you about
any concerns or needs with this Pearson product so that we can investigate and address
them.
Please contact us with concerns about any potential bias at
https://www.pearson.com/report-bias.html.
This page intentionally left blank
Contents
1 Understanding SQL 1
Database Basics 1
What Is a Database? 2
Tables 2
Columns and Datatypes 3
Rows 4
Primary Keys 4
What Is SQL? 6
Try It Yourself 6
Summary 7
2 Introducing MySQL 9
What Is MySQL? 9
Client/Server Software 9
MySQL Versions 10
MySQL Tools 11
mysql Command-Line Utility 11
MySQL Workbench 12
Other Tools 13
Summary 13
4 Retrieving Data 25
The SELECT Statement 25
Retrieving Individual Columns 25
viii Contents
6 Filtering Data 43
Using the WHERE Clause 43
WHERE Clause Operators 44
Checking Against a Single Value 45
Checking for Nonmatches 46
Checking for a Range of Values 47
Checking for No Value 48
Summary 49
Challenges 49
12 Summarizing Data 93
Using Aggregate Functions 93
The Avg() Function 94
The Count() Function 95
The Max() Function 96
The Min() Function 97
The Sum() Function 98
Aggregates on Distinct Values 99
Combining Aggregate Functions 100
Summary 101
Challenges 101
Index 265
This page intentionally left blank
Acknowledgments
Thanks to the team at Pearson for all these years of support, dedication, and encourage-
ment. Over the past two and a half decades, we’ve created 40+ books together, but our
little Sams Teach Yourself SQL in 10 Minutes series remains my favorite by far. Thank you
for trusting me with the creative freedom to evolve it as I have seen fit.
Speaking of Sams Teach Yourself SQL in 10 Minutes, that title covers MySQL (as it
does all major DBMSs), but it cannot provide in-depth lessons on features that are truly
unique to MySQL. This spinoff book was written in response to numerous requests from
readers for greater MySQL-specific coverage. Thanks for the nudge. I hope this book
lives up to your expectations.
Thanks to the many thousands of readers who provided feedback on prior editions of
these books. Fortunately, most of it was positive; all of it was appreciated. The enhance-
ments and changes in the latest editions are in direct response to your feedback, which
I continue to welcome.
I write because I love to teach. While nothing compares to hands-on in-classroom
instruction, turning those lessons into books that can be read far and wide has gifted
me with expanding my teaching reach. It is thus a source of much gratification to
see hundreds of colleges and universities use these SQL books as part of their IT and
computer science curricula. Being included by professors and teachers in this way is both
rewarding and humbling, and for that trust I am thankful.
And finally, thanks to the almost 1 million of you who bought the previous editions
of these books (in over a dozen languages), making them not just my best-selling series
but also the best-selling books on SQL. Your continued support is the highest compli-
ment an author can ever be paid.
—Ben Forta
This page intentionally left blank
About the Author
Ben Forta is Adobe’s Senior Director of Education Initiatives and has more than
three decades of experience in the computer industry—in product development,
support, training, and product marketing. He is the author of the best-selling Sams
Teach Yourself SQL in 10 Minutes (as well as spinoff titles like this one and versions on
SQL Server T-SQL, Oracle PL/SQL, and MariaDB), Learning Regular Expressions, and
Captain Code, which teaches Python to younger coders (and those young at heart), Java,
Windows, and more. He has extensive experience in database design and development,
has implemented databases for several highly successful commercial software programs
and websites, and is a frequent lecturer and columnist on application development and
Internet technologies. Ben lives in Oak Park, Michigan, with his wife, Dr. Marcy Forta,
and their children. He welcomes your email at [email protected] and invites you to visit
his website at http://forta.com.
This page intentionally left blank
Introduction
MySQL is one of the most popular database management systems in the world. From
small development projects to some of the best-known and most prestigious sites on the
Web, MySQL has proven itself to be a solid, reliable, fast, and trusted solution for all
sorts of data storage needs.
This book is based on my best-selling Sams Teach Yourself SQL in 10 Minutes. That
book has become one of the most-used SQL tutorials in the world, with an emphasis on
teaching what you really need to know—methodically, systematically, and simply. But as
popular and as successful as that book is, it does have some limitations:
Q In covering all of the major database management systems (DBMSs), coverage of
DBMS-specific features and functionality had to be kept to a minimum.
Q To simplify the SQL taught, the lowest common denominator had to be found—
SQL statements that would (as much as possible) work with all major DBMSs.
This requirement necessitated that better DBMS-specific solutions not be covered.
Q Although basic SQL tends to be rather portable between DBMSs, more advanced
SQL most definitely is not. As such, that book could not cover advanced topics,
such as triggers, cursors, stored procedures, access control, and transactions, in any
real detail.
And that is where this book comes in. MySQL Crash Course builds on the proven
tutorials and structure of Sams Teach Yourself SQL in 10 Minutes without getting bogged
down with anything except MySQL. Starting with simple data retrieval and working on
to more complex topics, including the use of joins, subqueries, regular expression and
full text-based searches, stored procedures, cursors, triggers, table constraints, and much
more, you’ll learn what you need to know methodically, systematically, and simply—in
highly focused chapters designed to make you immediately and effortlessly productive.
When you turn to Chapter 1 and get to work, you’ll be taking advantage of all
MySQL has to offer in no time at all.
Companion Website
This book has a companion website online at http://forta.com/books/9780138223021/.
At this website, you’ll find:
Q The files used to create the example tables used throughout this book
Q Answers to the questions in the “Challenges” section at the end of each chapter
Q Online errata
Note
A Note presents an interesting piece of information related to the surrounding discussion.
Tip
A Tip offers advice or teaches an easier way to do something.
Caution
A Caution advises you about potential problems and helps you steer clear of disaster.
New Term
A New Term box provides a clear definition of a new essential term.
Figure Credits
Figures 3.1-3.5: Oracle Corporation
Introduction xxiii
Input
The Input icon identifies code that you can type in yourself. It usually appears next
to a listing.
Output
The Output icon highlights the output produced by running MySQL code. It usually
appears after input and next to output.
Analysis
The Analysis icon alerts you to the line-by-line analysis of input or output.
This page intentionally left blank
1
Understanding SQL
In this chapter, you’ll learn about databases and SQL, which are prerequisites to learning
MySQL.
Database Basics
The fact that you are reading this book indicates that you, somehow, need to interact
with databases, and MySQL specifically. And so, before diving into MySQL and its
implementation of the SQL language, it is important that you understand some basic
concepts about databases and database technologies.
Whether you are aware of it or not, you use databases all the time. Each time you
select a name from your email address book, you are using a database. When you browse
contacts on your phone, you are using a database. If you conduct a search on an Internet
search site, you are using a database. When you log in to your network at work, you
are validating your name and password against a database. Even when you use your
ATM card at a cash machine, you are using databases for PIN verification and balance
checking.
But even though we all use databases all the time, there remains much confusion over
what exactly a database is. This is especially true because different people use the same
database terms to mean different things. Therefore, a good place to start our study is
with a list and explanation of the most important database terms.
Tip
Reviewing Basic Concepts What follows is a very brief overview of some basic
database concepts. It is intended to either jolt your memory if you already have some
database experience or to provide you with the absolute basics if you are new to data-
bases. Understanding databases is an important part of mastering MySQL, and you
might want to find a good book on database fundamentals to brush up on the subject,
if needed.
2 Chapter 1 Understanding SQL
What Is a Database?
The term database is used in many different ways, but for our purposes in this book, a
database is a collection of data stored in some organized fashion. The simplest way to
think of it is to imagine a database as a filing cabinet. The filing cabinet is simply a
physical location to store data, regardless of what that data is or how it is organized.
New Term
Database A container (usually a file or set of files) for storing organized data.
Caution
Misuse Causes Confusion People often use the term database to refer to the database
software they are running. This is incorrect, and it is a source of much confusion. Database
software is actually called a database management system (or DBMS). A database is a container
created and manipulated via a DBMS. A database might or might not be a file stored on a
hard drive. And for the most part, this is not even significant as you never access a database
directly anyway; you always use the DBMS, and it accesses the database for you.
Tables
When you store information in a filing cabinet, you don’t just toss it in a drawer. Rather,
you create files within the filing cabinet, and then you store related data in specific files.
In the database world, a file is called a table. A table is a structured file that can store
data of a specific type. A table might contain a list of customers, a product catalog, or
any other list of information.
New Term
Table A structured list of data of a specific type.
The key here is that the data stored in the table is one type of data or one list. You
would never store a list of customers and a list of orders in the same database table.
Doing so would make subsequent retrieval and access difficult. Rather, you’d create two
tables, one for each list.
Every table in a database has a name that identifies it. That name is always unique—
meaning no other table in that database can have the same name.
Note
Table Names What makes a table name unique is actually a combination of several
things, including the database name and table name. While you cannot use the same
table name twice in the same database, you definitely can reuse table names in different
databases.
Database Basics 3
Tables have characteristics and properties that define how data is stored in them.
These include information about what data may be stored, how it is broken up, how
individual pieces of information are named, and much more. The set of information
that describes a table is known as a schema, and a schema can be used to describe specific
tables within a database, as well as an entire database (and the relationship between tables
in a database, if any).
New Term
Schema Information about database and table layout and properties.
Note
Schema or Database? Occasionally the term schema is used as a synonym for database
(and schemata as a synonym for databases). While unfortunate and frequently confusing,
it is usually clear from the context which meaning of schema is intended. In this book,
schema is used as defined here.
New Term
Column A single field in a table. Every table is made up of one or more columns.
The best way to understand this is to envision database tables as grids, somewhat like
spreadsheets. Each column in the grid contains a particular piece of information. In a
customer table, for example, the customer number is stored in one column, the customer
name is stored in another, and the address, city, state, and zip code are all stored in their
own columns.
Tip
Breaking Up Data It is extremely important to break data into multiple columns
correctly. For example, city, state, and zip code should always be stored in separate columns.
By breaking these out, it becomes possible to sort or filter data by specific columns (for
example, to find all customers in a particular state or in a particular city). If city and state
are combined into one column, it would be extremely difficult to sort or filter by state.
Each column in a database has an associated datatype. A datatype defines what type of
data the column can contain. For example, if a column is to contain a number (perhaps
the number of items in an order), it would be associated with the numeric datatype.
4 Chapter 1 Understanding SQL
Columns that contain dates, text, notes, currency amounts, and so on would use the
appropriate datatypes.
New Term
Datatype A type of allowed data. Every table column has an associated datatype that
restricts (or allows) specific data in that column.
Datatypes restrict the type of data that can be stored in a column (for example,
preventing the entry of alphabetical characters into a numeric field). Datatypes also help
sort data correctly and play an important role in optimizing disk usage. As such, special
attention must be given to picking the right datatype when tables are created.
Rows
Data in a table is stored in rows; each record saved is stored in its own row. Again, if you
envision a table as a spreadsheet-style grid, the vertical columns in the grid are the table
columns, and the horizontal rows are the table rows.
For example, a customers table might store one customer per row. The number of
rows in the table is the number of records in the table.
New Term
Row A record in a table.
Note
Records or Rows? You might hear users refer to database records when referring to
rows. For the most part, the two terms are used interchangeably, but row is technically the
correct term.
Primary Keys
Every row in a table should have some column (or set of columns) that uniquely
identifies it. A table containing customers might use a customer number column for
this purpose, whereas a table containing orders might use the order ID. Similarly, an
employee list table might use an employee ID column.
New Term
Primary Key A column (or set of columns) whose values uniquely identify every row
in a table.
Random documents with unrelated
content Scribd suggests to you:
his purpose, and advanced against Turin, whilst Moreau at the same
moment had resolved to retire to Turin and the crests of the
Apennines, in order to preserve his communications with France. On
the 27th of May, Vukassovitch, who commanded the advance guard
of the Russians, surprised Turin, and forced the French to take
refuge in the citadel, leaving in the hands of the victors nearly three
hundred pieces of artillery, sixty thousand muskets, and an
enormous quantity of ammunition and military stores. Moreau’s
army, thus deprived of all its resources, was saved from destruction
only by the extraordinary ability of its commander, who led it safely
towards Genoa by a mountain path, which was rendered practicable
for artillery, in four days. With the exception of a few fortresses,
nothing now remained to the French of all Napoleon’s conquests in
northern Italy; they had been lost in less time than it had taken to
make them.
Exulting in the brilliant success of his arms,
[1799 a.d.] Paul bestowed another surname, Italienski, or
the Italian, on his victorious general, and
ordered by an express ukase that Suvarov should be universally
regarded as the greatest commander that had ever appeared.
Meanwhile the results of his skill and vigour were neutralised by the
selfish policy of the Austrian court, which had become by the Treaty
of Campo Formio, and the acquisition of Venice, in some degree an
actual accomplice with the aggressors against whom it was in arms.
Suvarov was compelled to submit to the dictation of the emperor
Francis I, and deeply disgusted he declared that he was no longer of
any use in Italy, and that he desired nothing so ardently as to be
recalled.
The disasters of the French in upper Italy were fatal to their
ascendancy in the south, and Macdonald received orders to abandon
the Parthenopean Republic, and unite his forces with those of
Moreau. His retreat was exposed to great dangers by the universal
insurrection of the peasants; but he accomplished it with great
rapidity and skill. The two French commanders then concerted
measures to dislodge the allies from their conquests—a project
which seemed not unlikely to be fulfilled, so obstinately had the Aulic
council adhered to the old system of dispersing the troops all over
the territory which they occupied. Though the allies had above a
hundred thousand men in the field, they could hardly assemble thirty
thousand at any one point; and Macdonald might easily have
destroyed them in detail could he have fallen upon them at once;
but the time he spent in reorganising his army in Tuscany, and in
concerting measures with Moreau, was well employed by Suvarov in
promptly concentrating his forces. Macdonald advanced against him
with an army of thirty-seven thousand men, taking Modena on his
way, and driving Hohenzollern out of it after a bloody engagement.
The two armies met on the Trebbia, where a first and indecisive
action took place on the 17th of June; it was renewed on each of the
two following days, and victory finally remained with the Russians.
In this terrible battle of three days, the most obstinately contested
and bloody that had occurred since the beginning of the war, the
loss on both sides was excessive; that of the French was above
twelve thousand in killed and wounded, and that of the allies not
much less. But nearly equal losses told with very unequal severity on
the respective combatants; those of the allies would speedily be
retrieved by large reinforcements, but the republicans had expended
their last resources, were cut off from Moreau, and had no second
army to fall back upon. Macdonald with infinite difficulty regained
the positions he had occupied before the advance to the Trebbia,
after losing an immense number of prisoners.
The fall of the citadel of Turin on the 20th of June was of great
importance to the allies; for besides disengaging their besieging
force it put into their hands one of the strongest fortresses in
Piedmont, and an immense quantity of artillery and ammunition.
This event, and Suvarov’s victory on the Trebbia, checked the
successful operations of Moreau, and compelled him to fall back to
his former defensive position on the Apennines. Again, contrary to
Suvarov’s wishes, the allied forces were divided for the purpose of
reducing Mantua and Alexandria, and occupying Tuscany. After the
fall of those two fortresses, Suvarov laid siege to Tortona, when
Joubert, who had meanwhile superseded Moreau, marched against
him at the head of the combined forces of the French. On the 15th
of August, another desperate battle was fought at Novi, in which
Joubert was killed, but from which neither side derived any particular
advantage. The French returned to their former positions, and the
Italian campaign was ended.
Suvarov now received orders to join his forces with those under
Korsakov, who was on the Upper Rhine with thirty thousand men.
The archduke Charles might, even without this fresh reinforcement,
have already annihilated Massena had he not remained for three
months, from June to August, in complete inactivity; at the very
moment of Suvarov’s expected arrival, he allowed the important
passes of the St. Gotthard to be again carried by a coup-de-main by
the French, under General Lecourbe, who drove the Austrians from
the Simplon, the Furka, the Grimsel, and the Devil’s Bridge. The
archduke, after an unsuccessful attempt to push across the Aar at
Dettingen, suddenly quitted the scene of war and advanced down
the Rhine for the purpose of supporting the English expedition under
the duke of York against Holland. This unexpected turn in affairs
proceeded from Vienna. The Viennese cabinet was jealous of Russia.
Suvarov played the master in Italy, favoured Sardinia at the expense
of the house of Habsburg, and deprived the Austrians of the laurels
and the advantages they had won. The archduke, accordingly,
received orders to remain inactive, to abandon the Russians, and
finally to withdraw to the north; by this movement Suvarov’s
triumphant progress was checked, he was compelled to cross the
Alps to the aid of Korsakov, and to involve himself in a mountain
warfare ill-suited to the habits of his soldiery.
Korsakov, whom Bavaria had been bribed with Russian gold to
furnish with a corps one thousand strong, was supported solely by
Kray and Hotze with twenty thousand men. Massena, taking
advantage of the departure of the archduke and the non-arrival of
Suvarov, crossed the Limmat at Dietikon and shut Korsakov, who had
imprudently stationed himself with his whole army in Zurich, so
closely in that, after an engagement that lasted two days, from the
15th to the 17th of September, the Russian general was compelled
to abandon his artillery and to force his way through the enemy. Ten
thousand men were all that escaped. Hotze, who had advanced from
the Grisons to Schwyz to Suvarov’s rencontre, was, at the same
time, defeated and killed at Schanis. Suvarov, although aware that
the road across the St. Gotthard was blocked by the Lake of
Lucerne, on which there were no boats, had the temerity to attempt
the passage. In Airolo, he was obstinately opposed by the French
under Lecourbe, and, although Shveikovski contrived to turn this
strong position by scaling the pathless rocks, numbers of the men
were, owing to Suvarov’s impatience, sacrificed before it.
On the 24th of September, 1799, he at length climbed the St.
Gotthard, and a bloody engagement, in which the French were
worsted, took place on the Oberalpsee. Lecourbe blew up the Devil’s
Bridge, but, leaving the Urnerloch open, the Russians pushed
through that rocky gorge, and, dashing through the foaming Reuss,
scaled the opposite rocks and drove the French from their position
behind the Devil’s Bridge. Altorf on the lake was reached in safety by
the Russian general, who was compelled, owing to the want of
boats, to seek his way through the valleys of Schächen and Muotta,
across the almost impassable rocks, to Schwyz. The heavy rains
rendered the undertaking still more arduous; the Russians, owing to
the badness of the road, were speedily barefoot; the provisions were
also exhausted. In this wretched state they reached Muotta on the
29th of September and learned the discouraging news of Korsakov’s
defeat. Massena had already set off in the hope of cutting off
Suvarov, but had missed his way. He reached Altorr, where he joined
Lecourbe on the 29th, when Suvarov was already at Muotta, whence
Massena found on his arrival that he had again retired across the
Bragelburg, through the Klönthal. He was opposed on the lake of
Klönthal by Molitor, who was, however, forced to retire by
Auffenberg, who had joined Suvarov at Altorf and formed his
advanced guard, Rosen, at the same time, beating off Massena with
the rearguard, taking five cannon and one thousand of his men
prisoners. On the 1st of October, Suvarov entered Glarus, where he
rested until the 4th, when he crossed the Panixer Mountains through
snow two feet deep to the valley of the Rhine, which he reached on
the 10th, after losing the whole of his beasts of burden and two
hundred of his men down the precipices; and here ended his
extraordinary march, which had cost him the whole of his artillery,
almost all his horses, and a third of his men.
The archduke had, meanwhile, tarried on the Rhine, where he had
taken Philippsburg and Mannheim, but had been unable to prevent
the defeat of the English expedition under the duke of York by
General Brune at Bergen, on the 19th of September. The archduke
now, for the first time, made a retrograde movement, and
approached Korsakov and Suvarov. The different leaders, however,
did nothing but find fault with each other, and the czar, perceiving
his project frustrated, suddenly recalled his troops, and the
campaign came to a close.
Paul’s anger fell without measure or reason on his armies and
their chiefs. All the officers who were missing, that is to say who
were prisoners in France, were broken as deserters, and Suvarov,
instead of being well received with well merited honours, was
deprived of his command and not suffered to see the emperor’s
face. This unjust severity broke the veteran’s heart. He died soon
after his return to St. Petersburg; and no Russian courtier, nor any
member of the diplomatic body except the English ambassador,
followed his remains to the grave.
Our website is not just a platform for buying books, but a bridge
connecting readers to the timeless values of culture and wisdom. With
an elegant, user-friendly interface and an intelligent search system,
we are committed to providing a quick and convenient shopping
experience. Additionally, our special promotions and home delivery
services ensure that you save time and fully enjoy the joy of reading.
textbookfull.com