Pro MySQL experts voice in open source phần 6 pptx

77 263 0
Pro MySQL experts voice in open source phần 6 pptx

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

Stored Procedures in MySQL Database vendors use a variety of programming languages and syntax for building and managing stored procedures. Many of these databases share a set of core SQL commands, but most of them have added extensions to facilitate the level of complexity that can be attained within the stored procedure. Oracle procedures are written in PL/SQL. Microsoft SQL Server 2000 procedures are written in Transact-SQL (T-SQL). To write procedures for PostgreSQL, you use PL/psSQL. Each implementation includes some common commands, and then an extended syntax for accomplishing more advanced logic. MySQL developers have taken the expected approach in their implementation of stored procedures. A database focused on simplicity and maximum performance would likely imple- ment a simple set of features that supply the most amount of control to users wanting to move logic into the database. MySQL has done this by implementing the SQL:2003 standard for stored procedures and has added minimal MySQL-specific syntax. In the cases where MySQL provides an extended use of a statement, the MySQL documentation (and this book) notes the extension to the standard. ■Note The official standard for stored procedures is ISO/IEC 9075-x:2003, where x is a range of numbers between 1 and 14 that indicate many different parts of the standard. For short, the standard is often referred to as SQL:2003, SQL-2003, or SQL 2003. We refer to the standard a SQL:2003, since the official specifica- tion uses the : as a separator, and MySQL documentation uses this format. The standard can be found on the ISO web site (http://www.iso.org) by doing a search for 9075. The standard is available for a fee. The SQL:2003 standard provides a basic set of commands for building multiple-statement interactions with the database. SQL:2003 was published in 2003 as the replacement for the pre- vious SQL standard, SQL:1999. These standards include specifications for syntax and behavior for SQL commands that are used to build, create, and maintain stored procedures. MySQL’s choice to stick to the SQL:2003 standard means that stored procedures created in MySQL can be seamlessly used in other databases that support this standard. Currently, IBM’s DB2 and Oracle Database 10g are compliant with SQL:2003. The success of moving a stored procedure from Ora- cle or DB2 into MySQL will depend on whether any of the vendor extensions have been used. Even if the vendor supports SQL:2003, if a stored procedure uses vendor-specific syntax, MySQL will fail on an unrecognized command when attempting to create the procedure. The MySQL implementation provides a wide array of controls for processing data and logic in the database. It doesn’t have the extended syntax bells and whistles of other database systems, but it does provide a rich set of basic commands that can create some incredibly powerful procedures. CHAPTER 9 ■ STORED PROCEDURES 353 505x_Ch09_FINAL.qxd 6/27/05 3:30 PM Page 353 Stored procedures are processed by the MySQL server, and they are independent of the storage engine used to store your data. If you use a feature of a particular storage engine in your stored procedure statement, you will need to continue to use that table type to use the stored procedure. MySQL stores the data for stored procedures in the proc table in the mysql database. Even though procedures are all stored in one place, they are created and called by either using the current database or by prepending a database name onto the various proce- dure statements. In the rest of this chapter, we’ll cover how to create, manage, and call MySQL stored procedures. Building Stored Procedures SQL:2003 sets forth a set of commands to create procedures; declare variables, handlers, and conditions; and set up cursors and constructs for flow control. In its simplest form, you can create a stored procedure with a CREATE statement, procedure name, and a single SQL statement. Listing 9-1 shows just how simple this can be. Listing 9-1. Creating a Single-Statement Procedure mysql> create procedure get_customers () SELECT customer_id,name FROM customer; ■Caution The stored procedure shown in Listing 9-1 has a SELECT statement as the last thing processed in the procedure, which returns a resultset to the caller.This is really convenient, but it is a MySQL extension to the SQL:2003 standard. The standard says you must put results into a variable or use a cursor to process a set of results. However frivolous Listing 9-1 may appear, it contains the required parts: a CREATE state- ment with a procedure name and a SQL statement. Calling the stored procedure to get the results is simple, as demonstrated in Listing 9-2. Listing 9-2. Calling a Single-Statement Procedure mysql> call get_customers (); + + + | customer_id | name | + + + | 1 | Mike | | 2 | Jay | | 3 | Johanna | | 4 | Michael | | 5 | Heidi | | 6 | Ezra | + + + 6 rows in set (0.00 sec) CHAPTER 9 ■ STORED PROCEDURES354 505x_Ch09_FINAL.qxd 6/27/05 3:30 PM Page 354 Other than abstracting the syntax of the query from the caller, this example doesn’t really justify creating a procedure. The same result is just as easily available with a single query from your application. As a more realistic example, let’s consider the scenario of merging duplicate accounts in your online ordering system. Your online store allows a user to create an account, with a user- defined login and password, to use for placing orders. Suppose user Mike places an order or two, and then doesn’t visit your site for a while. Then he returns and signs up again, inadver- tently creating a second account. He places a few more orders. At some point, he realizes that he has two accounts and puts in a request to have the old account removed. He says that he would prefer to keep all the old orders on the newer account. This means that in your database, you’ll need to find all the information associated with the old account, move it into the new account, and delete the old account. The new account record probably has core pieces of information like name, address, and phone, which won’t need to change. The data to be moved may include address book and payment information, as well as Mike’s orders. Anywhere in your system where a table has a relationship with your customer, you’ll need to make a change. Of course, you should check for the existence of the accounts, and the employee who makes that change may want to have a report of how many records were changed. Creating the series of statements to process this data merge in your code is possible, but using a procedure to handle it would simplify your application. Listing 9-3 demonstrates how a stored procedure might solve the requirements of this merge account request. Listing 9-3. Creating a Multistatement Stored Procedure DELIMITER // CREATE PROCEDURE merge_customers (IN old_id INT, IN new_id INT, OUT error VARCHAR(100)) SQL SECURITY DEFINER COMMENT 'merge customer accounts' BEGIN DECLARE old_count INT DEFAULT 0; DECLARE new_count INT DEFAULT 0; DECLARE addresses_changed INT DEFAULT 0; DECLARE payments_changed INT DEFAULT 0; DECLARE orders_changed INT DEFAULT 0; ## check to make sure the old_id and new_id exists SELECT count(*) INTO old_count FROM customer WHERE customer_id = old_id; SELECT count(*) INTO new_count FROM customer WHERE customer_id = new_id; IF !old_count THEN SET error = 'old id does not exist'; ELSEIF !new_count THEN SET error = 'new id does not exist'; ELSE UPDATE address SET customer_id = new_id WHERE customer_id = old_id; SELECT row_count() INTO addresses_changed; CHAPTER 9 ■ STORED PROCEDURES 355 505x_Ch09_FINAL.qxd 6/27/05 3:30 PM Page 355 UPDATE payment SET customer_id = new_id WHERE customer_id = old_id; SELECT row_count() INTO payments_changed; UPDATE cust_order SET customer_id = new_id WHERE customer_id = old_id; SELECT row_count() INTO orders_changed; DELETE FROM customer WHERE customer_id = old_id; SELECT addresses_changed,payments_changed,orders_changed; END IF; END // DELIMITER ; When entering multiple statement blocks into MySQL, you need to first change the default delimiter to something other than a semicolon (;), so MySQL will allow you to enter a ; without having the client process the input. Listing 9-3 begins by using the delimiter statement: DELIMITER //, which changes the delimiter to //. When you’re ready to have your procedure created, type //, and the client will process your entire procedure. When you’re finished working on your procedures, change the delimiter back to the standard semicolon with: DELIMITER ;, as you can see at the end of Listing 9-3. We’ll explain the other parts of this listing in detail shortly. Listing 9-4 shows how to call this procedure with the required parameters and get the results from the procedure. We’ll look at the details of executing stored procedures in the “Using Stored Procedures” section later in this chapter. Listing 9-4. Calling the Stored Procedure mysql> call merge_customers (1,4,@error); + + + + | addresses_changed | payments_changed | orders_changed | + + + + | 2 | 2 | 2 | + + + + 1 row in set (0.23 sec) Now, let’s step through each part of the stored procedure to see how it’s constructed and what options are available. CHAPTER 9 ■ STORED PROCEDURES356 505x_Ch09_FINAL.qxd 6/27/05 3:30 PM Page 356 The CREATE Statement You create a stored procedure using the CREATE statement, which takes a procedure name, fol- lowed by parameters in parentheses, followed by procedure characteristics, and ending with the series of statements to be run when the procedure is called. Here is the syntax: mysql> CREATE PROCEDURE [database.]<name> ([<parameters>]) [<characteristics>] <body statements> The name may be prefixed with a database name, and it must be followed by parentheses. If the database is not provided, MySQL creates the procedure in the current database or gives a No database selected error if a database is not active. Procedure names can be up to 64 characters long. ■Caution Avoid conflicts with built-in functions by not using built-in function names for your procedure. If you must have a procedure with the same name as a MySQL function, putting a space between the name and the parentheses will help MySQL differentiate between the two. For example, a build in function for get- ting all uppercase text is upper().We suggest you don’t, but if you must create a stored procedure with the same name, use upper () (note the space between the name and the opening parenthesis) to distinguish it from the built-in function. You can set parameters for a stored procedure using the following syntax: [IN|OUT|INOUT] <name> <data type> If you don’t specify IN, OUT, or INOUT for the parameter, it will default to IN. These three types of parameters work as follows: • An IN parameter is set and passed into the stored procedure to use internally in its processing. • An OUT parameter is set within the procedure, but accessed by the caller. • An INOUT parameter is passed into the procedure for internal use, but is also available to the caller after the procedure has completed. The name and data type of the parameter are used in the stored procedure for referencing and setting values going in and out of the procedure. The data type can be any valid data type for MySQL, and it specifies what type of data will be stored in the parameter. You’ll see a detailed example of passing arguments in and out of a procedure in the “Using Stored Procedures” sec- tion (Listings 9-13 and 9-16) later in this chapter. CHAPTER 9 ■ STORED PROCEDURES 357 505x_Ch09_FINAL.qxd 6/27/05 3:30 PM Page 357 The stored procedure characteristics include a number of options for how the stored pro- cedure behaves. Table 9-1 lists the available options with a description of how they affect the stored procedure. Table 9-1. Characteristics Used to Create a Stored Procedure Characteristic Value Description LANGUAGE SQL This is the language that was used to write the stored procedure. While MySQL intends to implement other languages with external procedures, currently SQL is the only valid option. SQL SECURITY DEFINER or INVOKER The SQL SECURITY characteristic tells MySQL which user to use for permissions when running the procedure. If it’s set to DEFINER, the stored procedure will be run using the privileges of the user who created the procedure. If INVOKER is specified, the user calling the procedure will be used for obtaining access to the tables. The default, if not specified, is DEFINER. COMMENT The COMMENT characteristic is a place to enter notes about a stored procedure. The comment is displayed in SHOW CREATE PROCEDURE commands. ■Caution The COMMENT characteristic is an extension to SQL:2003, which means that procedures with a comment in the definition may not easily move to another SQL:2003-compliant database. The Procedure Body The body of a stored procedure contains the collection of SQL statements that make up the actual procedure. In addition to the typical SQL statements you use to interact with data in your database, the SQL:2003 specification includes a number of additional commands to store variables, make decisions, and loop over sets of records. ■Note MySQL allows you to put Data Definition Language (DDL) statements (CREATE, ALTER, and so on) in the body of a stored procedure. This is part of the SQL:2003 standard, but it is labeled as an optional feature and may not be supported in other databases that comply with the standard. CHAPTER 9 ■ STORED PROCEDURES358 505x_Ch09_FINAL.qxd 6/27/05 3:30 PM Page 358 BEGIN and END Statements You use the BEGIN and END statements to group statements in procedures with more than one SQL statement. Declarations can be made only within a BEGIN . . . END block. You can define a label for the block to clarify your code, as shown here: customer: BEGIN <SQL statement>; <SQL statement>; END customer The labels must match exactly. The DECLARE Statement The DECLARE statement is used to create local variables, conditions, handlers, and cursors within the procedure. You can use DECLARE only as the first statements immediately within a BEGIN block. The declarations must occur with variables first, cursors second, and handlers last. A common declaration is the local variable, which is done with a variable name and type: DECLARE <name> <data type> [DEFAULT]; Variable declarations can use any valid data type for MySQL, and may include an optional default value. In Listing 9-3, several declarations are made, including a number of variables for counting items as the statements in the procedure are processed: DECLARE new_count INT DEFAULT 0; Here, we’ll look at how to declare variables, conditions, and handlers. Cursors are covered in more detail in Chapter 11. Variables Stored procedures can access and set local, session, and global variables. Local variables are either passed in as parameters or created using the DECLARE statement, and they are used in the stored procedure by referencing the name of the parameter or declared variable. You can set variables in several ways. Using the DECLARE statement with a DEFAULT will set the value of a local variable: DECLARE customer_count INT DEFAULT 0; You can assign values to local, session, and global variables using the SET statement: SET customer_count = 5; MySQL’s SET statement includes an extension to the SQL:2003 standard that permits setting multiple variables in one statement: SET customer_count = 5, order_count = 50; CHAPTER 9 ■ STORED PROCEDURES 359 505x_Ch09_FINAL.qxd 6/27/05 3:30 PM Page 359 ■Caution Setting multiple variables in a single statement is a MySQL extension to the SQL:2003 standard. Using this syntax may make your procedures less portable. Using SELECT . . . INTO is another method for setting variables within your stored pro- cedure. This allows you to query a table and push the results into a variable as a part of the query. SELECT . . . INTO works only if you are selecting a single row of data: SELECT COUNT(*) INTO customer_count FROM customer; You can also select multiple values into multiple variables: SELECT customer_id,name INTO new_id,new_name FROM customer LIMIT 1; ■Caution Use caution when creating variables in stored procedures. If variable names are the same as field names in a table, you may encounter unexpected results. You might want to define a naming convention for all variables in stored procedures to avoid conflicts with other items in the namespace. Conditions and Handlers When making declarations in your stored procedure, your list of declarations can include statements to indicate special handling when certain conditions arise. When you have a col- lection of statements being processed, being able to detect the outcome of those statements and proactively do something to help the procedure be successful can be important to your caller. Suppose one of the stored procedures created for your online store included a statement to update the customer’s name. The column for the customer’s name is CHAR(10), which is smaller than you would like, but is the most your legacy order-entry system can handle. The normal behavior for MySQL when updating a record is to truncate the inserted value to a length that fits the column. For numerous reasons, this is unacceptable to you. Fortunately, when MySQL does a truncation, it issues a warning and returns an error, and also sets the SQLSTATE to indicate that during the query, the data was truncated. ■Note More than 2,000 error numbers can be raised as errors or warnings from MySQL. Each MySQL error number has a message and a corresponding SQLSTATE value. For the details of each error number and its meaning, see http://dev.mysql.com/doc/mysql/en/Error-handling.html. Handlers are designed to detect when certain errors or warnings have been triggered by statements and allow you to take action. A handler is declared with a handler type, condition, and statement: DECLARE <handler type> HANDLER FOR <condition> <statement>; CHAPTER 9 ■ STORED PROCEDURES360 505x_Ch09_FINAL.qxd 6/27/05 3:30 PM Page 360 Handler Types The handler type is either CONTINUE or EXIT. 3 CONTINUE means that when a certain error or warning is issued, MySQL will run the provided statement and continue running the state- ments in the procedure. The EXIT handler type tells MySQL that when the condition is met, it should run the statement and exit the current BEGIN . . . END block. Here’s a handler statement with an EXIT handler type: DECLARE EXIT HANDLER FOR truncated_name UPDATE customer SET name = old_name WHERE customer_id = cust_id; In this statement, the EXIT handler type tells the procedure to execute the statement, and then exit when a truncation occurs. Conditions The handler condition is what triggers the handler to act. You can define your own conditions and reference them by name, or choose from a set of conditions that are provided by default in MySQL. Table 9-2 shows the MySQL handler conditions. Table 9-2. MySQL Handler Conditions Condition Description SQLSTATE '<number>' A specific warning or error number, which is described in the MySQL documentation. The number must be enclosed in quotes (typically single). <self-defined condition name> The name of the self-defined condition you created using the DECLARE . . . CONDITION statement. SQLWARNING Matches any SQLSTATE that begins with 01. Using this condition will allow you to catch a wide range of states. NOT FOUND Matches any SQLSTATE beginning with 02. Using this state lets you catch any instance where the query references a missing table, database, and so on. SQLEXCEPTION Matches every SQLSTATE except those beginning with 01 or 02. <MySQL error> Using a specific error will cause the handler to execute for the specific MySQL error. ■Tip Creating self-defined conditions improves readability of your code. Rather than using the MySQL error or SQLSTATE number, you are assigning a name to that state, which will be more understandable than just having the number. CHAPTER 9 ■ STORED PROCEDURES 361 3. The UNDO handler type, which is part of the SQL:2003 specification, is not currently supported in MySQL. 505x_Ch09_FINAL.qxd 6/27/05 3:30 PM Page 361 To create a self-defined condition, use a condition declaration with a name and a value: DECLARE <condition name> CONDITION FOR <condition value>; The condition name will be used in a DECLARE . . . HANDLER definition. The condition value can be either a MySQL error number or a SQLSTATE code. For example, to catch when some data has been truncated, the condition declaration with the MySQL error number looks like this: DECLARE truncated_name CONDITION FOR 1265; Or if you wanted to use the SQLSTATE number, you would write the same statement like this: DECLARE truncated_name CONDITION FOR SQLSTATE '01000'; ■Caution A single SQLSTATE value can be assigned to multiple MySQL error numbers, meaning that if you use the SQLSTATE numbers, you may have different errors that generate the same SQLSTATE. This can help or hinder the effectiveness of your handler. In some cases, you want to match all occurrences of a cer- tain type of error, which are grouped under a certain SQLSTATE. In the example, we want to find a very specific error, so it makes more sense to use the MySQL error code. Statements The last piece of the handler declaration is a statement, which will be run before the stored procedure either continues or exits, depending on the handler type you chose. For example, to catch a case where the name had been truncated, your stored procedure might look like the one shown in Listing 9-5. Listing 9-5. Declaring a Condition and Handler DELIMITER // CREATE PROCEDURE update_name (IN cust_id INT, IN new_name VARCHAR(20)) BEGIN DECLARE old_name VARCHAR(10); DECLARE truncated_name CONDITION for 1265; DECLARE EXIT HANDLER FOR truncated_name UPDATE customer SET name = old_name WHERE customer_id = cust_id; SELECT name INTO old_name FROM customer WHERE customer_id = cust_id; UPDATE customer SET name = new_name WHERE customer_id = cust_id; SELECT customer_id,name FROM customer WHERE customer_id = cust_id; END // DELIMITER ; The update_name procedure accepts a customer ID (cust_id) and a new name (new_name). The first two statements declare a variable to store the old name and a condition named CHAPTER 9 ■ STORED PROCEDURES362 505x_Ch09_FINAL.qxd 6/27/05 3:30 PM Page 362 [...]... procedure 367 505x_Ch09_FINAL.qxd 368 6/ 27/05 3:30 PM Page 368 CHAPTER 9 ■ STORED PROCEDURES To merge two of these customers by calling the merge_customers procedure (created in Listing 9-3) adds a little more complexity because you must pass IN and OUT parameters to the procedure A simple way to do this is shown in Listing 9- 16 Listing 9- 16 Calling a Stored Procedure with Parameters from PHP . database level (in the mysql. db table), or for a specific routine (in the mysql. procs_priv table). Creating and altering permissions: To govern creating and altering a stored procedure, MySQL uses. at http://www.php.net/mysqli. CHAPTER 9 ■ STORED PROCEDURES 368 505x_Ch09_FINAL.qxd 6/ 27/05 3:30 PM Page 368 Managing Stored Procedures Most of the work in an environment where stored procedures are used is in creating. for MySQL, and may include an optional default value. In Listing 9-3, several declarations are made, including a number of variables for counting items as the statements in the procedure are processed: DECLARE

Ngày đăng: 08/08/2014, 20:21

Từ khóa liên quan

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan