Tài liệu MySQL Administrator’s Bible- P7 pptx

50 299 0
Tài liệu MySQL Administrator’s Bible- P7 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 Routines, Triggers, and Events 7 continued Whether or not a stored routine is deterministic is important due to binary logging. A deterministic stored routine will replicate without a problem; however, a stored routine that is not deterministic may have problems replicating. If binary logging is set as statement-based (see Chapter 16), the binary log contains the statements that change data, so they can be replayed during an incremental restore or during replication. A stored routine that is not deterministic may have a different output given the same input, which means that an incremental restore or slave will not have data that matches the original data. Be very careful when using a stored routine that is not deterministic, because statement-based binary logging may not be adequate to store the data changes. If data integrity is a concern, use row-based binary logging or a deterministic stored routine instead. Unfortunately, at the time of this writing, the DETERMINISTIC and NOT DETERMINISTIC options serve only as comments, and are not verified by mysqld . There are no warnings or errors if a non-deterministic routine is set as DETERMINISTIC . MySQL will throw an error and refuse to create a stored function if binary logging of that function may be unsafe: ERROR 1418 (HY000): This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_ creators variable) The best way to fix this problem is to declare the function to be DETERMINISTIC , NO SQL ,or READS DATA . The next best way is to have a user with the SUPER privilege define the function. Turning binary logging off is another way to fix this issue, though it may not be possible. Setting log_bin_trust_function_creators to 1 will also fix this issue, though it is less safe because you may end up attempting to replicate a function that is not safe for replication. SQL usage The remaining option is what SQL statements the stored routine uses. These values are for informational purposes only, and do not affect the way mysqld handles the stored routine. The possible values are: ■ MODIFIES SQL DATA — The stored routine may update data (with a DELETE , INSERT ,or UPDATE command, for instance). ■ READS SQL DATA — The stored routine does not contain SQL to write data (as in MODI- FIES SQL DATA ) but does contain SQL that reads data (that is, SELECT statements). The store_offerings stored procedure is an example of a stored routine that qualifies as READS SQL DATA . ■ CONTAINS SQL — The stored routine does not read or write data in the database. The curr_time and increment_counter stored procedures are examples of stored routines that qualify as CONTAINS SQL . ■ NO SQL — The stored routine has no SQL statements in it. 267 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Part II Developing with MySQL The default is CONTAINS SQL . Any changes to the default are done manually by the user; MySQL does not check whether or not the option is correct. For example, the store_offerings stored procedure is created with the default of CONTAINS SQL even though READS SQL DATA is the correct option. Because this is for informational purposes only, there is no harm in having this option be incorrect. However, if you intend to use the information to guide decisions, make sure you set the appropriate option. Full CREATE PROCEDURE syntax The full CREATE PROCEDURE syntax is: CREATE [DEFINER = { user | CURRENT_USER }] PROCEDURE p_name ([parameter[, . ]]) [SQL SECURITY {DEFINER | INVOKER}] [option . ] {statement} option is one or more of: SQL SECURITY {DEFINER | INVOKER} COMMENT ’comment string’ LANGUAGE SQL [NOT] DETERMINISTIC {CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA} parameter is: [IN|OUT|INOUT] name data_type Note that the CREATE ROUTINE privilege is needed in order to create a stored procedure. See Chapter 14 for more information about managing privileges. Creating a basic stored function A stored function outputs only one scalar value, so there is no such thing as an OUT parame- ter in a stored function. Therefore, the requirements for arguments to a stored function are that each input variable is named and the type defined. You must also specify the type of the return value, and most of the time, create a local variable to store the value to be returned. The differ- ences between CREATE PROCEDURE and CREATE FUNCTION are: ■ All arguments to a function are input parameters; arguments to a procedure may be input parameters, output variables, or INOUT variables. ■ A function must use the RETURNS keyword after the input parameters to specify the type of the scalar value to be returned. ■ A function must use the RETURN keyword in its body to specify the value to be returned. 268 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Stored Routines, Triggers, and Events 7 The following defines a basic stored function to get the store_id of a staff member from the staff table given a staff_id : mysql> DELIMITER | mysql> CREATE FUNCTION get_store_id (f_staff_id TINYINT UNSIGNED) RETURNS TINYINT UNSIGNED -> READS SQL DATA -> BEGIN -> DECLARE f_store_id TINYINT UNSIGNED; -> SELECT store_id INTO f_store_id FROM staff WHERE staff_id=f_staff_id; -> RETURN f_store_id; -> END -> | Query OK, 0 rows affected (0.03 sec) mysql> DELIMITER ; Full CREATE FUNCTION syntax The full syntax for CREATE FUNCTION is: CREATE [DEFINER = { user | CURRENT_USER }] FUNCTION f_name ([parameter[, . ]]) RETURNS type [option . ] {statement} option is one or more of: SQL SECURITY {DEFINER | INVOKER} COMMENT ’comment string’ LANGUAGE SQL [NOT] DETERMINISTIC {CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA} parameter is: name data_type Note that both the CREATE ROUTINE and SUPER privileges are needed in order to create a stored function. See Chapter 14 for more information about managing privileges. Invoking a stored function A stored function is invoked just as a standard MySQL function is invoked — by using the function name and passing input parameters: mysql> SELECT get_store_id(1); 269 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Part II Developing with MySQL +-----------------+ | get_store_id(1) | +-----------------+ |1| +-----------------+ 1 row in set (0.20 sec) Note that you need the EXECUTE privilege in order to invoke the function; the creator of the stored function is given this privilege automatically. Changing a stored routine MySQL supports the ALTER PROCEDURE and ALTER FUNCTION statements, by which you can change the SQL usage, SQL SECURITY option, and COMMENT of a stored routine. To change more than one of these in one ALTER command, separate the options by a space: mysql> ALTER PROCEDURE increment_counter COMMENT "increments the INOUT variable by 1" CONTAINS SQL; Query OK, 0 rows affected (0.00 sec) Note that you need the ALTER ROUTINE privilege in order to change the stored routine; the cre- ator of the stored routine is given this privilege automatically. The automatic_sp_privileges system variable can be set to 0 to change the default behavior of a stored routine’s creator getting automatic ALTER ROUTINE privilege. To change any other part of a stored routine (the DEFINER or the code body, for example), you must drop and re-create the stored routine. To see details of a stored procedure, use the SHOW CREATE PROCEDURE command: mysql> SHOW CREATE PROCEDURE increment_counter\G *************************** 1. row *************************** Procedure: increment_counter sql_mode: STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER, NO_ENGINE_SUBSTITUTION Create Procedure: CREATE DEFINER=`root`@`localhost` PROCE- DURE `increment_counter`(INOUT p_count INT UNSIGNED) COMMENT ’increments the INOUT variable by 1’ SET p_count:=p_count+1 character_set_client: latin1 collation_connection: latin1_swedish_ci Database Collation: latin1_swedish_ci 1 row in set (0.03 sec) To see details of a stored function, use the SHOW CREATE FUNCTION command: mysql> SHOW CREATE FUNCTION get_store_id\G 270 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Stored Routines, Triggers, and Events 7 *************************** 1. row *************************** Function: get_store_id sql_mode: STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER, NO_ENGINE_SUBSTITUTION Create Function: CREATE DEFINER=`root`@`localhost` FUNCTION `get_store_id`(f_staff_id TINYINT UNSIGNED) RETURNS tinyint(3) unsigned READS SQL DATA BEGIN DECLARE f_store_id TINYINT UNSIGNED; SELECT store_id INTO f_store_id FROM staff WHERE staff_id=f_staff_id; RETURN f_store_id; END character_set_client: latin1 collation_connection: latin1_swedish_ci Database Collation: latin1_swedish_ci 1 row in set (0.00 sec) There is no shortcut to find all the stored routines associated with a database. To use SQL to find what stored routines are in the system, query the ROUTINES table in the INFORMATION_SCHEMA database: mysql> SELECT ROUTINE_NAME, ROUTINE_TYPE FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_SCHEMA=’sakila’; +----------------------------+--------------+ | ROUTINE_NAME | ROUTINE_TYPE | +----------------------------+--------------+ | film_in_stock | PROCEDURE | | film_not_in_stock | PROCEDURE | | get_customer_balance | FUNCTION | | inventory_held_by_customer | FUNCTION | | inventory_in_stock | FUNCTION | | rewards_report | PROCEDURE | +----------------------------+--------------+ 6 rows in set (0.09 sec) For more about the INFORMATION_SCHEMA database, see Chapter 21. Naming: stored routines Stored routines can be named using reserved words. This is an extremely bad idea to do on purpose. Because it is possible you may accidentally give your stored routine a name that is a reserved word, we will explain how to name a stored routine using a reserved word. To name a stored routine with a reserved word, there must be whitespace between the routine name (reserved word) and the opening parenthesis used for the parameters: mysql> DELIMITER | mysql> CREATE PROCEDURE count(INOUT p_count INT UNSIGNED) 271 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Part II Developing with MySQL -> COMMENT ’this fails because count is a reserved word and no space exists between count and (’ -> BEGIN -> SET p_count:=p_count+1; -> END -> | ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ’count (INOUT p_count INT UNSIGNED) COMMENT ’this will fail because count is a res’ at line 1 mysql> CREATE PROCEDURE count (INOUT p_count INT UNSIGNED) -> COMMENT ’this succeeds because of the space between count and (, but is a bad idea’ -> BEGIN -> SET p_count:=p_count+1; -> END -> | Query OK, 0 rows affected (0.25 sec) mysql> DELIMITER ; The same holds true for using a stored routine named with a reserved word: there must be a space between the routine name and the opening parenthesis used for the parameters: mysql> set @count:=123; Query OK, 0 rows affected (0.00 sec) mysql> CALL count(@count); ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ’count (@count)’ at line 1 mysql> CALL count (@count); Query OK, 0 rows affected (0.11 sec) mysql> select @count; +--------+ | @count | +--------+ | 124 | +--------+ 1 row in set (0.00 sec) mysql> -- dropping the procedure right away for sanity’s sake mysql> DROP PROCEDURE IF EXISTS count; Query OK, 0 rows affected (0.03 sec) Note that the sql_mode named IGNORE_SPACE has no bearing on this rule — IGNORE_SPACE does not apply to stored routines. 272 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Stored Routines, Triggers, and Events 7 If you get an SQL syntax error when attempting to execute a stored routine, check the name of the stored routine — you may have accidentally given your stored routine a name that is a reserved word! Stored procedure result sets A stored procedure can return information by way of OUT and INOUT variables; however, a stored procedure can also return information with SQL statements inside the stored procedure. For example, a SELECT statement inside a stored procedure will execute as it would on a command line, and when invoking the stored procedure you would see that result set. Ziesel created the store_offerings stored procedure because she wanted to get the count of movies offered by a given store_id , whether or not that movie was in stock. To return the count, she took advantage of an OUT variable: DELIMITER | CREATE PROCEDURE store_offerings ( IN p_store_id INT, OUT p_count INT ) SELECT COUNT(*) INTO p_count FROM inventory WHERE store_id = p_store_id; | DELIMITER ; However, Ziesel could have also returned the count by issuing a simple SELECT statement, send- ing the result set back — the same way a result set is sent back when a user directly issues a SELECT statement: mysql> DROP PROCEDURE IF EXISTS store_offerings; Query OK, 0 rows affected (0.02 sec) mysql> DELIMITER | mysql> CREATE PROCEDURE store_offerings ( IN p_store_id INT ) -> SELECT COUNT(*) -> FROM inventory -> WHERE store_id = p_store_id; -> | Query OK, 0 rows affected (0.05 sec) mysql> DELIMITER ; mysql> CALL store_offerings (1); +----------+ | COUNT(*) | +----------+ | 2270 | +----------+ 1 row in set (0.25 sec) Query OK, 0 rows affected (0.25 sec) 273 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Part II Developing with MySQL Ziesel modified the stored procedure, changing the SELECT COUNT(*) INTO query to a SELECT COUNT(*) query, eliminating the need for an OUT variable to store the result in. The result is sent back to the client program that invoked the stored procedure (in this case, the mysql command-line client). Sending Back Result Sets S tored procedures can send information back in two ways: by updating a variable and by running queries that send back result sets. There is no need to choose only one method — a single stored procedure can update variables and run queries that send back results. There may be times when you want to minimize using user-defined variables; in these cases you may prefer to send back a result set. In other cases, perhaps when you do not want the overhead of processing a returned result set, user-defined variables are preferable. The programs that call the stored procedure need to be able to handle all of the returned information, whether or not it is returned via a variable. OUT variables must be specified when the procedure is invoked, otherwise the command will fail. However, there is no error or warning from MySQL if information is returned via a result set and your application does not process that result set, or processes it incorrectly (perhaps by assuming the result set has exactly one row). In the store_offerings example, only one SELECT query is part of the body. However, a stored procedure can issue many queries, including issuing many queries that return result sets to the client. Make sure your application can handle all possible output, including multiple result sets, errors, warnings, and unexpected result sets (empty result sets, or result sets with more rows than expected). Stored routine errors and warnings If you did not want to allow pct_increase to accept negative values for p_incr ,youwould have defined the input parameter as IN p_incr INT UNSIGNED : mysql> DROP PROCEDURE IF EXISTS pct_increase; Query OK, 0 rows affected (0.00 sec) mysql> DELIMITER | mysql> CREATE PROCEDURE pct_increase (INOUT p_int INT, IN p_incr INT UNSIGNED, OUT p_pct_incr DECIMAL (5,2)) -> BEGIN -> DECLARE p_int_new INT; -> SET p_int_new:=p_int+p_incr; -> SET p_pct_incr:=(p_int_new-p_int)/p_int*100; -> SET p_int:=p_int_new; -> END -> | Query OK, 0 rows affected (0.00 sec) 274 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Stored Routines, Triggers, and Events 7 mysql> DELIMITER ; mysql> SET @num:=100; Query OK, 0 rows affected (0.00 sec) mysql> CALL pct_increase (@num, -10, @pct); ERROR 1264 (22003): Out of range value for column ’p_incr’ at row 1 mysqld handles stored routine errors and warnings as if the client ran the commands interac- tively. A user invoking pct_increase with a negative number for the second argument receives the error Out of range value as seen in the preceding code. The error message is accurate, but it is confusing. There is no indication that p_incr refers to the second argument ( -10 ). The error message specifies column ’p_incr’ , which is confusing because there are no columns being referenced, only variables and scalar values. The user will have to examine the stored routine to figure out the problem. There is no debug- ger for stored routines, so logical errors can be difficult to detect and fix. One way to debug a stored procedure is to use a SELECT statement to print variables at certain positions. A SELECT statement before each line mimics stepping through the stored procedure and checking variable values at each step. By the way, data type incompatibilities and overflows in a stored routine are treated the same as on the command line. Warnings or errors are generated, depending on the sql_mode .This holds true for arguments as well as local variables. Conditions and handlers Though the error handling in stored routines is not very advanced, MySQL allows you to spec- ify handlers that can trap conditions. This allows you to handle known exceptions. Using the DECLARE syntax, you can create a handler to specify what to do when a condition is met. You can also create a condition using the DECLARE syntax for use in a handler. You can find a full list of MySQL error codes, SQL states, and messages in the manual at http://dev.mysql.com/doc/refman/6.0/en/error-messages-server.html . Handlers The stored procedure pct_increase defined an OUT variable as a signed decimal with two dec- imal places. What happens if the OUT variable requires more precision? mysql> SHOW CREATE PROCEDURE pct_increase\G *************************** 1. row *************************** Procedure: pct_increase sql_mode: STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER, NO_ENGINE_SUBSTITUTION Create Procedure: CREATE DEFINER=`root`@`localhost` PROCE- DURE `pct_increase` (INOUT p_int INT, IN p_incr INT UNSIGNED, OUT p_pct_incr DECI- MAL (5,2)) 275 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Part II Developing with MySQL BEGIN DECLARE p_int_new INT; SET p_int_new:=p_int+p_incr; SET p_pct_incr:=(p_int_new-p_int)/p_int*100; SET p_int:=p_int_new; END character_set_client: latin1 collation_connection: latin1_swedish_ci Database Collation: latin1_swedish_ci 1 row in set (0.00 sec) mysql> SET @num:=100; Query OK, 0 rows affected (0.00 sec) mysql> CALL pct_increase (@num, 10, @pct); Query OK, 0 rows affected (0.00 sec) mysql> SELECT @num, @pct; +------+-------+ | @num | @pct | +------+-------+ | 110 | 10.00 | +------+-------+ 1 row in set (0.00 sec) mysql> CALL pct_increase (@num, 10, @pct); Query OK, 0 rows affected, 1 warning (0.00 sec) mysql> SHOW WARNINGS; +-------+------+-------------------------------------------------+ | Level | Code | Message | +-------+------+-------------------------------------------------+ | Note | 1265 | Data truncated for column ’p_pct_incr’ at row 1 | +-------+------+-------------------------------------------------+ 1 row in set (0.00 sec) mysql> SELECT @num, @pct; +------+------+ | @num | @pct | +------+------+ | 120 | 9.09 | +------+------+ 1 row in set (0.00 sec) There was data truncated for a variable, and a warning was generated. If the stored procedure had an sql_mode that was set to TRADITIONAL , there would have been an error generated. Note that the warning included at row 1 , so there is no way of knowing which line in the 276 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. [...]... 277 7 Part II Developing with MySQL The following example increments a user variable when the data truncation handler is invoked The scope of the user variable is outside of the stored routine, so the stored procedure will display how many times the warning was issued mysql> DROP PROCEDURE IF EXISTS pct_increase; Query OK, 0 rows affected (0.00 sec) mysql> DELIMITER | mysql> CREATE PROCEDURE pct_increase... events will finish mysql> SHOW GLOBAL VARIABLES LIKE ’event_scheduler’; + -+ -+ | Variable_name | Value | + -+ -+ | event_scheduler | OFF | + -+ -+ 1 row in set (0.00 sec) Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark 289 7 Part II Developing with MySQL mysql> SET GLOBAL event_scheduler=’ON’; Query OK, 0 rows affected (0.00 sec) mysql> SHOW GLOBAL... option file or as an argument directly to mysqld, as in the following: shell> mysqld event_scheduler=DISABLED If the event scheduler is disabled, it cannot be modified from the command-line client If you try to change the value of event_scheduler when it is set to DISABLED, you will see the following error: mysql> SET GLOBAL event_scheduler=’ON’; ERROR 1290 (HY000): The MySQL server is running with the event-scheduler=DISABLED... in MySQL except those involving microseconds See Chapter 5 for more detail on the available interval data types In this example, Ziesel wants to know when the event scheduler is working So she creates a table: mysql> USE test; Database changed mysql> CREATE TABLE event_scheduler_log ( -> event_time DATETIME NOT NULL -> ); Query OK, 0 rows affected (0.39 sec) And then she creates the event itself: mysql> ... this can be changed to a warning by using the IF EXISTS phrase: mysql> DROP EVENT event_scheduler_test; Query OK, 0 rows affected (0.00 sec) mysql> DROP EVENT event_scheduler_test; ERROR 1539 (HY000): Unknown event ’event_scheduler_test’ mysql> DROP EVENT IF EXISTS event_scheduler_test; Query OK, 0 rows affected, 1 warning (0.00 sec) mysql> SHOW WARNINGS; + -+ + -+ | Level |... running periodically: mysql> DROP EVENT event_scheduler_test; Query OK, 0 rows affected (0.00 sec) mysql> TRUNCATE event_scheduler_log; Query OK, 0 rows affected (0.00 sec) mysql> -> -> -> CREATE EVENT event_scheduler_test ON SCHEDULE EVERY 1 SECOND ENDS NOW() + INTERVAL 10 SECOND DO INSERT INTO event_scheduler_log (event_time) VALUES (NOW()); Query OK, 0 rows affected (0.00 sec) mysql> SELECT event_time... Developing with MySQL Event backup and storage Events are stored in the event table of the mysql database Manual manipulation of the event table is not advised Event backup can be done by using mysqldump, and during hot and cold backups For more information on backing up events, see Chapter 13 It is possible, but not recommended, to see a list of events by querying the event table: mysql> SELECT db,... manipulation of the proc table is not advised Stored routine backup can be done by using mysqldump, and during hot and cold backups For more information on backing up stored routines, see Chapter 13 It is possible, but not recommended, to see a list of stored routines by querying the proc table: mysql> SELECT db,name,type FROM mysql. proc; + + + -+ | db | name | type | + + ... Developing with MySQL To retrieve values from the cursor, Eli has to use the FETCH INTO syntax: FETCH cursor_name INTO variable_name [, variable_name ] In this case, Eli’s cursor only selected one field, actor_id, so he only needs one variable He will create a variable cur_actor to be the target for the cursor’s current value of actor_id The full stored procedure definition is: mysql> mysql> -> ->... future by using the optional clause STARTS timestamp_expr: mysql> TRUNCATE event_scheduler_log; Query OK, 0 rows affected (0.00 sec) mysql> -> -> -> CREATE EVENT event_scheduler_test ON SCHEDULE EVERY 1 MINUTE STARTS NOW() + INTERVAL 10 MINUTE DO INSERT INTO event_scheduler_log (event_time) VALUES (NOW()); Query OK, 0 rows affected (0.00 sec) mysql> SELECT * FROM event_scheduler_log; Empty set (0.00 . your MySQL server version for the right syntax to use near ’count (@count)’ at line 1 mysql& gt; CALL count (@count); Query OK, 0 rows affected (0.11 sec) mysql& gt;. a SELECT statement: mysql& gt; DROP PROCEDURE IF EXISTS store_offerings; Query OK, 0 rows affected (0.02 sec) mysql& gt; DELIMITER | mysql& gt; CREATE PROCEDURE

Ngày đăng: 24/12/2013, 17:15

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