Homework content – stored procedures and triggers, indexing experiments
1. Stored procedure and trigger experiment
1. Please implement at least one stored procedure for each of the following operations on the database platform you choose according to your application scenario:
1) Single or multi-table query 2) Data insertion 3) Data deletion 4) Data modification
2. Call the implemented background stored procedure in the front-end program (C/S or B/S mode) through ODBC, OLEDB, JDBC or any other way.
3. In your case scenario, design and implement a trigger triggered by data insertion, data update, and data deletion (either pre-trigger or post-trigger), and test the execution effect of the trigger.
2. Index experiment
1) Combining with homework #3, write a simple data query for a table in your database (the query statement should include a single query condition involving the comparison of non-main attribute equivalence, set the non-main attribute as A, and combine the specific attributes with the business Background) and data insertion statement, the program should be able to record the time-consuming of each data read and write operation in the form of a file on the terminal or server.
2) No index test: Execute the query (the query condition does not include the main code, and there is no index established for attribute A), record the query time under different data scales,
3) Indexed test: Create an index for attribute A, use the same query as in 2), and record the query time under different data scales.
4) Analyze the experimental data, make charts, compare the change of query time with the increase of data volume under the condition of index and no index, and analyze the reasons leading to the experimental results.
-
Stored procedure and trigger experiment
1. Please implement at least one stored procedure for each of the following operations on the database platform you choose according to your application scenario:
1) Single table or multi-table query
Query the data in the client table whose client_id is [init, termient]
CREATE DEFINER=`root`@`localhost` PROCEDURE `select_pro`(in init int, in termint int) BEGIN SELECT * FROM client WHERE client_id>=init AND client_id<=termient; END
- Data insertion
Insert data into the bank table, and check the primary key constraint before inserting. The bank_id of the data to be inserted already exists, return this data in the existing table, and return the message ‘The ID has exsited already’. The bank_id of the data to be inserted does not exist, insert new data, and return ‘Successfully insert’ message.
CREATE DEFINER=`root`@`localhost` PROCEDURE `insert_pro`(IN id INT, IN bank_name VARCHAR(255), IN bank_balance DOUBLE, OUT result VARCHAR(64)) BEGIN IF EXISTS(SELECT * FROM bank WHERE bank_id=id) THEN SET result='The ID has exsited already'; SELECT * FROM bank WHERE bank_id=id; ELSE INSERT INTO bank VALUES(id, bank_name, bank_balance); SET result='Successfully insert'; END IF; END
- Data deletion
Delete the data in the bank table. If the data exists, delete it and return the ‘Successfully delete’ message. If the message does not exist, return ‘No this data’ message.
CREATE DEFINER=`root`@`localhost` PROCEDURE `delete_pro`(IN id INT, OUT result VARCHAR(64)) BEGIN IF EXISTS(SELECT * FROM bank WHERE bank_id=id) THEN DELETE FROM administrator WHERE adm_id=id; SET result='Successfully delete'; ELSE SET result='No this data'; END IF; END
- Data modification
Specify bank_id to modify the corresponding bank_balance data in the bank table. If the data exists, update the data and return the ‘Successfully update’ message. If the data does not exist, return ‘No this data’ message.
CREATE DEFINER=`root`@`localhost` PROCEDURE `update_pro`(IN id INT, IN balance DOUBLE, OUT result VARCHAR(64)) BEGIN IF EXISTS(SELECT * from bank where bank_id=id) THEN UPDATE bank SET bank_balance=balance WHERE bank_id=id; SET result='Successfully update'; ELSE SET result='No this data'; END IF; END
2. Call the implemented background stored procedure in the front-end program (C/S or B/S mode) through ODBC, OLEDB, JDBC or any other way.
Use ODBC to implement the front-end implementation of the `update_pro` stored procedure for the above data modification through the python language.
import web import pyodbc class update_web: ''''' open the update web ''' def GET(self): return render. update() class result_web: ''''' open the result web ''' def GET(self): return render.result(result) class return: ''''' receive message from web and return to homepage ''' def POST(self): raise web.seeother('/') class update(): def POST(self): i = web.input() # Receive information sent by web try: cnxn =pyodbc.connect('DRIVER={' + driver + '};' + f'SERVER={server};DATABASE={database};UID={username};PWD={password}') # connect to database ODBC cursor = cnxn. cursor() global result result = '' params = (i.bank_id, i.bank_balance, result) cursor.execute("{CALL update_pro(?,?,?)}", params) rows = cursor. fetchall() result = rows[0][0].decode() print(result) cnxn. close() raise web.seeother('/result') except: pass if __name__ == "__main__": urls = ( '/', 'update_web', '/update', 'update', '/result', 'result_web', '/returnback', 'returnback' ) # Database ODBC connection information driver = 'MySQL ODBC 8.0 Unicode Driver' # pyodbc.drivers() View available drivers, select the driver that has configured the database before server = 'localhost' database = 'bank' username = 'root' password = '********' render = web.template.render('./template') app = web. application(urls, globals()) app. run()
3. In your case scenario, design and implement a trigger triggered by data insertion, data update, and data deletion (either pre-trigger or post-trigger), and test the execution effect of the trigger.
data insertion trigger
-- Newly inserted employee points are always 0 CREATE DEFINER=`root`@`localhost` TRIGGER insert_adm BEFORE INSERT on administrator FOR EACH ROW IF new. score<>0 THEN SET new. score=0; END IF
-- When a new user deposits for the first time, the balance in the bank table will also increase, that is, the total funds of the bank will increase accordingly CREATE TRIGGER insert_basic AFTER INSERT on basic_service FOR EACH ROW UPDATE bank SET bank_balance=bank_balance + new.balance where bank_id=new.bank_id;
data update trigger
-- When the user deposits and withdraws money, the balance in the bank table also changes accordingly CREATE TRIGGER update_basic AFTER UPDATE on basic_service FOR EACH ROW UPDATE bank SET bank_balance=bank_balance-old.balance + new.balance where bank_id=old.bank_id;
Data Delete Trigger
-- When the user withdraws all deposits, the balance in the bank table also decreases CREATE TRIGGER delete_basic AFTER DELETE on basic_service FOR EACH ROW UPDATE bank SET bank_balance=bank_balance-old.balance where bank_id=old.bank_id;
-
Index experiment
1) Combining with homework #3, write a simple data query for a table in your database (the query statement should include a single query condition involving the comparison of non-main attribute equivalence, set the non-main attribute as A, and combine the specific attributes with the business Background) and data insertion statement, the program should be able to record the time-consuming of each data read and write operation in the form of a file on the terminal or server.
2) No index test: Execute the query (the query condition does not include the main code, and there is no index established for attribute A), record the query time under different data scales,
3) Indexed test: Create an index for attribute A, use the same query as in 2), and record the query time under different data scales.
4) Analyze the experimental data, make charts, compare the change of query time with the increase of data volume under the condition of index and no index, and analyze the reasons leading to the experimental results.
import numpy as np from random import randint import pickle import pymysql import time from tqdm import tqdm, trange def insert_data(job_num_i, data_num_i,f): # Data insertion, set the number of categories and the total number of data in the index column start_time = time.perf_counter() sql = "INSERT INTO administrator VALUES(%s,'L','hycyzufs','2023-5-23',13022896926,990,%s)" sql_list = [] for i in trange(data_num_i, desc=f'inserting-{job_num_i}-{data_num_i}', leave=False): a = randint(1, job_num_i) sql_list. append((i + 1, a)) cursor.executemany(sql, sql_list) conn.commit() insert_time = time.perf_counter() - start_time f.write(f'Insert_time: {insert_time}\\ ') def delete_all(): # delete all data sql = 'DELETE FROM administrator where adm_id>0' cursor. execute(sql) conn.commit() def index_on(): # open index sql = 'CREATE INDEX index_job ON administrator (job_id)' cursor. execute(sql) conn.commit() def index_out(): # close index sql = 'DROP INDEX index_job ON administrator' cursor. execute(sql) conn.commit() def test(test_num_i, data_num_i, sql, f): # Test search time, set the number of tests, and calculate the average search time all_time = [] for _ in trange(test_num_i, desc=f'testing-{test_num_i}', leave=False): start_time = time.perf_counter() cursor. execute(sql) results = cursor. fetchall() pickle.dump(list(results), open('outcome', 'wb')) end_time = time.perf_counter() use_time = end_time - start_time all_time.append(use_time) avg_time = np. mean(all_time) f.write(f'{str(data_num_i)}: {str(avg_time)}\\ ') if __name__ == '__main__': job_num = [3, 5, 10] # list of index column categories data_num = [100, 1000, 10000, 100000, 1000000] # generate a list of data numbers test_num = 10 # list of test times, average after several tests conn = pymysql.connect(user='root', password='********', database='bank') cursor = conn.cursor(pymysql.cursors.DictCursor) f = open('results.txt', 'w + ') sql = 'select * from administrator where job_id=1' job_num_i = job_num[0] data_num_i = data_num[0] for job_num_i in tqdm(job_num, desc=f'job_num-{job_num_i}'): f.write(f'-------job_num{job_num_i}---------\\ ') for data_num_i in tqdm(data_num, desc=f'data_num-{data_num_i}'): delete_all() insert_data(job_num_i, data_num_i, f) test(test_num, data_num_i, sql, f) try: index_on() time. sleep(3) except: pass test(test_num, data_num_i, sql, f) try: index_out() time. sleep(3) except: pass f.write('\\ ') delete_all() f. close() cursor. close() conn. close()
Test Results:
data_num job_num |
100 |
1,000 |
10,000 |
100,000 |
1,000,000 |
no index 3 |
0.002488 |
0.008003 |
0.065155 |
0.792094 |
8.438734 |
have index 3 |
0.001907 |
0.007637 |
0.058433 |
0.077227 |
0.094179 |
no index 5 |
0.153701 |
0.029841 |
0.049829 |
0.934420 |
5.202662 |
have index 5 |
0.001961 |
0.004566 |
0.027477 |
0.0697084 |
0.563507 |
no index 10 |
0.329588 |
0.031040 |
0.039202 |
0.291128 |
2.984093 |
have index 10 |
0.001789 |
0.005060 |
0.003347 |
0.068878 |
0.086979 |
From the perspective of data volume, when there is less data, the query time with or without index is very fast, and with index is slightly faster than without index, but the gap between the two is not large. As the amount of data increases, the query time with the index will gradually show its advantages. In this experiment, the biggest difference can be achieved that the time spent with the index is 1/180 of the time spent without the index.
From the perspective of the number of categories in the index column, under different categories in this experiment, it is faster to have an index than to have no index. However, as the number of categories increases, the query time with indexes gradually increases, and the advantages decrease.
For the complete code, see: (1 message) Database: Stored Procedures, Triggers, Indexing Experimental Code Resources – CSDN Library