需求: 查询指定库中所有的表中字段记录为空的字段,把这些字段删除掉。注:如果某张表中有100条记录,但有一个字段只在某一条记录中有值,此字段就不能删除。要完全为空才能删除。存储过程代码我以写了一小部份,但存储过程实在不熟悉,所以求大家帮我写一下。感谢。100分送上。BEGIN
/*局部变量的定义 */
declare tmpName varchar(200) default '' ;
declare sum1 int;
declare sum2 int;
declare resultNames cursor FOR SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = 'department' AND table_schema = 'sz8_news';declare CONTINUE HANDLER FOR SQLSTATE '02000' SET tmpname = null;OPEN resultNames;/*打开游标*/FETCH resultNames into tmpname; -- 取数据
/* 循环体 */
WHILE ( tmpname is not null) DO set @count = "select count(*) into @sum1 from department";/*总记录数*/
set @sql = concat('select count(*) into @sum2 from department where ',tmpname," is null;");/*为空的总记录数*/ PREPARE stmt1 FROM @count ;
EXECUTE stmt1 ;
DEALLOCATE PREPARE stmt1; PREPARE stmt2 FROM @sql;
EXECUTE stmt2;
DEALLOCATE PREPARE stmt2; set sum1 = @sum1+0;
set sum2 = @sum2+0;/*判断字段是否为空*/
if sum1==sum2 then
-- 还需要大家帮我写两个循环及删除语句,这一段我写了一天了.存储过程不熟写得好累.
-- select sum1,sum2;
end if;
/*游标向下走一步*/
FETCH resultNames INTO tmpname;
END WHILE;CLOSE resultNames; /*关闭游标*/
END
/*局部变量的定义 */
declare tmpName varchar(200) default '' ;
declare sum1 int;
declare sum2 int;
declare resultNames cursor FOR SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = 'department' AND table_schema = 'sz8_news';declare CONTINUE HANDLER FOR SQLSTATE '02000' SET tmpname = null;OPEN resultNames;/*打开游标*/FETCH resultNames into tmpname; -- 取数据
/* 循环体 */
WHILE ( tmpname is not null) DO set @count = "select count(*) into @sum1 from department";/*总记录数*/
set @sql = concat('select count(*) into @sum2 from department where ',tmpname," is null;");/*为空的总记录数*/ PREPARE stmt1 FROM @count ;
EXECUTE stmt1 ;
DEALLOCATE PREPARE stmt1; PREPARE stmt2 FROM @sql;
EXECUTE stmt2;
DEALLOCATE PREPARE stmt2; set sum1 = @sum1+0;
set sum2 = @sum2+0;/*判断字段是否为空*/
if sum1==sum2 then
-- 还需要大家帮我写两个循环及删除语句,这一段我写了一天了.存储过程不熟写得好累.
-- select sum1,sum2;
end if;
/*游标向下走一步*/
FETCH resultNames INTO tmpname;
END WHILE;CLOSE resultNames; /*关闭游标*/
END
解决方案 »
- 我向数据库中插入时间 2012-4-10 为什么到数据库里显示1982
- mysql 嵌套游标的问题
- 关于MyISAM表问题
- 请问如何把mysql的数据导入到sql2005中?
- 复制字段问题
- <MySqlAPI>错误号:2013
- postgresql有没有判断游标打开或关闭的属性?
- 在我的phpadmin中总有这句"使用链接表的额外特性尚未激活。要查出原因,请单击此处。"是什么意思呢?
- 求助,如何优化count 统计left join group by having 结果集的记录数
- 更新某id记录,没更新的自动删除,请问有这样的语句吗
- mysql auto_increment
- 让大家帮我写一段这种需求的mysql存储过程
你到底是 “指定库中所有的表” 还是 仅查这个 table_name = 'department' ?
终于看到你了。。我给你发站内短信了。你回我吧。我找的就是你。你到底是 “指定库中所有的表” 还是 仅查这个 table_name = 'department' ?
是“指定库中所有的表”哈。。我现在还没有加入循环功能。因为我不会。所以就只针对单个表来作测试。
具体思路:
使用嵌套cursor, 逐表取列,如果该列is not null的count(1)值为0,则drop 该列, 生成alter table语句,插入临时表。(注:不能直接生成该语句, 马上执行,这样会影响当前cursor获取下一条记录)完整的存储过程如下:
delimiter //CREATE PROCEDURE drop_nullcolumns(IN userName varchar(256))
BEGIN
DECLARE v int DEFAULT 0;
DECLARE tname varchar(200) default '' ;
DECLARE done int DEFAULT 0;
DECLARE tmpName varchar(200) default '' ;
DECLARE alterStmt varchar(512) default '';
DECLARE tableNames cursor FOR SELECT table_name FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = userName;
DECLARE resultNames cursor FOR SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = tname AND table_schema = userName;
DECLARE tmpCursor cursor FOR select stmt from tmp_dropnullcolumns;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1;
/* DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK; */
SET @x=0;
SET @alterstr='';
/* select tname; */
/* create a temporary table to store the 'alter table ' statement */
create temporary table if not exists tmp_dropnullcolumns(stmt VARCHAR(256));
OPEN tableNames;
WHILE ( done = 0 ) DO
FETCH tableNames into tname;
if not done then
/* select tname; */
OPEN resultNames;
WHILE (done = 0) DO
FETCH resultNames into tmpName;
if not done then
/* select tmpName; */
set @sqlstr = concat('select count(1) into @x from ', tname, ' where ', tmpName, ' is not null');
prepare stmt from @sqlstr;
execute stmt;
deallocate prepare stmt;
if (@x = 0) then
set @alterstr = concat('alter table ', tname, ' drop column ', tmpName);
select @alterstr;
insert into tmp_dropnullcolumns values(@alterstr);
end if;
end if;
END WHILE;
CLOSE resultNames;
set done = 0;
end if;
END WHILE;
set done = 0;
CLOSE tableNames; OPEN tmpCursor;
WHILE ( done = 0 ) DO
if not done then
FETCH tmpCursor into alterStmt;
select alterStmt;
set @sqlstr = concat (' ', alterStmt);
prepare stmt from @sqlstr;
execute stmt;
deallocate prepare stmt;
end if;
END WHILE;
CLOSE tmpCursor;
DROP table tmp_dropnullcolumns;
END
//以下是执行结果:
mysql> call drop_nullcolumns('test');//
+---------------------------------+
| @alterstr |
+---------------------------------+
| alter table test drop column id |
+---------------------------------+
1 row in set (0.19 sec)+-----------------------------------+
| @alterstr |
+-----------------------------------+
| alter table test drop column name |
+-----------------------------------+
1 row in set (0.22 sec)+------------------------------------------+
| @alterstr |
+------------------------------------------+
| alter table zsystempage drop column site |
+------------------------------------------+
1 row in set (0.53 sec)+-----------------------------------------+
| @alterstr |
+-----------------------------------------+
| alter table zsystempage drop column url |
+-----------------------------------------+
1 row in set (0.55 sec)+------------------------------------------------+
| @alterstr |
+------------------------------------------------+
| alter table zsystempage drop column updatetime |
+------------------------------------------------+
1 row in set (0.58 sec)+--------------------------------------------+
| @alterstr |
+--------------------------------------------+
| alter table zsystempage drop column length |
+--------------------------------------------+
1 row in set (0.59 sec)+----------------------------------------------+
| @alterstr |
+----------------------------------------------+
| alter table zsystempage drop column filename |
+----------------------------------------------+
1 row in set (0.61 sec)+---------------------------------+
| alterStmt |
+---------------------------------+
| alter table test drop column id |
+---------------------------------+
1 row in set (0.63 sec)+-----------------------------------+
| alterStmt |
+-----------------------------------+
| alter table test drop column name |
+-----------------------------------+
1 row in set (0.75 sec)ERROR 1090 (42000): You can't delete all columns with ALTER TABLE; use DROP TABLE instead
mysql> show tables; //
+----------------+
| Tables_in_test |
+----------------+
| a |
| a2 |
| aa |
| t123 |
| t5 |
| tbigint |
| tdate |
| test |
| tt |
| zcleanurl |
| zsystempage |
+----------------+
11 rows in set (0.00 sec)mysql> desc test;//
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| name | varchar(32) | YES | | a | |
+-------+-------------+------+-----+---------+-------+
1 row in set (0.02 sec)仅供参考。实际上,如果某表所有字段都是空,没有值,最后只能剩下一个字段,不能将所有字段全部清除。其实,写一个jdbc的java小程序,也许来得更快。思路都是一样的。
+------+------+------+------+
| id | col1 | col2 | col3 |
+------+------+------+------+
| 1 | NULL | NULL | NULL |
| 2 | 2 | NULL | NULL |
+------+------+------+------+
2 rows in set (0.00 sec)mysql> select * from t2;
+------+------+------+------+
| id | col1 | col2 | col3 |
+------+------+------+------+
| 1 | NULL | 1 | NULL |
| 2 | NULL | 2 | 2 |
+------+------+------+------+
2 rows in set (0.00 sec)mysql> select * from t3;
+------+------+------+------+
| id | col1 | col2 | col3 |
+------+------+------+------+
| 1 | NULL | 1 | NULL |
| 2 | 2 | 2 | 2 |
+------+------+------+------+
2 rows in set (0.00 sec)mysql> delimiter //
mysql> drop PROCEDURE p_maoweiwer//
Query OK, 0 rows affected (0.00 sec)mysql> CREATE PROCEDURE p_maoweiwer()
-> BEGIN
-> DECLARE done INT DEFAULT 0;
->
-> DECLARE cTbl varchar(64);
-> DECLARE cCol varchar(64);
->
-> DECLARE cur1 CURSOR FOR
-> select TABLE_NAME,COLUMN_NAME
-> from INFORMATION_SCHEMA.COLUMNS
-> where TABLE_SCHEMA='maoweiwer'
-> and IS_NULLABLE='YES'
-> order by TABLE_NAME;
-> DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
->
-> set @sqlDrop='';
-> OPEN cur1;
-> FETCH cur1 INTO cTbl, cCol;
-> WHILE done = 0 DO
-> set @x=0;
-> set @sql=concat('select 1 into @x from `',cTbl,'` where `',cCol,'` is not null limit 1');
-> PREPARE stmt1 FROM @sql;
-> EXECUTE stmt1;
-> DEALLOCATE PREPARE stmt1;
-> if @x=0 then
-> set @sqlDrop=concat('alter table `',cTbl,'` drop COLUMN`',cCol,'`;');
-> PREPARE stmt1 FROM @sqlDrop;
-> EXECUTE stmt1;
-> DEALLOCATE PREPARE stmt1;
-> end if ;
-> set done = 0;
-> FETCH cur1 INTO cTbl, cCol;
-> END WHILE;
-> CLOSE cur1;
->
-> END//
Query OK, 0 rows affected (0.00 sec)mysql> delimiter ;
mysql>
mysql> call p_maoweiwer();
Query OK, 0 rows affected (0.13 sec)mysql> select * from t1;
+------+------+
| id | col1 |
+------+------+
| 1 | NULL |
| 2 | 2 |
+------+------+
2 rows in set (0.00 sec)mysql> select * from t2;
+------+------+------+
| id | col2 | col3 |
+------+------+------+
| 1 | 1 | NULL |
| 2 | 2 | 2 |
+------+------+------+
2 rows in set (0.00 sec)mysql> select * from t3;
+------+------+------+------+
| id | col1 | col2 | col3 |
+------+------+------+------+
| 1 | NULL | 1 | NULL |
| 2 | 2 | 2 | 2 |
+------+------+------+------+
2 rows in set (0.00 sec)mysql>
先不说了我先看下你们写的。膜拜一下。
马上给分,同时我自己测试了一下,针对我数据库表的特殊需求,把程序进行了一小点的改进。BEGIN
DECLARE done INT DEFAULT 0; DECLARE cTbl varchar(64);
DECLARE cCol varchar(64); DECLARE cur1 CURSOR FOR
select TABLE_NAME,COLUMN_NAME
from INFORMATION_SCHEMA.COLUMNS
where TABLE_SCHEMA='sz8_news'
and IS_NULLABLE='YES'
order by TABLE_NAME;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; set @sqlDrop='';
OPEN cur1;
FETCH cur1 INTO cTbl, cCol;/*得到表名及列名*/
WHILE done = 0 DO
set @x=0;
/*主要改进了这里把空值也纳入判断条件中去,即如果字段为null或空*/
set @sql=concat('select 1 into @x from ',cTbl,' where ',cCol,' is not null and ',cCol,' !="" limit 1'); PREPARE stmt1 FROM @sql;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1; if @x=0 then
set @sqlDrop=concat('alter table `',cTbl,'` drop COLUMN`',cCol,'`;'); PREPARE stmt1 FROM @sqlDrop;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
end if ;
set done = 0;
FETCH cur1 INTO cTbl, cCol;
END WHILE;
CLOSE cur1; END