~~SLIDESHOW~~ ====== Database Access through the Web====== **Supplementary Material** Provided for Reference. This material is no longer taught on this module. **Lecturer**: [[C.P.Jobling@Swansea.ac.uk|Dr Chris P. Jobling]]. An introduction to relational databases, three-tier architecture and database driven web applications. ===== Database Access through the Web ===== * A common feature of many Web applications is the use of relational databases for the efficient storage and retrieval of information. * In this lecture we will discuss how databases can be added to web applications. * Additional notes on SQL and interfaces to languages other than PHP are [[eg-259:extras:dbandsql|available]]. ---- Based on Chapter 14 of Robert W. Sebasta, //Programming the World-Wide Web//, 3rd Edition, Addison Wesley, 2006. and Chapters 11 and 13 of Chris Bates, Web Programming: //Building Internet Applications//, 3rd Edition, John Wiley, 2006. Chris Bates, Web Programming: Building Internet Applications, 3rd Edition, John Wiley, 2006. ===== Contents of this Lecture ===== //Introducing Databases and Database Access with PHP/MySQL// * [[eg-259:lecture19#relational_databases|Relational Databases]] * [[eg-259:extras:dbandsql|Introduction to SQL]] (not examined) * [[eg-259:lecture19#architectures_for_database_access|Architectures for Database Access]] * [[eg-259:lecture19#the_mysql_database_system|Introducing MySQL]] * [[eg-259:lecture19#database_access_with_php_mysql|Database Access with PHP and MySQL]] The [[eg-259:examples:php1#examples_from_lecture_19|Examples of Database Access through the Web]]. ===== Assumed Knowledge ===== //You should be able to answer the following questions:// - What is the purpose of the primary keys of a table in a relational database? - What is the purpose of a cross-reference table? - How are string literals delimited in SQL? - What does the ''NOT NULL'' constraint specify in a column of a ''CREATE TABLE SQL'' command? - What does an asterisk specify when it appears as the value of a ''SELECT'' clause? ===== Assumed Knowledge (continued) ===== //You should be able to answer the following questions:// - What is specified by the ''WHERE'' clause of a ''SELECT'' command? - How are the column names associated with the values in an ''INSERT'' command? - What is the purpose of an ''UPDATE'' command: - What exactly is a //table join//, and how is one specified in SQL? If you have any difficulty, read the [[eg-259:extras:dbandsql|additional notes on SQL]]. ===== Relational Databases ===== * A database is a collection of data organized to allow relatively easy access for retrievals, additions, and deletions * A relational database is a collection of tables of data, each of which has one special column that stores the primary keys of the table * Rows are sometimes called //entities// * Much more detail in module //CS-219// ===== An Example Database ===== * A relational database for used //Corvettes// that are for sale * Could just put all data in a single table, whose key would be a simple sequence number * The table could have information about various equipment the cars could have * Better to put the equipment in a different table and use a cross-reference table to relate cars to equipment * Use a separate table for state names, with only references in the main table ===== Logical Data Model ===== {{eg-259:l19-logical-structure.png?800|Logical structure of the Corvettes database}} ---- "Reading" the diagram we have a corvette belongs to a state and there are many corvettes in a state. Corvettes have one or more pieces of equipment, equipment can belong to more than one corvette. 1 to many relationships indicate a foreign key in the many side. Many to many relationships require a //relationship table//. ===== The Corvettes table ===== ^ Vette_id ^ Body_style ^ Miles ^ Year ^ State ^ | 1 | coupe | 18.0 | 1997 | 4 | | 2 | hatchback | 58.0 | 1996 | 7 | | 3 | convertible | 13.5 | 2001 | 1 | | 4 | hatchback | 19.0 | 1995 | 2 | | 5 | hatchback | 25.0 | 1991 | 5 | | 6 | hardtop | 15.0 | 2000 | 2 | | 7 | coupe | 55.0 | 1979 | 10 | | 8 | convertible | 17.0 | 1999 | 5 | | 9 | hardtop | 17.0 | 2000 | 5 | | 10 | hatchback | 50.0 | 1995 | 7 | ===== The States table ===== ^ State_id ^ State ^ | 1 | Alabama | | 2 | Alaska | | 3 | Arizona | | 4 | Arkansas | | 5 | California | | 6 | Colorado | | 7 | Connecticut | | 8 | Delaware | | 9 | Florida | | 10 | Georgia | | : | : | | 51 | Wyoming | ===== The Equipment table ===== ^ Equp_id ^ Equip ^ | 1 | Automatic | | 2 | 4-speed | | 3 | 5-speed | | 4 | 6-speed | | 5 | CD | | 6 | Leather | ===== The Corvettes_Equipment table ===== ^ Vette_id ^ Equip ^ | 1 | 1 | | 1 | 5 | | 1 | 6 | | 2 | 1 | | 2 | 5 | | 2 | 6 | | 3 | 1 | | 3 | 6 | | : | : | | 10 | 5 | ===== Using SQL ===== * To define a database and **C**reate, **R**etrieve, **U**pdate, and **D**elete records in a web application we need some knowledge of SQL * Some examples follow: * Use ''CREATE TABLE'' to create a database * **C**reating new records with ''INSERT'' * **R**etrieving data with ''SELECT'' * **U**dating records with ''UPDATE'' * **D**eleting records with ''DELETE'' ===== Use CREATE TABLE to create a database ===== CREATE TABLE 'states' ( 'State_id' int(11) NOT NULL auto_increment, 'State' varchar(25) NOT NULL, PRIMARY KEY ('State_id') ); CREATE TABLE 'corvettes' ( 'Vette_id' int(11) NOT NULL auto_increment, 'Body_style' varchar(25) NOT NULL, 'Miles' float NOT NULL, 'Year' year(4) NOT NULL, 'State' int(11) NOT NULL, PRIMARY KEY ('Vette_id') ); ===== Creating new records with INSERT ===== INSERT INTO Corvettes(Vette_id, Body_style, Miles, Year, State) VALUES (37, 'convertible', 25.5, 1986, 17) ===== Retrieving data with SELECT ===== SELECT Body_style FROM Corvettes WHERE Year > 1994 ===== Udating records with UPDATE ===== * The ''WHERE'' clause is (often) the primary key of the row to be updated: UPDATE Corvettes SET Year = 1996 WHERE Vette_id = 17 ===== Deleting records with DELETE===== DELETE FROM Corvettes WHERE Vette_id = 27 ===== Deleting tables with DROP ===== DROP TABLE IF EXISTS States ===== Intro to SQL: Joins ===== * If you want all cars that have CD players, you need information from two tables, ''Corvettes'' and ''Equipment'' * ''SELECT'' can build a temporary table with info from two tables, from which the desired results can be gotten -- this is called a //join// of the two tables ===== Joins ===== * A ''SELECT'' that does a join operation specifies two tables in its ''FROM'' clause and also has a compound ''WHERE'' clause * For our example, we must have three ''WHERE'' conditions - ''Vette_ids'' from ''Corvettes'' and ''Corvettes_Equipment'' must match - ''Equip'' from ''Corvettes_Equipment'' must match the ''Equip_id'' from ''Equipment'' - The ''Equip'' from ''Equipment'' must be '''CD''' ===== The join statement! ===== SELECT Corvettes.Vette_id, Corvettes.Body_style, Corvettes.Miles, Corvettes.Year, Corvettes.State, Equipment.Equip FROM Corvettes, Equipment WHERE Corvettes.Vette_id = Corvettes_Equipment.Vette_id AND Corvettes_Equipment.Equip = Equipment.Equip_id AND Equipment.Equip = 'CD' ===== The query results! ===== ^ ''VETTE_ID'' ^ ''BODY_STYLE'' ^ ''MILES'' ^ ''YEAR'' ^ ''STATE'' ^ ''EQUIP'' ^ | 1 | coupe | 18.0 | 1997 | 4 | CD | | 2 | hatchback | 58.0 | 1996 | 7 | CD | | 8 | convertible | 17.0 | 1999 | 5 | CD | | 9 | hardtop | 17.0 | 2000 | 5 | CD | | 10 | hatchback | 50.0 | 1995 | 7 | CD | ===== Learning Outcomes – Database Access ===== //At the end of this lecture you should be able to answer these questions//: - What is the purpose of a third tier in a client/server configuration for Web access to a database? - Why are two-tier client/server configurations sometimes inadequate? - Explain how SQL database access can be provided by extending a programming language. - What is the disadvantage of embedding SQL in a programming language? ===== Architectures for Database Access ===== * Client-Server Architectures * //Client tasks//: * Provide a way for users to submit queries * Run applications that use the results of queries * Display results of queries * //Server tasks//: * Implement a data manipulation language, which can directly access and update the database ===== Two-tier system ===== * A two-tier system has clients that are connected directly to the database server * Problems with a two-tier system: * Because the relative power of clients has grown considerably, we could shift processing to the client, but then keeping all clients current with application updates is difficult ===== Three-Tier system ===== * A solution to the problems of two-tier systems is to add a component in the middle to create a three-tier system * For Web-based database access, the middle tier can run applications (client just gets results) ===== Three-Tier architecture ===== {{eg-259:l19-3-tier.png?800|Three-tier architecture of a Web site supported by databases}} ===== Database Access with Embedded SQL ===== * SQL commands are embedded in programs written in a host programming language, whose compiler is extended to accept some form of SQL commands * //Advantage//: * One package has computational support of the programming language, as well as database access with SQL * //Disadvantage//: * Portability among database systems ===== Common Database Access Architecture ===== {{eg-259:dba-architecture.png?800|Common Database Access Architecture}} ===== Learning Outcomes – MySQL and PHP ===== //At the end of this lecture you should be able to answer these questions//: - What is MySQL? - What does the MySQL constraint ''auto_increment'' do? - What is the problem with quotes in a SQL command obtained from a form element in an XHTML document? - What is the purpose of the PHP ''mysql_select_db'' function? - How can a PHP program determine the number of rows in a query result? ===== Learning Outcomes (continued) ===== //At the end of this lecture you should be able to answer these questions//: - What does the PHP function ''mysql_fetch_array'' do? - Explain the exact form of the value returned by ''mysql_fetch_array''. - What is metadata? - How is the collection of metadata extracted from a database? - How can column labels can be obtained from an object of metadata? ===== PHP & Database Access ===== * An API for each specific database system * Also convenient for Web access to databases, because PHP is run on the Web server ===== The MySQL Database System ===== * A free, efficient, widely used SQL implementation * Available from http://www.mysql.org * Logging on to MySQL (starting it): mysql [-h host] [-u username] [database name] [-p] * The given database name becomes the "focus" of MySQL ---- * ''host'' is the name of the MySQL server -- default is the user's machine * ''username'' is that of the owner of the database -- default is the name used to log into the system ===== Accessing Databases ===== * If you want to access an existing database, but it was not named in the //mysql// command, you must choose it for focus: use cars; * Response is: ''Database changed'' * If the focus has not been set and MySQL gets an SQL command, you get: ERROR 1046: No Database Selected ===== Creating Databases and Tables ===== * To create a new database: CREATE DATABASE cars; * Response: Query ok, 1 row affected (0.05 sec) ---- * Example: CREATE TABLE Equipment (Equip_id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, Equip CHAR(10)); ===== Accessing Metadata ===== * To see the tables of a database: SHOW TABLES; * To see the description of a table (columns): DESCRIBE Corvettes; ===== Database Access with PHP/MySQL ===== * When values from a DB are to be put in XHTML, you must worry about XHTML special characters * To get rid of the XHTML special characters, use the PHP function, ''htmlspecialchars($str)'' * Replaces the special characters in the string with their corresponding XHTML entities ===== Database Access with PHP/MySQL (continued) ===== * Another problem with PHP and XHTML forms is the string special characters (''?'', ''"'', ''\'', and ''NULL''), which could come from ''$_GET'' and ''$_POST'' * To fix these, ''magic_quotes_gpc'' in the ''PHP.ini'' file is set to ''ON'' by default * This //escapes// these special characters ===== Database Access with PHP/MySQL (continued) ===== * Example: $query = "SELECT * FROM Names WHERE Name = $name"; * If this wasn't done and the value of ''$name'' is ''O'Shanter'', it would prematurely terminate the query string * But with ''magic_quotes_gpc'' on, it will be converted to ''O\'Shanter'' ===== Database Access with PHP/MySQL (continued) ===== * Unfortunately, this can create new problems * For example, if a ''SELECT'' clause has a single-quoted part, like '''California''', the single quotes will be implicitly backslashed, making the query illegal for MySQL * So, ''magic_quotes_gpc'' must be turned off, or else the extra backslashes can be removed with ''stripslashes'' ===== PHP: Connecting to a Database ===== * To connect PHP to a database, use ''mysql_connect'', which can have three parameters: - ''host'' (default is localhost) - ''username'' (default is the username of the PHP script -- i.e. effective user id of web server) - ''password'' (default is blank, which works if the database does not require a password) $db = mysql_connect(); * Usually checked for failure * Close the connection to the database with ''mysql_close'' ===== PHP: Selecting database and executing queries ===== * //To focus MySQL//: mysql_select_db("cars"); * //Requesting MySQL Operations//: * Call ''mysql_query'' with a string parameter, which is an SQL command: $query = "SELECT * from States"; $result = mysql_query($query); ===== PHP: Dealing with the result ===== * 1. Get the number of rows in the result: $num_rows = mysql_num_rows($result); * 2. Get the rows with ''mysql_fetch_array'': for ($row_num = 0; $row_num < $num_rows; $row_num++) { $row = mysql_fetch_array($result); print "

Result row number" . ($row_num + 1) . " State_id: "; print htmlspecialchars($row["State_id"]); print "State: "; : } ===== PHP: Using Metadata ===== * We have had it easy -- the column titles were known * If they are not known, we must get them * The result rows are in PHP arrays, whose elements are actually double sets of elements * Each pair has the value, but one has a numeric key and one has a string key ===== PHP: Example of Metadata ===== * For example, if the result has the field values ''(1, Alabama)'', the array has: ((0, 1), (State_id, 1), (1, Alabama), (State, Alabama)) * If the row is indexed with numbers, the element values are returned ===== PHP: Accessing field values ===== * The following displays all field values from ''$row'': $values = array_values($row); for ($index = 0; $index < $num_fields / 2; $index++) print "$values[2 * $index + 1]
";
===== PHP: Displaying all column names ===== * To display all column names: $keys = array_keys($row); for ($index = 0; $index < $num_fields; $index++) print "$keys[2 * $index + 1]
";
===== PHP/MySQL: Example ===== * [[http://eespectre.swan.ac.uk/~eechris/eg-259/examples/lecture19/carsdata.html|carsdata.html]] ( [[http://localhost/eg-259/examples/lecture19/carsdata.html|carsdata.html @ localhost]] ) uses a form to collect a query against the cars database * [[http://eespectre.swan.ac.uk/~eechris/eg-259/examples/lecture19/access_cars.php|access_cars.php]] ( [[http://localhost/eg-259/examples/lecture19/access_cars.php|access_cars.php @ localhost]] ) is a PHP script to access the cars database through MySQL and execute the query passed through ''$_POST'' ---- For reasons of security, examples are designed to work from a local installation. I used ''DocumentRoot/eg-259/examples/lecture19'' and created the cars database using //phpMyAdmin//. Data for cars database etc, is available on Blackboard site. * //The initial form//: Access to the corvettes database

Try:

SELECT Vette_id, Body_style, Year, States.State
FROM Corvettes, States
WHERE Corvettes.State = States.State_id AND States.State = 'California'
Please enter your query:


* //The query result page//: Access the cars database with MySQL The query is: " . $query_html . "

"; // Execute the query $result = mysql_query($query); if (!$result) { print "Error - the query could not be executed"; $error = mysql_error(); print "

" . $error . "

"; exit ; } // Display the results in a table print ""; print ""; // Get the number of rows in the result, as well as the first row // and the number of fields in the rows $num_rows = mysql_num_rows($result); $row = mysql_fetch_array($result); $num_fields = mysql_num_fields($result); // Produce the column labels $keys = array_keys($row); for ($index = 0; $index < $num_fields; $index++) print ""; print ""; // Output the values of the fields in the rows for ($row_num = 0; $row_num < $num_rows; $row_num++) { print ""; $values = array_values($row); for ($index = 0; $index < $num_fields; $index++) { $value = htmlspecialchars($values[2 * $index + 1]); print " "; } print ""; $row = mysql_fetch_array($result); } print "

Query Results

" . $keys[2 * $index + 1] . "
" . $value . "
"; ?>
===== PHP/MySQL: Result ===== * //Result//: {{eg-259:l19-access_cars_php.png?800|A result of a typical query access cars}} ===== PHP/MySQL: Example 2 ===== * The form display document and the PHP processing document can be combined ===== Combining Form and Results ===== * After simply inserting the XHTML from the display document into the PHP document, several modifications are required: - Change the value of the ''action'' attribute of the form to the name of the combined document file - Create a //hidden// input element that sets its value when the document is first displayed. This provides a way for the document to determine which it is doing, displaying the form or processing the form data: - The PHP code to test this has the form: $stage = $_POST["stage"]; if (!IsSet($stage))) { ... } * the ''then'' clause includes the form processing; * the ''else'' clause includes the form display ===== Combining Form and Results ===== * Here is the result: [[http://eespectre.swan.ac.uk/~eechris/eg-259/examples/lecture19/access_cars2.php|access_cars2.php]] ( [[http://localhost/eg-259/examples/lecture19/access_cars2.php|access_cars2.php @ localhost]] ) ---- * //The code//: Access the cars database with MySQL

Try:

SELECT Vette_id, Body_style, Year, States.State
FROM Corvettes, States
WHERE Corvettes.State = States.State_id AND States.State = 'California'
Please enter your query:


The query is: " . $query_html . "

"; // Execute the query $result = mysql_query($query); if (!$result) { print "Error - the query could not be executed"; $error = mysql_error(); print "

" . $error . "

"; exit; } // Display the results in a table print ""; print ""; // Get the number of rows in the result, as well as the first row // and the number of fields in the rows $num_rows = mysql_num_rows($result); $row = mysql_fetch_array($result); $num_fields = mysql_num_fields($result); // Produce the column labels $keys = array_keys($row); for ($index = 0; $index < $num_fields; $index++) { print ""; } print ""; // Output the values of the fields in the rows for ($row_num = 0; $row_num < $num_rows; $row_num++) { print ""; $values = array_values($row); for ($index = 0; $index < $num_fields; $index++){ $value = htmlspecialchars($values[2 * $index + 1]); print " "; } print ""; $row = mysql_fetch_array($result); } print "

Query Results

" . $keys[2 * $index + 1] . "
" . $value . "
"; } ?>
===== Summary of this Lecture ===== //Introducing Databases and Database Access with PHP/MySQL// * [[eg-259:lecture19#relational_databases|Relational Databases]] * [[eg-259:extras:dbandsql|Introduction to SQL]] (not examined) * [[eg-259:lecture19#architectures_for_database_access|Architectures for Database Access]] * [[eg-259:lecture19#the_mysql_database_system|Introducing MySQL]] * [[eg-259:lecture19#database_access_with_php_mysql|Database Access with PHP and MySQL]] ====== Learning Outcomes ===== //At the end of this lecture you should be able to answer these questions//: - What is the purpose of a third tier in a client/server configuration for Web access to a database? - Why are two-tier client/server configurations sometimes inadequate? - At the end of this lecture you should be able to answer these questions: - Explain how SQL database access can be provided by extending a programming language. - What is the disadvantage of embedding SQL in a programming language? ===== Learning Outcomes (continued) ===== //At the end of this lecture you should be able to answer these questions//: - What is MySQL? - What does the MySQL constraint ''auto_increment'' do? - What is the problem with quotes in a SQL command obtained from a form element in an XHTML document? - What is the purpose of the PHP ''mysql_select_db'' function? - How can a PHP program determine the number of rows in a query result? ===== Learning Outcomes (continued) ===== //At the end of this lecture you should be able to answer these questions//: - What does the PHP function ''mysql_fetch_array'' do? - Explain the exact form of the value returned by ''mysql_fetch_array''. - What is metadata? - How is the collection of metadata extracted from a database? - How can column labels can be obtained from an object of metadata? ===== Homework Exercise ===== * Modify and test the program ''access_cars.php'' to handle ''UPDATE'' and ''INSERT'' SQL commands. ===== What's Next? ===== **Web Application Frameworks** * [[eg-259:lecture20#three-tiers_are_not_enough|Three-tiers are not enough!]] * [[eg-259:lecture20#the_problem_with_web_applications|The Problem of Web Application Development]] * [[eg-259:lecture20#web_application_frameworks_1|Web Application Frameworks]] * [[eg-259:lecture20#design_patterns_3_4|Design Patterns]] * [[eg-259:lecture20#case-studyruby-on-rails|Case-Study: Ruby-on-Rails]] [[eg-259:lecture18|Previous Lecture]] | [[eg-259:home]] | [[eg-259:lecture20|Next Lecture]]