Все статьи свода знаний,GitHubОн был записан, добро пожаловать в Star! Еще раз спасибо, я желаю вам войти на завод как можно скорее!
Адрес гитхаба: GitHub.com/zip и треки/…
Хранимая процедура MySQL
Во-первых, хранимая процедура
1.1 Что такое хранимая процедура
Хранимая процедура — это набор операторов SQL в большой системе баз данных для выполнения определенной функции. Она хранится в базе данных и действует постоянно после одной компиляции. Пользователь указывает имя хранимой процедуры и дает параметры (если хранимая процедура с параметрами) для его выполнения. Хранимые процедуры являются важным объектом в базе данных. В случае особенно большого объема данных использование хранимых процедур может повысить эффективность в два раза.
1.2 Программа хранимых процедур базы данных
Когда мы понимаем, что такое хранимая процедура, нам нужно понимать три типа программ типа хранилища базы данных, которые существуют в базе данных, а именно:
- Хранимая процедура:Хранимая процедура является наиболее распространенным типом хранимой процедуры, хранимая процедура представляет собой программный модуль, который может принимать входные и выходные параметры и может выполняться по запросу.
- Сохраненная функция:Хранимая функция похожа на хранимую процедуру, но ее выполнение возвращает значение. Что наиболее важно, хранимые функции можно использовать как стандартные операторы SQL, что позволяет программистам эффективно расширять возможности языка SQL.
- курок:Триггеры — это хранимые процедуры, используемые для реагирования на события, которые активируют или инициируют поведение базы данных. Как правило, триггеры используются для вызова в ответ на языки манипулирования базой данных, а триггеры могут использоваться для проверки данных и автоматического обратного форматирования.
Примечание. Другие базы данных предоставляют дополнительные процедуры хранения данных, включая пакеты и классы. В настоящее время MySQL не предоставляет эту структуру.
1.3 Зачем использовать хранимые процедуры
Хотя мы не используем много сохраненных программ в текущей разработке, это не обязательно отрицается. На самом деле хранимые процедуры дадут нам много преимуществ в использовании и управлении базами данных:
- Безопаснее использовать хранимые процедуры.
- Хранимые процедуры предоставляют механизм абстракции для доступа к данным, который может значительно повысить удобство сопровождения вашего кода по мере развития базовых структур данных.
- Хранимые процедуры могут уменьшить перегрузку сети, поскольку данные относятся к внутренним данным сервера базы данных, что намного быстрее, чем передача данных через Интернет.
- Хранимые процедуры могут реализовывать подпрограммы совместного доступа для множества периферийных приложений, использующих различные архитектуры, вне зависимости от того, являются ли эти архитектуры внешними или внутренними по отношению к серверу базы данных.
- Логика, ориентированная на данные, может быть размещена независимо в хранимых процедурах, что может предоставить программистам более высокий и уникальный опыт программирования баз данных.
- В некоторых случаях использование хранимых процедур может улучшить переносимость приложений. (В других случаях переносимость будет плохой!)
Здесь я кратко объясню вышеупомянутые преимущества использования хранимых процедур:
Нам нужно знать, что в языке Java нам нужно ввести JDBC, чтобы использовать базу данных и код Java для объединения постоянного хранилища. Думая о JDBC, можем ли мы все еще думать о проблемах SQL-инъекций? Хотя использование PreparedStatement для решения проблемы SQL-инъекции действительно абсолютно безопасно? Нет, это не совсем безопасно.
В это время проанализируйте процесс операции соединения между базой данных и кодом Java. В структуре BS браузер обычно обращается к серверу, а затем сервер отправляет оператор SQL в базу данных, компилирует и запускает оператор SQL в базе данных и, наконец, обрабатывает результат через сервер и возвращает его в браузер. Во время этой операции браузер будет вызывать соответствующий оператор SQL для компиляции и выполнения каждый раз, когда он отправляет запрос на операцию с базой данных на сервер, что является пустой тратой производительности.падение производительностиЗатем объясните работу базы данныхнизкая эффективность.
Другая возможность заключается в том, что оператор SQL, который отправляется и передается в этом процессе, является оператором SQL, который работает с реальной таблицей базы данных.Если он будет перехвачен во время процесса передачи и передачи, некоторые преступники сделают вывод на основе перехваченного оператора SQL. структуру библиотечной таблицы в нашей базе данных, которая является большойРиски безопасности.
Что касается улучшения ремонтопригодности, здесь моделируется сценарий. Обычно базой данных управляет администратор базы данных в компании.Если администратор базы данных, который управлял базой данных в течение многих лет, уходит в отставку, база данных будет управляться следующим администратором базы данных. Здесь возникает проблема: такое количество данных и операторов SQL в базе данных явно не очень удобно для следующего менеджера. Даже DBA, управляющий много лет, что-то забудет, если долго не будет проверять базу. Поэтому нам необходимо ввести хранимые процедуры для унифицированного написания и компиляции операторов SQL,облегчает техническое обслуживание. (Вообще, я думаю, что этот пример не является ярким и разумным, но чтобы все поняли, пожалуйста, поймите!)
Я говорил об эволюции преимуществ многих хранимых программ.Один или несколько фрагментов скомпилированных операторов SQL необходимо поместить в хранимую программу на стороне базы данных, чтобы решить вышеуказанные проблемы и облегчить прямые вызовы разработчиками.
Во-вторых, использование хранимых процедур.
2.1 Идея развития хранимой процедуры
Хранимая процедура является важным объектом базы данных. Она может инкапсулировать набор операторов SQL, который можно использовать для выполнения более сложной бизнес-логики, а также может вводить параметры (параметры) и выходные параметры (возвращаемые параметры). Это очень похоже к способу упаковки в Java сходство.
Более того, он будет предварительно скомпилирован и сохранен при создании, и последующие вызовы разработчиками не нужно будет компилировать заново.
2.2 Преимущества и недостатки хранимых процедур
Преимущества и недостатки использования хранимых процедур фактически упоминаются в преимуществах 1.3. Здесь я кратко перечисляю преимущества и недостатки хранимых процедур.
- преимущество:
- В производственной среде бизнес-логика или ошибки могут быть изменены путем прямого изменения хранимой процедуры без перезапуска сервера.
- Скорость выполнения высокая.После того как хранимая процедура скомпилирована, она будет намного быстрее, чем компиляция и выполнение один за другим.
- Уменьшите сетевой трафик.
- Его удобно использовать и поддерживать разработчикам или администраторам баз данных.
- Улучшенная переносимость с тем же синтаксисом базы данных.
- недостаток:
- Процедурное программирование, стоимость обслуживания сложных бизнес-процессов высока.
- Неудобно отлаживать.
- Поскольку синтаксис разных баз данных несовместим, переносимость между разными базами данных плохая.
2.3 Официальная документация по хранимым процедурам MySQL
Друзья, хорошо владеющие английским или способные, могут обратиться к официальной документации. Если вы не ссылаетесь на официальную документацию, это не имеет значения.Я также подробно опишу различные точки знаний о хранимых процедурах MySQL ниже.
https://dev.mysql.com/doc/refman/5.6/en/preface.html
2.3 Синтаксис использования хранимых процедур
create PROCEDURE 过程名( in|out|inout 参数名 数据类型 , ...)
begin
sql语句;
end;
call 过程名(参数值);
in
ключевое слово, определяющее входящий параметр.out
ключевое слово, определяющее параметр.inout
Является ли для определения параметра, который можно ввести или выйти. Если в скобках ничего не определено, это означает, что хранимая процедура является функцией без параметров. Далее будет подробное тематическое исследование.Уведомление:Терминатор по умолчанию для операторов SQL:
;
, поэтому при использовании вышеуказанной хранимой процедуры будет сообщено о синтаксической ошибке 1064. мы можем использоватьDELIMITER
Временное объявление ключевого слова изменяет терминатор оператора SQL на//
,следующее:
-- 临时定义结束符为"//"
DELIMITER //
create PROCEDURE 过程名( in|out 参数名 数据类型 , ...)
begin
sql语句;
end//
-- 将结束符重新定义回结束符为";"
DELIMITER ;
Например:Используйте хранимую процедуру для запроса зарплаты сотрудника (без параметров)
Уведомление:Если в особых необходимых обстоятельствах, мы также можем передатьdelimiter
ключевые слова будут;
Терминатор объявлен обратно в использование, в следующем случае я не объявлял терминатор обратно в исходный;
Пожалуйста, обратите внимание на это ~
Почему я предоставляю дроп здесь?
Это связано с тем, что если нам нужно изменить содержимое хранимой процедуры при ее использовании, нам нужно сначала удалить существующую хранимую процедуру, а затем создать ее снова.
# 声明结束符为//
delimiter //
# 创建存储过程(函数)
create procedure se()
begin
select salary from employee;
end //
# 调用函数
call se() //
# 删除已存在存储过程——se()函数
drop procedure if exists se //
Три, переменные хранимой процедуры и назначения
3.1 Локальные переменные
Объявить синтаксис локальной переменной:
declare var_name type [default var_value];
Синтаксис назначения:
Уведомление:Определение локальных переменных, действительных в начальных/конечных блоках.
Используйте set для присвоения значений параметрам
# set赋值
# 声明结束符为//
delimiter //
# 创建存储过程
create procedure val_set()
begin
# 声明一个默认值为unknown的val_name局部变量
declare val_name varchar(32) default 'unknown';
# 为局部变量赋值
set val_name = 'Centi';
# 查询局部变量
select val_name;
end //
# 调用函数
call val_set() //
Используйте into для получения параметров
delimiter //
create procedure val_into()
begin
# 定义两个变量存放name和age
declare val_name varchar(32) default 'unknown';
declare val_age int;
# 查询表中id为1的name和age并放在定义的两个变量中
select name,age into val_name,val_age from employee where id = 1;
# 查询两个变量
select val_name,val_age;
end //
call val_into() //
3.2 Пользовательские переменные
Пользовательская переменная, действующая для текущего сеанса (соединения). Подобно переменным-членам в Java.
- грамматика:
@val_name
- Уведомление:Пользовательскую переменную не нужно объявлять заранее, она объявляется при использовании.
delimiter //
create procedure val_user()
begin
# 为用户变量赋值
set @val_name = 'Lacy';
end //
# 调用函数
call val_user() //
# 查询该用户变量
select @val_name //
3.3 Переменные сеанса
Переменные сеанса предоставляются системой и действительны только в текущем сеансе (соединении).
грамматика:
@@session.val_name
# 查看所有会话变量
show session variables;
# 查看指定的会话变量
select @@session.val_name;
# 修改指定的会话变量
set @@session.val_name = 0;
Здесь я получаю все переменные сеанса, там около 500 записей переменных сеанса. После того, как мы подробно изучим MySQL, мы поймем роль каждого значения переменной сеанса и сможем изменить значение переменной сеанса в соответствии с требованиями и сценариями.
delimiter //
create procedure val_session()
begin
# 查看会话变量
show session variables;
end //
call val_session() //
3.4 Глобальные переменные
Глобальные переменные предоставляются системой и действительны на всем сервере MySQL.
грамматика:
@@global.val_name
# 查看全局变量中变量名有char的记录
show global variables like '%char%' //
# 查看全局变量character_set_client的值
select @@global.character_set_client //
3.5 Входные параметры и выходные параметры
Синтаксис входных и выходных параметров упоминался в начале статьи, но демонстрации нет, здесь я продемонстрирую использование входных и выходных параметров.
грамматика:
in|out|inout 参数名 数据类型 , ...
in
определить параметры;out
определить входные параметры;inout
Определите исходящие и входящие параметры.
из женьшеня
При использовании параметра in нам нужно передать параметры, где параметры можно изменить. Проще говоря, in отвечает только за передачу параметров в хранимые процедуры, аналогично формальным параметрам в Java.
delimiter //
create procedure val_in(in val_name varchar(32))
begin
# 使用用户变量出参(为用户变量赋参数值)
set @val_name1 = val_name;
end //
# 调用函数
call val_in('DK') //
# 查询该用户变量
select @val_name1 //
входной параметр выход
При использовании out вам необходимо передать параметр. Этот параметр эквивалентен возвращаемому значению, и содержимое этого параметра можно получить путем вызова и приема. Проще говоря, out отвечает только за возвращаемое значение.
delimiter //
# 创建一个入参和出参的存储过程
create procedure val_out(in val_id int,out val_name varchar(32))
begin
# 传入参数val_id查询员工返回name值(查询出的name值用出参接收并返回)
select name into val_name from employee where id = val_id;
end //
# 调用函数传入参数并声明传入一个用户变量
call val_out(1, @n) //
# 查询用户变量
select @n //
входной параметр
Ключевое слово inout объединяет вход и выход в одно ключевое слово. Параметры, изменяемые ключевыми словами, могут быть как выходными, так и входными параметрами.
delimiter //
create procedure val_inout(in val_name varchar(32), inout val_age int)
begin
# 声明一个a变量
declare a int;
# 将传入的参数赋值给a变量
set a = val_age;
# 通过name查询age并返回val_age
select age into val_age from employee where name = val_name;
# 将传入的a与-和查询age结果字符串做拼接并查询出来(concat——拼接字符串)
select concat(a, '-', val_age);
end //
# 声明一个用户变量并赋予参数为40
set @ages = '40' //
# 调用函数并传入参数值
call val_inout('Ziph', @ages) //
# 执行结果
# 40-18
В-четвертых, управление процессом в хранимой процедуре
4.1 если условное суждение (рекомендуется)
Расширение:
timestampdiff(unit, exp1, exp2)
Разность получается для exp2 - exp1, а единицей является единица. (обычно используется для дат)Расширенный пример:
select timestampdiff(year,’2020-6-6‘,now()) from emp e where id = 1;
Пример расширения пояснения:Запросите возраст сотрудника, чей идентификатор равен 1 в таблице сотрудников, а exp2 может быть датой рождения сотрудника, которая рассчитывается в годах.
грамматика:
IF 条件判断 THEN 结果
[ELSEIF 条件判断 THEN 结果] ...
[ELSE 结果]
END IF
Пример:Введите параметр id для запроса стандарта заработной платы (s=15000 - это стандартный стандарт высокой заработной платы)
delimiter //
create procedure s_sql(in val_id int)
begin
# 声明一个局部变量result存放工资标准结果
declare result varchar(32);
# 声明一个局部变量存放查询得到的工资
declare s double;
# 根据入参id查询工资
select salary into s from employee where id = val_id;
# if判断的使用
if s <= 6000 then
set result = '低工资标准';
elseif s <= 10000 then
set result = '中工资标准';
elseif s <= 15000 then
set result = '中上工资标准';
else
set result = '高工资标准';
end if;
# 查询工资标准结果
select result;
end //
# 调用函数,传入参数
call s_sql(1);
4.2 состояние дела
Что касается оператора case, его можно использовать не только в хранимых процедурах, но и в базовых операторах запросов MySQL. Это эквивалентно оператору switch в Java.
грамматика:
# 语法一
CASE case_value
WHEN when_value THEN 结果
[WHEN when_value THEN 结果] ...
[ELSE 结果]
END CASE
# 语法二(推荐语法)
CASE
WHEN 条件判断 THEN 结果
[WHEN 条件判断 THEN 结果] ...
[ELSE 结果]
END CASE
Пример:
# 语法一
delimiter //
create procedure s_case(in val_id int)
begin
# 声明一个局部变量result存放工资标准结果
declare result varchar(32);
# 声明一个局部变量存放查询得到的工资
declare s double;
# 根据入参id查询工资
select salary into s from employee where id = val_id;
case s
when 6000 then set result = '低工资标准';
when 10000 then set result = '中工资标准';
when 15000 then set result = '中上工资标准';
else set result = '高工资标准';
end case;
select result;
end //
call s_case(1);
# 语法二(推荐)
delimiter //
create procedure s_case(in val_id int)
begin
# 声明一个局部变量result存放工资标准结果
declare result varchar(32);
# 声明一个局部变量存放查询得到的工资
declare s double;
# 根据入参id查询工资
select salary into s from employee where id = val_id;
case
when s <= 6000 then set result = '低工资标准';
when s <= 10000 then set result = '中工资标准';
when s <= 15000 then set result = '中上工资标准';
else set result = '高工资标准';
end case;
select result;
end //
call s_case(1);
4.3 петля петля
Цикл бесконечный, нам нужно выйти из цикла вручную, мы можем использовать
leave
чтобы выйти из циклаОтпуск можно рассматривать как перерыв в Java, ему соответствуют
iterate
(Продолжить цикл) также можно рассматривать как продолжение Java.
грамматика:
[别名:] LOOP
循环语句
END LOOP [别名]
Примечание. Псевдонимы и псевдонимы управляют одной и той же меткой.
Пример 1:Напечатайте 1~10 в цикле (выход из цикла контролируется отпуском)
Примечание. Цикл цикла является бесконечным циклом. Мы проверили число 1–10, равное i. В бесконечном цикле он настроен на остановку цикла, когда он больше или равен 10, то есть содержимое в цикл выполняется 10 раз, и результат запрашивается 10 раз, было сгенерировано 10 результатов (1~10).
delimiter //
create procedure s_loop()
begin
# 声明计数器
declare i int default 1;
# 开始循环
num:
loop
# 查询计数器记录的值
select i;
# 判断大于等于停止计数
if i >= 10 then
leave num;
end if;
# 计数器自增1
set i = i + 1;
# 结束循环
end loop num;
end //
call s_loop();
распечатать результат:
Пример 2:Цикл печати 1 ~ 10 (итерация и выход из цикла управления)
Примечание. Здесь мы используем результат счетчика конкатенации строк, и условие должно быть i
delimiter //
create procedure s_loop1()
begin
# 声明变量i计数器
declare i int default 1;
# 声明字符串容器
declare str varchar(256) default '1';
# 开始循环
num:
loop
# 计数器自增1
set i = i + 1;
# 字符串容器拼接计数器结果
set str = concat(str, '-', i);
# 计数器i如果小于10就继续执行
if i < 10 then
iterate num;
end if;
# 计数器i如果大于10就停止循环
leave num;
# 停止循环
end loop num;
# 查询字符串容器的拼接结果
select str;
end //
call s_loop1();
4.4 повторный цикл
Цикл повторения аналогичен циклу do while в Java, который не завершит цикл, пока условие не будет выполнено.
грамматика:
[别名:] REPEAT
循环语句
UNTIL 条件
END REPEAT [别名]
Пример:цикл печати 1 ~ 10
delimiter //
create procedure s_repeat()
begin
declare i int default 1;
declare str varchar(256) default '1';
# 开始repeat循环
num:
repeat
set i = i + 1;
set str = concat(str, '-', i);
# until 结束条件
# end repeat 结束num 结束repeat循环
until i >= 10 end repeat num;
# 查询字符串拼接结果
select str;
end //
call s_repeat();
4.5 пока цикл
Цикл while очень похож на цикл while в Java.
грамматика:
[别名] WHILE 条件 DO
循环语句
END WHILE [别名]
Пример:цикл печати 1 ~ 10
delimiter //
create procedure s_while()
begin
declare i int default 1;
declare str varchar(256) default '1';
# 开始while循环
num:
# 指定while循环结束条件
while i < 10 do
set i = i + 1;
set str = concat(str, '+', i);
# while循环结束
end while num;
# 查询while循环拼接字符串
select str;
end //
call s_while();
4.6 Операторы управления потоком (продолжение, конец)
Что касается продолжения и завершения управления потоком, мы использовали его раньше. Вот еще один список.
оставить: аналогично перерыву в Java;
leave 标签;
iterate: похоже на continue; в Java
iterate 标签;
5. Курсор и обработчик
5.1 Курсоры
Курсор может получать результирующий набор и обрабатывать данные построчно. Построчная работа курсора приводит к тому, что курсор используется редко!
грамматика:
DECLARE 游标名 CURSOR FOR 查询语句
-- 打开语法
OPEN 游标名
-- 取值语法
FETCH 游标名 INTO var_name [, var_name] ...
-- 关闭语法
CLOSE 游标名
Зная синтаксис курсоров, давайте начнем использовать курсоры. следующее:
Пример:Используйте курсор для запроса идентификатора, имени и зарплаты.
delimiter //
create procedure f()
begin
declare val_id int;
declare val_name varchar(32);
declare val_salary double;
# 声明游标
declare emp_flag cursor for
select id, name, salary from employee;
# 打开
open emp_flag;
# 取值
fetch emp_flag into val_id, val_name, val_salary;
# 关闭
close emp_flag;
select val_id, val_name, val_salary;
end //
call f();
Результаты:
Из-за построчной операции курсора мы можем использовать курсор только для запроса строки записей. Как улучшить код для запроса всех записей? Умные друзья придумали использовать петли. Да, давайте попробуем использовать цикл.
delimiter //
create procedure f()
begin
declare val_id int;
declare val_name varchar(32);
declare val_salary double;
# 声明游标
declare emp_flag cursor for
select id, name, salary from employee;
# 打开
open emp_flag;
# 使用循环取值
c:loop
# 取值
fetch emp_flag into val_id, val_name, val_salary;
end loop;
# 关闭
close emp_flag;
select val_id, val_name, val_salary;
end //
call f();
После того, как мы использовали цикл, мы обнаружили, что есть проблема, потому что цикл является бесконечным циклом, мы не добавляем условия для завершения цикла, курсор всегда будет запрашивать записи, а когда записи не найдены, исключение будет брошен1329:未获取到选择处理的行数
.
Что, если бы мы нашли способ указать условия для завершения цикла?
В это время вы можете объявить тег логического типа. Если true, запросите набор результатов, если false, завершите цикл.
delimiter //
create procedure f()
begin
declare val_id int;
declare val_name varchar(32);
declare val_salary double;
# 声明flag标记
declare flag boolean default true;
# 声明游标
declare emp_flag cursor for
select id, name, salary from employee;
# 打开
open emp_flag;
# 使用循环取值
c:loop
fetch emp_flag into val_id, val_name, val_salary;
# 如果标记为true则查询结果集
if flag then
select val_id, val_name, val_salary;
# 如果标记为false则证明结果集查询完毕,停止死循环
else
leave c;
end if;
end loop;
# 关闭
close emp_flag;
select val_id, val_name, val_salary;
end //
call f();
Вы обнаружите, что приведенный выше код не закончен, он оставляет очень серьезную проблему. Цикл можно завершить, когда flag = false. Но когда флаг будет ложным?
Итак, MySQL предоставляет намhandler
ручка. Это может помочь нам решить это сомнение.
синтаксис дескриптора обработчика:
declare continue handler for 异常 set flag = false;
Дескриптор обработчика можно использовать для перехвата исключений, то есть в этом сценарии, когда перехваченный1329:未获取到选择处理的行数
, измените значение флага flag на false. Это использует дескриптор обработчика для решения проблемы завершения цикла. Давайте попробуем!
Пример редукса:Решены многострочные запросы и проблемы с завершением цикла.
delimiter //
create procedure f()
begin
declare val_id int;
declare val_name varchar(32);
declare val_salary double;
# 声明flag标记
declare flag boolean default true;
# 声明游标
declare emp_flag cursor for
select id, name, salary from employee;
# 使用handler句柄来解决结束循环问题
declare continue handler for 1329 set flag = false;
# 打开
open emp_flag;
# 使用循环取值
c:loop
fetch emp_flag into val_id, val_name, val_salary;
# 如果标记为true则查询结果集
if flag then
select val_id, val_name, val_salary;
# 如果标记为false则证明结果集查询完毕,停止死循环
else
leave c;
end if;
end loop;
# 关闭
close emp_flag;
select val_id, val_name, val_salary;
end //
call f();
Результаты:
В результатах выполнения видно, что результаты запроса распределяются в виде нескольких запросов и отображаются в каждом окне результатов запроса.
Уведомление:В грамматике объявление переменной, объявление курсора и объявление обработчика должны быть написаны по порядку, иначе при создании хранимой процедуры возникает ошибка.
5.2 рукоятка обработчика
грамматика:
DECLARE handler操作 HANDLER
FOR 情况列表...(比如:异常错误情况)
操作语句
Примечание. Исключения могут записывать коды ошибок исключений, псевдонимы исключений или коды SQLSTATE.
работа обработчика:
- ПРОДОЛЖАТЬ:Продолжать
- ВЫХОД:покидать
- ОТМЕНИТЬ:отозвать
Список исключений:
- mysql_error_code
- SQLSTATE [VALUE] sqlstate_value
- condition_name
- SQLWARNING
- NOT FOUND
- SQLEXCEPTION
Уведомление:Различные коды исключений, коды ошибок, псевдонимы и коды SQLSTATEM в MySQL см. в официальной документации:
Пример написания:
DECLARE exit HANDLER FOR SQLSTATE '3D000' set flag = false;
DECLARE continue HANDLER FOR 1050 set flag = false;
DECLARE continue HANDLER FOR not found set flag = false;
Шесть, цикл для создания таблицы
необходимость:Создайте таблицу, соответствующую каждому дню следующего месяца, и формат созданной таблицы:
comp_2020_06_01、comp_2020_06_02、...
описывать:Нам нужно использовать определенную таблицу для записи большого количества данных, таких как запись поведения поиска и покупки определенного пользователя (обратите внимание, что предполагается, что база данных хранится здесь). Нам нужно разделить таблицы. Наше требование состоит в том, что нам нужна одна таблица в день для хранения статистических данных за день, и нам нужно производить эти таблицы заранее - создавать таблицу на каждый день следующего месяца в конце каждого месяца!
Предварительно скомпилировано: PREPARE 数据库对象名 FROM 参数名
воплощать в жизнь: EXECUTE 数据库对象名 [USING @var_name [, @var_name] ...]
Создайте или удалите таблицы из объектов базы данных: {DEALLOCATE | DROP} PREPARE 数据库对象名
Заявление об обработке времени:
-- EXTRACT(unit FROM date) 截取时间的指定位置值
-- DATE_ADD(date,INTERVAL expr unit) 日期运算
-- LAST_DAY(date) 获取日期的最后一天
-- YEAR(date) 返回日期中的年
-- MONTH(date) 返回日期的月
-- DAYOFMONTH(date) 返回日
Код:
-- 思路:循环构建表名 comp_2020_06_01 到 comp_2020_06_30;并执行create语句。
delimiter //
create procedure sp_create_table()
begin
# 声明需要拼接表名的下一个月的年、月、日
declare next_year int;
declare next_month int;
declare next_month_day int;
# 声明下一个月的月和日的字符串
declare next_month_str char(2);
declare next_month_day_str char(2);
# 声明需要处理每天的表名
declare table_name_str char(10);
# 声明需要拼接的1
declare t_index int default 1;
# declare create_table_sql varchar(200);
# 获取下个月的年份
set next_year = year(date_add(now(),INTERVAL 1 month));
# 获取下个月是几月
set next_month = month(date_add(now(),INTERVAL 1 month));
# 下个月最后一天是几号
set next_month_day = dayofmonth(LAST_DAY(date_add(now(),INTERVAL 1 month)));
# 如果下一个月月份小于10,就在月份的前面拼接一个0
if next_month < 10
then set next_month_str = concat('0',next_month);
else
# 如果月份大于10,不做任何操作
set next_month_str = concat('',next_month);
end if;
# 循环操作(下个月的日大于等于1循环开始循环)
while t_index <= next_month_day do
# 如果t_index小于10就在前面拼接0
if (t_index < 10)
then set next_month_day_str = concat('0',t_index);
else
# 如果t_index大于10不做任何操作
set next_month_day_str = concat('',t_index);
end if;
# 拼接标命字符串
set table_name_str = concat(next_year,'_',next_month_str,'_',next_month_day_str);
# 拼接create sql语句
set @create_table_sql = concat(
'create table comp_',
table_name_str,
'(`grade` INT(11) NULL,`losal` INT(11) NULL,`hisal` INT(11) NULL) COLLATE=\'utf8_general_ci\' ENGINE=InnoDB');
# 预编译
# 注意:FROM后面不能使用局部变量!
prepare create_table_stmt FROM @create_table_sql;
# 执行
execute create_table_stmt;
# 创建表
DEALLOCATE prepare create_table_stmt;
# t_index自增1
set t_index = t_index + 1;
end while;
end//
# 调用函数
call sp_create_table()
7. Другое
7.1 characteristic
В хранимых процедурах MySQL, если нет явного определения характеристики, будет неявно определен набор значений по умолчанию для характеристик для создания хранимой процедуры.
LANGUAGE SQL
- Язык хранимой процедуры, по умолчанию — sql, что указывает на то, что хранимая процедура написана на языке sql, в настоящее время поддерживается только sql, а в будущем могут поддерживаться и другие языки.
NOT DETERMINISTIC
- Является ли детерминированный ввод детерминированным выводом, по умолчанию НЕ ДЕТЕРМИНИСТИЧЕСКИЙ, только для того же ввода, вывод тот же, текущее значение не использовалось
CONTAINS SQL
- Предоставляет внутреннюю информацию о данных, используемых подпрограммой.Эти значения характеристик в настоящее время предоставляются серверу и не ограничивают фактическое использование данных процессом на основе этих значений характеристик. Доступны следующие варианты:
- CONTAINS SQL указывает, что подпрограмма не содержит инструкций для чтения или записи данных.
- NO SQL означает, что подпрограмма не содержит sql
- READS SQL DATA указывает, что подпрограмма содержит инструкции для чтения данных, но не для записи данных.
- MODIFIES SQL DATA указывает, что подпрограмма содержит операторы, которые записывают данные.
SQL SECURITY DEFINER
- Хранимые процедуры MySQL указываются путем указания предложения SQL SECURITY, чтобы указать фактического пользователя, выполняющего хранимую процедуру. Таким образом, вторичное значение используется для указания того, выполняется ли хранимая процедура с разрешения создателя или с разрешения исполнителя.Значение по умолчанию — DEFINER.
- Идентификатор создателя DEFINER вызывается для текущего пользователя: если разрешение на выполнение хранимой процедуры и у создателя есть разрешение на доступ к таблице, текущий пользователь может успешно выполнить вызов процедуры.
- Выполняется удостоверение вызывающего INVOKER Для текущего пользователя: если разрешение на выполнение хранимой процедуры состоит в доступе к таблице с текущим удостоверением, если текущее удостоверение не имеет разрешения на доступ к таблице, даже если оно имеет разрешение на выполнение процедуры, она по-прежнему не может быть успешно выполнена вызов процедуры.
COMMENT ''
- Комментарий к хранимой процедуре записывается в COMMENT, где это может быть только одна строка текста, многострочный текст будет удален на возврат каретки, перевод строки и т. д.
7.2 Обработка бесконечного цикла
Если есть бесконечный цикл, вы можете просмотреть и убить (завершить) с помощью следующей команды
show processlist;
kill id;
7.3 Запись case в операторе select
select
case
when 条件判断 then 结果
when 条件判断 then 结果
else 结果
end 别名,
*
from 表名;
7.4 Копирование таблиц и данных
CREATE TABLE dept SELECT * FROM procedure_demo.dept;
CREATE TABLE emp SELECT * FROM procedure_demo.emp;
CREATE TABLE salgrade SELECT * FROM procedure_demo.salgrade;
7.5 Временные таблицы
create temporary table 表名(
  字段名 类型 [约束],
  name varchar(20)
)Engine=InnoDB default charset utf8;
-- 需求:按照部门名称查询员工,通过select查看员工的编号、姓名、薪资。(注意,此处仅仅演示游标用法)
delimiter ?
create procedure sp_create_table02(in dept_name varchar(32))
begin
declare emp_no int;
declare emp_name varchar(32);
declare emp_sal decimal(7,2);
declare exit_flag int default 0;
declare emp_cursor cursor for
select e.empno,e.ename,e.sal
from emp e inner join dept d on e.deptno = d.deptno where d.dname = dept_name;
declare continue handler for not found set exit_flag = 1;
-- 创建临时表收集数据
CREATE temporary TABLE `temp_table_emp` (
`empno` INT(11) NOT NULL COMMENT '员工编号',
`ename` VARCHAR(32) NULL COMMENT '员工姓名' COLLATE 'utf8_general_ci',
`sal` DECIMAL(7,2) NOT NULL DEFAULT '0.00' COMMENT '薪资',
PRIMARY KEY (`empno`) USING BTREE
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB;
open emp_cursor;
c_loop:loop
fetch emp_cursor into emp_no,emp_name,emp_sal;
if exit_flag != 1 then
insert into temp_table_emp values(emp_no,emp_name,emp_sal);
else
leave c_loop;
end if;
end loop c_loop;
select * from temp_table_emp;
select @sex_res; -- 仅仅是看一下会不会执行到
close emp_cursor;
end?
call sp_create_table02('RESEARCH');
Статьи с разными адресами GitHub: GitHub.com/zip и треки/…Добро пожаловать Звезда!