Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 77 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
77
Dung lượng
496,26 KB
Nội dung
Listing 12-12. Output of a View with a HAVING Clause mysql> SELECT * FROM small_ship_dates; + + + | ship_date | number_of_orders | + + + | 2005-08-27 | 1 | | 2005-08-28 | 1 | | 2005-08-31 | 1 | | 2005-09-10 | 1 | | 2005-09-27 | 1 | + + + 5 rows in set (0.00 sec) Unioned Tables Views can also be created by two or more SELECT statements joined together with a UNION statement. As explained in Chapter 7, the UNION statement allows you to join multiple queries that have the same fields. To illustrate how multiple SQL statements might be joined with a UNION, suppose our online ordering system forwards the order to a certain fulfillment center based on the geo- graphic location of the person placing the order. Each center keeps a separate record of the customers. We want to provide a way to query customers across all centers, so we pull their databases onto a single server and create a view that centralizes their databases onto a single table using a UNION statement. Listing 12-13 shows a sample of the customer table from the region 1 database. Listing 12-13. Sample Customer Database from Region 1 mysql> SELECT * FROM region1.customer; + + + | customer_id | name | + + + | 1 | Mike | | 2 | Jay | + + + 2 rows in set (0.00 sec) We can easily create a view that pulls data from all three regions with the CREATE statement shown in Listing 12-14. Listing 12-14. Creating a View with UNION mysql> CREATE VIEW all_customers AS SELECT * FROM region1.customer UNION SELECT * FROM region2.customer UNION SELECT * FROM region3.customer; CHAPTER 12 ■ VIEWS430 505x_Ch12_FINAL.qxd 6/27/05 3:32 PM Page 430 A simple SELECT statement will now present results from all three tables, as shown in Listing 12-15. Listing 12-15. Output of Selecting from the View Created with UNION mysql> SELECT * FROM all_customers; + + + | customer_id | name | + + + | 1 | Mike | | 2 | Jay | | 3 | Johanna | | 4 | Michael | | 5 | Heidi | | 6 | Ezra | + + + 6 rows in set (0.00 sec) Listing 12-15 offers a convenient snapshot of the customer data pulled from the three different regions. The view might be more useful if, along with the combined data, we also included the data source for each customer record. Listing 12-16 presents a statement for creating a view that will include a column indicating from which region the customer record originates. Listing 12-16. Creating a UNION View with a Data Source mysql> CREATE OR REPLACE VIEW all_customers (region, customer_id, name) AS SELECT 1, customer_id, name FROM region1.customer UNION SELECT 2, customer_id, name FROM region2.customer UNION SELECT 3, customer_id, name FROM region3.customer; The output from a simple SELECT statement applied to the all_customers table now includes the number of the region where the data resides, as shown in Listing 12-17. Listing 12-17. Output of a UNION View with a Data Source mysql> SELECT * FROM all_customers; + + + + | region | customer_id | name | + + + + | 1 | 1 | Mike | | 1 | 2 | Jay | | 2 | 3 | Johanna | | 2 | 4 | Michael | | 3 | 5 | Heidi | | 3 | 6 | Ezra | + + + + 6 rows in set (0.00 sec) CHAPTER 12 ■ VIEWS 431 505x_Ch12_FINAL.qxd 6/27/05 3:32 PM Page 431 Check Options When creating an updatable view (a view that is part of an UPDATE, INSERT, or DELETE state- ment, as described in the next section), MySQL allows you to specify how much the parser will do when processing an update. This is done with the WITH CHECK OPTION syntax tacked onto the end of your SQL statement when creating a view. Enabling check options tells the parser to review the WHERE clause that defines the view when processing a statement to update a record or set of records in the view. With check options enabled, you aren’t allowed to insert, update, or delete any records from the view (and subsequently the underlying table) unless the INSERT, UPDATE, or DELETE statement affects rows available within the view. Two keywords can be added to the WITH CHECK OPTION statement: LOCAL and CASCADING. The default, LOCAL, tells the query parser that when a user is attempting to update a view, a check should be made of the SELECT statement that defines the view to ensure that the data being updated is part of the view. Consider a previous example from Listing 12-2, which cre- ated a view to display customer records from region 1. The view is updatable, but its CREATE statement doesn’t include the CHECK OPTION syntax. In this case, a user can create an entry in the table for region 2, even though the view doesn’t permit the user to see customers from region 2. Listing 12-18 shows the CREATE statement with the WITH LOCAL CHECK OPTION set to limit updates. Listing 12-18. Creating a View with Check Options mysql> CREATE OR REPLACE VIEW customer_region1 AS SELECT customer_id, name, region FROM customer WHERE region = 1 WITH LOCAL CHECK OPTION; An attempted update to the customer_region1 view to set the region to a value not included in the view results in a MySQL error is shown in Listing 12-19. Listing 12-19. Illegal Update of a View with Check Options mysql> UPDATE customer_region1 SET region = 2 WHERE customer_id = 1; ERROR 1369 (HY000): CHECK OPTION failed 'shop.customer_region1' ■Note WITH CHECK OPTION is used with only an updatable view. If the algorithm is set to TEMPTABLE,or the SQL statement uses syntax or a keyword that makes the view not updatable, specifying WITH CHECK OPTION will result in a MySQL error: ERROR 1368 (HY000) at line 5: CHECK OPTION on ➥ non-updatable view. CHAPTER 12 ■ VIEWS432 505x_Ch12_FINAL.qxd 6/27/05 3:32 PM Page 432 The CASCADING option checks both the current view, and if the current view is based on another view, the check looks at that view as well to verify that the change conforms to the view definition. With the CASCADING keyword, the query parser continues down through all views until the parser reaches a table to verify that all column and row changes that are in the issued statement are defined in the hierarchy of views. Creating views based on other views is covered in the “Defining Views of Views” section later in this chapter. ■Caution The CASCADE modifier to WITH CHECK OPTION is not part of the SQL:2003 specification. Use of this option, while helpful for views of views, may result in incompatible CREATE statements in other database systems. Creating Updatable Views Depending on the complexity of your views, you may be able to create views that can do more than provide output of data. Views in MySQL are meant to be updatable, as long as the SQL statement that creates the view doesn’t represent the underlying tables in such a way that an update to the underlying data would be impossible to map through the view. We use the term updatable to mean that a view can be a part of an UPDATE, an INSERT, or a DELETE statement. To be updatable, the records in the view must have a one-to-one relationship with the records in the underlying tables. Beyond that general restriction, a few other rules determine if a view can be updated. The easiest way to describe what kinds of views are updatable is to define the conditions under which a view becomes disqualified from being updatable. Views are not updatable in the following cases: • The view is created with the algorithm specified as TEMPTABLE. •A table in the FROM clause is reference by a subquery in the WHERE statement. • There is a subquery in the SELECT clause. • The SQL statement defining the view joins tables. •One of the tables in the FROM clause is a non-updatable view. • The SELECT statement of the view contains an aggregate function such as SUM(), COUNT(), MAX(), MIN(), and so on. • The keywords DISTINCT, GROUP BY, HAVING, UNION, or UNION ALL appear in the defining SQL statement. As MySQL parses the query, it will consider the rules and mark the view as non-updatable if any of the conditions are met. If none of these conditions is met, you will have an updatable view. CHAPTER 12 ■ VIEWS 433 505x_Ch12_FINAL.qxd 6/27/05 3:32 PM Page 433 To illustrate, let’s go back to our example where we created a view to control which cus- tomers could be viewed for employees in different regions. The data in the customer table is shown in Listing 12-20. Listing 12-20. Records in the customer Table + + + + | customer_id | region | name | + + + + | 1 | 1 | Mike | | 2 | 1 | Jay | | 3 | 2 | Johanna | | 4 | 2 | Michael | | 5 | 3 | Heidi | | 6 | 3 | Ezra | + + + + Creating a view that shows just the records from region 3 will give us a one-to-one rela- tionship between the records in the view and those in the customer table. Listing 12-21 shows the creation of the customer_region3 view. Listing 12-21. Creating an Updatable View CREATE OR REPLACE VIEW customer_region3 AS SELECT customer_id, name, region FROM customer WHERE region = 3 WITH LOCAL CHECK OPTION; A SELECT statement of all the records in this view shows that we’re getting only the appro- priate records, as shown in Listing 12-22. Listing 12-22. Records in the customer_region3 View mysql> SELECT * FROM customer_region3; + + + + | customer_id | name | region | + + + + | 5 | Heidi | 3 | | 6 | Ezra | 3 | + + + + 2 rows in set (0.00 sec) Because this view doesn’t violate any of the criteria for creating an updatable view, we are allowed to update one of the records: mysql> UPDATE customer_region3 SET name = 'David' WHERE customer_id = 6; Query OK, 1 row affected (0.01 sec) CHAPTER 12 ■ VIEWS434 505x_Ch12_FINAL.qxd 6/27/05 3:32 PM Page 434 If we had specified TEMPTABLE as the algorithm, or had used some other syntax that would cause the parser to mark the view as non-updatable, we would have a different response to our attempt to update: mysql> UPDATE customer_region3 SET name = 'David' WHERE customer_id = 6; ERROR 1288 (HY000): The target table customer_region3 of the UPDATE is not updatable Becoming familiar with the different rules for making a view updatable takes some time and practice. For more reading on MySQL’s view implementation and the rules regarding updatable views, see http://dev.mysql.com/doc/mysql/en/create-view.html. Defining Views of Views Not only does MySQL allow you to create virtual representations of data in tables, you can also create a virtual representation of a view, or a view of a view. This can go as many levels deep as you can maintain. Creating a view of a view is identical to creating a view of a table. You use the same CREATE ➥ VIEW statement, but instead of naming a table in the SQL statement, you use the name of a view. A view of a view can be a handy way to create cascading levels of access to data. One sce- nario might involve a table filled with customer order and payment information. At the global level, you might have a view that excludes payment information, for the global support staff. At the regional level, you might provide two views: one with all information for a particular region and a second view of everything except for the payment information. This scenario is outlined in Table 12-1. Table 12-1. Cascading Levels of Information for an Online Ordering System View Name Staff Position Available Information manage_all_orders Global manager Customer number, address, ordered items, payment information for all regions support_all_orders Global customer support Customer number, address, ordered items for all regions manage_region_orders Regional manager Customer number, address, ordered items, payment information for single region support_region_orders Regional customer support Customer number, address, ordered items for single region As discussed earlier in the section on creating views, the CASCADING parameter of WITH ➥ CHECK OPTION is designed to ensure that when you are using views of views, the statement checks to determine if permissions on making updates to a table will cascade down through all the view levels. As the check moves down through the levels of views, it checks to make sure the INSERT, UPDATE, or DELETE operation is being made on data that is available in your view. As you add more layers with views, it’s important to consider performance issues with views. View performance is discussed near the end of this chapter. Also, consider if using views of views adds an extra layer of unnecessary complexity. CHAPTER 12 ■ VIEWS 435 505x_Ch12_FINAL.qxd 6/27/05 3:32 PM Page 435 Managing Views Once you have a set of views in place, you’ll likely need to manage those views. MySQL pro- vides commands to display, change, and remove views. Displaying Views You can use the SHOW CREATE VIEW command to view the entire CREATE syntax used when cre- ating a view: SHOW CREATE VIEW [<database name>.]name Listing 12-23 displays the output from the SHOW CREATE VIEW for the all_customers view (using the \G option for output in rows). Listing 12-23. Output of SHOW CREATE VIEW mysql> SHOW CREATE VIEW all_customers\G *************************** 1. row *************************** View: all_customers Create View: CREATE ALGORITHM=UNDEFINED VIEW `shop`.`all_customers` AS select 1 AS `region`,`region1`.`customer`.`customer_id` AS `customer_id`,`region1`.`customer`.`name` AS `name` from `region1`.`customer` union select 2 AS `2`,`region2`.`customer`.`customer_id` AS `customer_id`,`region2`.`customer`.`name` AS `name` from `region2`.`customer` union select 3 AS `3`,`region3`.`customer`.`customer_id` AS `customer_id`,`region3`.`customer`.`name` AS `name` from `region3`.`customer` 1 row in set (0.00 sec) SHOW CREATE VIEW doesn’t produce the most readable output (we’ve inserted some line breaks for formatting), but it will provide you with a statement that can be used to re-create the view. If you require something more readable, and are more interested in seeing the col- umn names and data types, the DESCRIBE statement works on a view just as it does on a table. Listing 12-24 shows the output from a DESCRIBE on the all_customers table. Listing 12-24. Output of DESCRIBE all_customers mysql> DESCRIBE all_customers; + + + + + + + | Field | Type | Null | Key | Default | Extra | + + + + + + + | region | bigint(20) | NO | | 0 | | | customer_id | int(11) | NO | | 0 | | | name | varchar(10) | YES | | NULL | | + + + + + + + 3 rows in set (0.00 sec) CHAPTER 12 ■ VIEWS436 505x_Ch12_FINAL.qxd 6/27/05 3:32 PM Page 436 One other place to find information about your views is in the data dictionary file. The data dictionary file is stored in the directory with the data files for the database. The view name is used to name the .frm file. If your data directory is /data/mysql, the ship_summary view diction- ary file can be found at /data/mysql/shop/ship_summary.frm. A look inside this file reveals numerous expected fields and values, plus some additional ones, as shown in Listing 12-25. Listing 12-25. The ship_summary.frm Data Dictionary File shell> cat /data/mysql/shop/ship_summary.frm TYPE=VIEW query=select `shop`.`cust_order`.`ship_date` AS `date`, count(`shop`.`cust_order`.`ship_date`) AS `number_of_orders` from `shop`.`cust_order` group by `shop`.`cust_order`.`ship_date` md5=492eb8a32a6bd3b57b5f9f73be4db621 updatable=0 algorithm=1 with_check_option=0 revision=1 timestamp=2005-04-27 19:44:43 create-version=1 source=CREATE ALGORITHM = TEMPTABLE VIEW ship_summary\n (date,number_of_orders) AS\n SELECT ship_date, count(ship_date)\n FROM cust_order\n GROUP BY ship_date The TYPE, updatable, algorithm, with_check_option, and source fields contain values we set and would expect to be in the definition. The following fields are used internally by MySQL, but they can provide valuable information: • query: This information is the internal representation of the view’s SELECT statement. • md5: This field stores a hash of the view for verification that the data dictionary hasn’t changed. • revision: This keeps track of the version number of the view. • timestamp: This maintains the date and time of the CREATE or last ALTER statement. • create-version: This is always set to 1 and doesn’t appear to be currently in use, but perhaps will serve a purpose in the future. ■Note You may notice that in the ship_summary.frm data dictionary file, the query field looks different from the source. When MySQL gets the CREATE statement, it takes the field labels specified after the view name and maps them to the <column name> AS <label> syntax for internal use. While we continue to recommend using the label definitions instead of the AS statement, it is interesting to see how MySQL trans- forms the CREATE statement for internal use. In this case, we’re seeing the syntax of the SQL:2003 standard being mapped to the syntax understood by the existing MySQL query parser. CHAPTER 12 ■ VIEWS 437 505x_Ch12_FINAL.qxd 6/27/05 3:32 PM Page 437 Changing Views The ALTER VIEW statement is the same as the CREATE statement, except for the omission of the OR REPLACE option. In fact, the ALTER VIEW statement does the same thing as CREATE OR ➥ REPLACE, except that in the case of ALTER, a view of the same name must already exist. Lack of a view with the same name will result in a MySQL error. In altering a view, you are required to specify the attributes, columns, and SQL statement. None of these items is required to stay the same as the currently defined view, except for the name. The full ALTER statement looks like this: ALTER [<algorithm attributes>] VIEW [<database>.]< name> [(<columns>)] AS <SELECT statement> [<check options>] The algorithm attributes, database, name, columns, SELECT statement, and check options are covered in detail in the previous section detailing the syntax of the CREATE statement. To demonstrate using the ALTER VIEW command, suppose the customer support staff has been using the view created in Listing 12-16, which uses a UNION of multiple customer tables, but now they have started complaining about it. They would like to see the following changes: • The query results return a region number, but the regions had been recently assigned names, and nobody remembers the region numbers anymore. Rather than seeing region numbers in their SELECT statements, they want to have the appropriate region name instead. •Case-sensitivity issues involving the customer table’s name have prompted requests to capitalize the output of the name column (the names are being used to programmati- cally compare customer data with names from a purchased mailing list). • The shipping labels have problems if the names are too long, prompting a request to provide a column highlighting the name length, so they can scan down and ensure none of the labels will be misprinted. All of these requests are easy to accommodate with a few changes to the previous view definition: change the region to the appropriate names, add a function that changes the name to uppercase, and add a new column that is a count of the characters in the name column. The ALTER VIEW statement to make these changes is shown in Listing 12-26. Listing 12-26. ALTER VIEW Statement mysql> ALTER VIEW all_customers (region,customer_id,name,name_length) AS SELECT 'northeast', customer_id, upper(name), length(name) FROM region1.customer UNION SELECT 'northwest', customer_id, UPPER(name), LENGTH(name) FROM region2.customer UNION SELECT 'south', customer_id, upper(name), length(name) FROM region3.customer; Now the customer support folks will be happier with the query results, and perhaps be less prone to making mistakes with the zones and package labels. Listing 12-27 shows the output of the altered view. CHAPTER 12 ■ VIEWS438 505x_Ch12_FINAL.qxd 6/27/05 3:32 PM Page 438 Listing 12-27. Output from the Altered View mysql> SELECT * FROM all_customers; + + + + + | region | customer_id | name | name_length | + + + + + | northeast | 1 | MIKE | 4 | | northeast | 2 | JAY | 3 | | northwest | 3 | JOHANNA | 7 | | northwest | 4 | MICHAEL | 7 | | south | 5 | HEIDI | 5 | | south | 6 | EZRA | 4 | + + + + + 6 rows in set (0.00 sec) ■Note Listings 12-26 and 12-27 demonstrate a simple example of using functions in the view definition to create new data, which isn’t part of the underlying tables. In the all_customers view, the name_length column doesn’t exist in the underlying tables, but is the value returned from a function. Views are an excel- lent way to present new results derived from performing functions on or calculations with existing data. Removing Views To delete a view, use the DROP VIEW command. As with all DROP commands (index, table, proce- dure, database, and so on), DROP VIEW takes one argument: the name of the view to be dropped. DROP VIEW [IF EXISTS] [<database>.]<name> For example, to drop the all_customers view, issue this statement: mysql> DROP VIEW all_customers; A database name can be prepended to the view name if you want to be explicit or are dropping a view in a database other than the current, active database. You can add the IF EXISTS syntax if you would like to prevent an error from occurring if the view does not exist. A warning is generated when removing a nonexistent view with the IF EXISTS syntax. ■Tip When a view is altered or replaced, MySQL makes a backup copy of the data dictionary file in <datadir>/<database name>/arc.A copy is not made when the view is dropped. If you accidentally drop a view, check the arc directory for an old copy that was saved on an ALTER or REPLACE operation. You may be able to use that copy for re-creating the view. CHAPTER 12 ■ VIEWS 439 505x_Ch12_FINAL.qxd 6/27/05 3:32 PM Page 439 [...]... Chapter 9 includes a discussion regarding the practicality of using stored procedures That discussion contains a number of points similar to the arguments presented in this chapter for using triggers, and might provoke some additional thoughts on how to decide to use database technology Triggers in MySQL MySQL aims at using the SQL standards when implementing new or updating existing functionality MySQL. .. shown in Listing 13-22 Listing 13-22 Delete Trigger for Performance Testing DELIMITER // CREATE TRIGGER after_cust_order_delete AFTER DELETE on cust_order FOR EACH ROW BEGIN IF @insert_count IS NULL THEN SET @insert_count = 0; END IF; SET @insert_count = @insert_count + 1; END // DELIMITER ; Our intention in testing was to determine how much overhead is involved in the inclusion of the trigger in the... fields in the incoming record with NEW. Listings 13-3 and 13 -7 showed examples of using the OLD syntax: customer_id = OLD.customer_id, name = OLD.name, You’ll see examples of the NEW syntax in getting and setting record values in upcoming examples 4 We attempted to find a limit for the number of lines in a trigger However, after successfully running a script-generated, one million-line trigger... performance, indexes on underlying tables should be designed to match the SELECT statement used in defining views ■ Note Views do not have indexes of their own They rely on the indexes of the underlying tables to provide optimized lookups If your data is well organized and your indexes are in good condition, your views will perform well In essence, when using the MERGE algorithm, MySQL creates a new, single... environment Using EXPLAIN As with queries against tables, you can use the EXPLAIN syntax on a query of a view: EXPLAIN SELECT * FROM all_orders WHERE customer_id = 1; The output of the EXPLAIN will reflect the indexes of the underlying tables, not the view itself, as views do not have indexes See Chapters 6 and 7 for details on interpreting the output of EXPLAIN Summary In this chapter, we’ve introduced... comes in contact with your database or data The ability to rearrange, compile, combine, limit, relabel, hide, and sort data in virtual tables opens up endless possibilities in meeting the demands of your data destinations 505x_Ch13_FINAL.qxd 6/ 27/ 05 3:34 PM CHAPTER Page 443 13 ■■■ Triggers W ith the introduction of triggers in versions 5.0.2 and greater, MySQL provides more built -in support for helping... can include declaration and flow control statements to build decision-making mechanisms into the trigger Tools for managing triggers are limited The CREATE and DROP statements are the only tools provided for managing triggers in the database Triggers are viewed using the INFORMATION_ SCHEMA in MySQL Check MySQL' s trigger documentation for up-to-the-minute information about the release of more administrative... NEW.item_sum + NEW.shipping; ELSE SET NEW.total = NEW.item_sum (NEW.discount_percent/100 * NEW.item_sum) + NEW.shipping; END IF; END // DELIMITER ; Now, let’s see what happens when we try to insert a record into the cust_order table and ask for a discount of 24%, as shown in Listing 13-14 Listing 13-14 Inserting into the cust_order Table with an Invalid Discount mysql> INSERT INTO cust_order SET ship_date='2005-08-12',... PostgreSQL 505x_Ch13_FINAL.qxd 6/ 27/ 05 3:34 PM Page 4 47 CHAPTER 13 ■ TRIGGERS MySQL triggers are independent of the storage engines used to store the data They can be used with any of the available storage engines (See Chapter 5 for details on MySQL storage engines.) In MySQL, triggers are stored in . and source fields contain values we set and would expect to be in the definition. The following fields are used internally by MySQL, but they can provide valuable information: • query: This information. syntax for internal use. While we continue to recommend using the label definitions instead of the AS statement, it is interesting to see how MySQL trans- forms the CREATE statement for internal. EXPLAIN will reflect the indexes of the underlying tables, not the view itself, as views do not have indexes. See Chapters 6 and 7 for details on interpreting the output of EXPLAIN. Summary In