和往常一样,4点前搞定了日常的工作安排,正准备好好缓口气,检查一下以前写的代码的时候,突然收到了个“简单的”需求。
在MySQL数据库中,用存储过程或函数完成查询所有数据库表中BrandId字段等于0的数量。收到这个需求,第一反应,这个简单,三两下搞定。这一刻,也决定了我之后掉入了Mysql的巨坑之中,开启了崭新的填坑之旅。
作为用惯了SqlServer2008的我来说,这种查询是小菜一碟,因为SQLserver支持组装的Sql运行(关键字exec)。在自定义函数中,可以自定义变量,把值赋给自定义变量后,可作为表名组装成SQL,然后运行。自定义函数这东东早就写了n遍了,不过就是用MySQL重新写一下而已,可是却发现,报错!
神奇了,对于SqlServer很简单的东西Mysql要怎么弄?百度了一下,MySQL不支持用自定义函数执行SQL语句,真他娘的遇到鬼了,欺负老子读书少,以前打了太多酱油么。
用度娘查询了一下其他的小伙伴怎么搞的,运行了这么多年的MySQL总会有人遇到这种事情吧,而且这个需求也应该有很大机会遇到。偶然瞄到了一个2017年的帖子,有小伙伴遇到了相同的问题,结果发现,他们没把解决方案发出来,晴天霹雳啊!꒰╬•᷅д•᷄╬꒱
这也造成了我写这文章的原因,把这个方案放到网上,看看以后有没有有缘人瞄一眼,毕竟互联网的精神就是开放,共享。
废话不多说,直接上代码:
1、首先查询数据库中有这个字段的数据库表数量:
drop FUNCTION if exists GetTableCount;
CREATE FUNCTION GetTableCount()
RETURNS int(11)
begin
DECLARE x int;
select count(table_name) into x
from information_schema.COLUMNS as a
where a.table_name in (select table_name from information_schema.tables where table_schema='wm_cloud0' and table_type='base table')
AND a.table_schema='wm_cloud0' and a.COLUMN_NAME="BrandId";
RETURN x;
end;
2、根据表名查询数据库表有几条brandId=0的记录:
rop procedure if exists GetTableCountByNameReturn;
create PROCEDURE GetTableCountByNameReturn(tablename VARCHAR(200),out p_recordcount int,out message varchar(500))
BEGIN
SET @sql=concat("select count(1) as count into @recordcount from ",tablename," where BrandId=0");
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
set p_recordcount=@recordcount;
END;
p_recordcount 是返回值,out是返回值的标志;message 原本是定义sql运行错误,返回的错误内容。
3、使用存储过程查询。
drop procedure if exists GetTableCountByName; -- 如果存在就删除
create PROCEDURE GetTableCountByName()
begin
DECLARE _name VARCHAR(200);
DECLARE x int;
DECLARE y int;
DECLARE z int;
DECLARE i int;
DECLARE _message VARCHAR(500);
drop table tmp; -- 删除临时表
create temporary table if not exists tmp -- 如果表已存在,则使用关键词 if not exists 可以防止发生错误
(
count int(11),
name varchar(200)
);
select GetTableCount() into x; -- 查询所有条数
SET i=0;
WHILE i
-- SET y=x-1;
SET y=i;
-- select table_name into _name from information_schema.tables where table_schema='wm_cloud0' and table_type='base table' ORDER BY CREATE_TIME LIMIT y,1;
select table_name into _name
from information_schema.COLUMNS as a
where a.table_name in (select table_name from information_schema.tables where table_schema='wm_cloud0' and table_type='base table')
AND a.table_schema='wm_cloud0' and a.COLUMN_NAME="BrandId" LIMIT y,1;
call GetTableCountByNameReturn(_name,z,_message);
insert into tmp(count,name) value(z,_name);
SET i=i+1;
END WHILE;
SELECT * from tmp;
end;
这里创建了临时表(tmp),然后 WHILE(条数)调用存储过程(GetTableCountByNameReturn)把数据添加到了临时表中。记得要清空临时表,否则在关闭链接前会一直存在。存储过程最后,直接查询临时表。
好了,这样就搞定了!