How to insert data from an EXECUTE statement in mySql? - mysql

I have data in a wp_users table, and I want to duplicate the data from that table (except for the ID column) into another table, called wp_users2.
If I didn't care about the id column, which I want to auto-increment, I could just do this:
insert into wp_users2 (select *, NULL as ID from wp_users)
So I know I could do this by typing out all of the column headers except for ID and manually selecting that one as NULL,
SELECT NULL as id, col2, col3...
but I'd like to do it dynamically. I read this great S.O. post about how to do that, and it works, however I can't figure out how to take the data it gives me and put it into an insert statement.
INSERT INTO wp_users2 (
SET #sql = CONCAT('SELECT NULL as ID,',
(SELECT REPLACE(GROUP_CONCAT(COLUMN_NAME), 'ID,', '')
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'wp_users'
AND TABLE_SCHEMA = 'wp1'),
' FROM wp_users');
PREPARE stmt1 FROM #sql;
EXECUTE stmt1;
)
What's the right syntax for that?

As I understand - id is AUTO_INCREMENT field.
So, try to use this script as an example for your task -
CREATE TABLE table1(
id INT(11) NOT NULL AUTO_INCREMENT,
column1 VARCHAR(255) DEFAULT NULL,
column2 VARCHAR(255) DEFAULT NULL,
PRIMARY KEY (id)
);
CREATE TABLE table2(
id INT(11) NOT NULL AUTO_INCREMENT,
column1 VARCHAR(255) DEFAULT NULL,
column2 VARCHAR(255) DEFAULT NULL,
PRIMARY KEY (id)
);
INSERT INTO table1 VALUES
(1, 'c1', 'c2'),
(2, 'c3', 'c4');
SET #source_table = 'table1';
SET #target_table = 'table2';
SET #id = 'id';
SET #columns = NULL;
SELECT group_concat(column_name) INTO #columns FROM information_schema.columns
WHERE
table_schema = 'database_name' -- Set your database name here
AND table_name = #source_table
AND column_name != #id;
SET #insert = concat('INSERT INTO ', #target_table, '(', #id, ',', #columns, ') SELECT NULL, ', #columns, ' FROM ', #source_table);
PREPARE stmt1 FROM #insert;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;

set #sql = (select concat('insert into wp_users2 SELECT NULL,',
group_concat(column_name),' from ',table_name) from information_schema.columns
where table_name = 'wp_users' and table_schema = 'wp1' and column_name != 'id'
order by ordinal_position);
prepare stmt1 from #sql;
execute stmt1;
deallocate prepare stmt1;

Related

Create table and insert using variable

I'd like to create a table and insert data only changing the variable name.
but instead, it creates a table with the name #myId, and not with the value of the variable.
i also have tried to remove the `` but i got an sql error.
set #myId = "tabletest";
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";
CREATE TABLE `#myId` (
`id` int(10) NOT NULL,
`position` int(10) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `#myId` (`id`, `position`) VALUES
(1, 1);
I am not recommending that you do this. Table names should not be coming from variables. However, you did ask a valid question and if you were going to do this, you need dynamic SQL:
SET #sql = 'CREATE TABLE #myId (id int(10) NOT NULL, position int(10) NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=latin1;';
SET #sql = REPLACE(#sql, '#myId', 'tabletest');
PREPARE ct FROM #sql;
EXECUTE ct;
DEALLOCATE PREPARE ct;
SET #sql = 'INSERT INTO #myId (id, position) VALUES (1, 1);';
SET #sql = REPLACE(#sql, '#myId', 'tabletest');
PREPARE st FROM #sql;
EXECUTE st;
DEALLOCATE PREPARE st;
You can then execute:
SELECT * FROM tabletest;
Note that if you wanted to use #myId in the SELECT, you would need more dynamic SQL: Yucch!
Usually the right solution is just a table where you insert rows with an identifier. You can then delete those rows (or invalidate them) if necessary when you are done.
Here is a db<>fiddle.

the count of row( user) for each table begining with cm in the schema

I want all the tables' list with corresponding count of number of NULL entries in column 'user'. I have printed all table's name beginning with cm using
SELECT
TABLE_NAME
FROM
INFORMATION_SCHEMA.TABLES WHERE (TABLE_NAME LIKE 'cm%') ;
but for each table i want to run
SELECT COUNT(1) FROM <TABLENAME> WHERE `create_user` IS NULL
OR `create_time` IS NULL
and print
Create the table below, replacing it with the correct database name:
CREATE TABLE `db`.`tbl_count_null` (
`tableschema` varchar(64) NOT NULL DEFAULT '',
`tablename` varchar(64) NOT NULL DEFAULT '',
`qtd` char(0) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
See if the procedure below meets you:
CREATE DEFINER=`user`#`%` PROCEDURE `nameprocedure`()
BEGIN
DECLARE x, y LONGTEXT;
DECLARE done INT DEFAULT 0;
DECLARE databasesCursor CURSOR FOR
SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME LIKE 'cm%';
DECLARE CONTINUE HANDLER
FOR SQLSTATE '02000' SET done = 1;
OPEN databasesCursor;
myLoop: LOOP
FETCH databasesCursor INTO x, y;
IF NOT done THEN
SET #query = CONCAT("INSERT INTO`db`.`tbl_count_null` (tableschema, tablename, qtd) SELECT '",x,"' AS `schema`,'",y,"' AS `table`,COUNT(1) FROM `",x,"`.`",y,"` WHERE `create_user` IS NULL OR `create_time` IS NULL;");
PREPARE stmt FROM #query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END IF;
END LOOP myLoop;
CLOSE databasesCursor;
END;
After creating the above procedure, call with the command:
call db.nameprocedure;
Verify that the records have been inserted into the table db.tbl_count_null

Mysql 5.7 Stored Procedure error

I an trying to create stored procedure in following format :
DELIMITER $$
CREATE PROCEDURE `CreateInsertLocation` (tableName VARCHAR(255),ts BIGINT(20),systs INT(20),lat FLOAT,lon FLOAT)
BEGIN
DECLARE FoundCount INT;
SELECT COUNT(1) INTO FoundCount
FROM information_schema.tables
WHERE table_schema = 'DB'
AND table_name = tableName;
IF FoundCount = 1 THEN SET #sql = CONCAT('INSERT INTO ',tableName,'
(timestamp, lattitude, longitude,systime)
VALUES
(','ts','lat','lon','systs')');
PREPARE stmt FROM #sql;
EXECUTE stmt;
ELSE
SET #sql = CONCAT('CREATE TABLE `',tableName,'`(
`id` bigint(20) NOT NULL DEFAULT '0',
`timestamp` bigint(20) NOT NULL DEFAULT '0',
`lattitude` float NOT NULL DEFAULT '0',
`longitude` float NOT NULL DEFAULT '0',
`systime` bigint(20) DEFAULT NULL,
KEY `LocIdx` (`vtuId`,`timestamp`),
KEY `SysIdx` (`vtuId`,`systime`),
PRIMARY KEY (id)');
PREPARE stmt FROM #sql;
EXECUTE stmt;
SET #sql = CONCAT('INSERT INTO ',tableName,'
(timestamp, lattitude, longitude,systime)
VALUES
(','ts','lat','lon','systs')');
PREPARE stmt FROM #sql2;
EXECUTE stmt;
END
$$
DELIMITER ;
-- When I am trying to execute this query in Mysql 5.7 I am getting following error
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 '');
PREPARE stmt FROM #sql;
EXECUTE stmt;
ELSE SET #sql = CONCAT' at line 10
Can anyone help to improve this sotred procedure ?
This should work. Pay attention to order of single quotes as it can get tricky.
DELIMITER $$
CREATE PROCEDURE `CreateInsertLocation` (tableName VARCHAR(255),ts BIGINT(20),systs INT(20),lat FLOAT,lon FLOAT)
BEGIN
DECLARE FoundCount INT;
SELECT COUNT(1) INTO FoundCount
FROM information_schema.tables
WHERE table_schema = 'DB'
AND table_name = tableName;
IF FoundCount = 1 THEN
SET #sql = CONCAT('INSERT INTO ',tableName,' (timestamp, lattitude, longitude,systime) VALUES (',ts, ',', lat, ',', lon, ',', systs, ')' );
PREPARE stmt FROM #sql;
EXECUTE stmt;
ELSE
SET #sql = CONCAT('CREATE TABLE `',tableName,'` (
`id` bigint(20) NOT NULL DEFAULT 0,
`timestamp` bigint(20) NOT NULL DEFAULT 0,
`lattitude` float NOT NULL DEFAULT 0,
`longitude` float NOT NULL DEFAULT 0,
`systime` bigint(20) DEFAULT NULL,
KEY `LocIdx` (`vtuId`,`timestamp`),
KEY `SysIdx` (`vtuId`,`systime`),
PRIMARY KEY (id) )' );
PREPARE stmt FROM #sql;
EXECUTE stmt;
END IF;
SET #sql = CONCAT('INSERT INTO ',tableName,' (timestamp, lattitude, longitude,systime) VALUES (',ts, ',', lat , ',', lon, ',', systs, ')');
PREPARE stmt FROM #sql;
EXECUTE stmt;
END
$$
DELIMITER ;
You are using single quote (') for the concat string of your create table statement and the default values within it.
Either put the default values in double quotes ("), escape them (\') or remove them as they are all numberic types.
Edit: Your parameters for the insert statements are also put into quotes which looks wrong, too.
create schema mine;
use mine;
delimiter $$
CREATE PROCEDURE `CreateInsertLocation` (tableName VARCHAR(255),ts BIGINT(20),systs INT(20),lat FLOAT,lon FLOAT)
BEGIN
DECLARE FoundCount INT;
SELECT COUNT(1) INTO FoundCount
FROM information_schema.tables
WHERE table_schema = 'DB'
AND table_name = tableName;
IF FoundCount = 1 THEN SET #sql = CONCAT('INSERT INTO ',tableName,'
(timestamp, lattitude, longitude,systime)
VALUES
(','ts','lat','lon','systs\')');
PREPARE stmt FROM #sql;
EXECUTE stmt;
ELSE
SET #sql = CONCAT('CREATE TABLE ',tableName,'(
`id` bigint(20) NOT NULL DEFAULT \'0\',
`timestamp` bigint(20) NOT NULL DEFAULT \'0\',
`lattitude` float NOT NULL DEFAULT \'0\',
`longitude` float NOT NULL DEFAULT \'0\',
`systime` bigint(20) DEFAULT NULL,
KEY `LocIdx` (`vtuId`,`timestamp`),
KEY `SysIdx` (`vtuId`,`systime`),
PRIMARY KEY (id)');
PREPARE stmt FROM #sql;
EXECUTE stmt;
SET #sql = CONCAT('INSERT INTO ',tableName,'
(timestamp, lattitude, longitude,systime)
VALUES
(','ts','lat','lon','systs\')');
PREPARE stmt FROM #sql2;
EXECUTE stmt;
END if;
end
$$
DELIMITER ;
You can try above code;
Firstly you need to escape all Single quote '
And you forgot to close ENDIF.
In the marked comment, this code was missing a quote to complete concat correctly
$$
CREATE PROCEDURE `CreateInsertLocation` (tableName VARCHAR(255),ts BIGINT(20),systs INT(20),lat FLOAT,lon FLOAT)
BEGIN
DECLARE FoundCount INT;
SELECT COUNT(1) INTO FoundCount
FROM information_schema.tables
WHERE table_schema = 'DB'
AND table_name = tableName;
IF FoundCount = 1 THEN SET #sql = CONCAT('INSERT INTO ',tableName,'
(timestamp, lattitude, longitude,systime)
VALUES
(','ts','lat','lon','systs',')'); /* Error in this line */
PREPARE stmt FROM #sql;
EXECUTE stmt;
ELSE
SET #sql = CONCAT('CREATE TABLE `',tableName,'`(
`id` bigint(20) NOT NULL DEFAULT '0',
`timestamp` bigint(20) NOT NULL DEFAULT '0',
`lattitude` float NOT NULL DEFAULT '0',
`longitude` float NOT NULL DEFAULT '0',
`systime` bigint(20) DEFAULT NULL,
KEY `LocIdx` (`vtuId`,`timestamp`),
KEY `SysIdx` (`vtuId`,`systime`),
PRIMARY KEY (id)');
PREPARE stmt FROM #sql;
EXECUTE stmt;
SET #sql = CONCAT('INSERT INTO ',tableName,'
(timestamp, lattitude, longitude,systime)
VALUES
(','ts','lat','lon','systs')');
PREPARE stmt FROM #sql2;
EXECUTE stmt;
END
$$
DELIMITER ;

Mysql dynamic trigger creation in stored procedure

I want to create the dynamic trigger when call the procedure, it give the mysql server version syntax error, when i select that query and execute in separate query editor it will be executed.
DROP TABLE IF EXISTS auditLog;
CREATE TABLE `auditlog` (
`tableName` VARCHAR(255) DEFAULT NULL,
`rowPK` INT(11) DEFAULT NULL,
`fieldName` VARCHAR(255) DEFAULT NULL,
`old_value` VARCHAR(255) DEFAULT NULL,
`new_value` VARCHAR(255) DEFAULT NULL,
`ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=ARCHIVE;
CREATE TABLE country(countryname VARCHAR(100);
DROP PROCEDURE IF EXISTS addLogTrigger;
DELIMITER $
/*
call addLogTrigger('country','CountryID','CountryName')
*/
CREATE PROCEDURE addLogTrigger
(IN tableName VARCHAR(255), IN pkField VARCHAR(255),IN column_name VARCHAR(50))
BEGIN
SET #qry = CONCAT
(
'
DROP TRIGGER IF EXISTS ', tableName, '_AU ;
CREATE TRIGGER ', tableName, '_AU AFTER UPDATE ON ', tableName, '
FOR EACH ROW
','
INSERT INTO auditLog (',
'tableName, ',
'rowPK, ',
'fieldName, ',
'old_value, ',
'new_value'
') VALUES
( ''',
tablename, ''', NEW.',
pkField, ', ''',
column_name, ''', OLD.',
column_name, ', NEW.',
column_name,
');
'
, '
'
) ;
SELECT #qry;
PREPARE stmt FROM #qry;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END$
DELIMITER ;
Karthikeyan,
You can not create a trigger inside stored procedure.
Trigger is a DDL statement which is not allowed inside procedures.
" ERROR 1303 (2F003): Can't create a TRIGGER from within another stored routine "
To solve your purpose you can do following:
Take current values from table inside variable.
Simply write a update query inside your procedure, then check whether value is updated or not by "ROW_COUNT()".
Compare new value with old value, of changed then manually insert into change_log table.

Find all those columns which have only null values, in a MySQL table

The situation is as follows:
I have a substantial number of tables, with each a substantial number of columns. I need to deal with this old and to-be-deprecated database for a new system, and I'm looking for a way to eliminate all columns that have - apparently - never been in use.
I wanna do this by filtering out all columns that have a value on any given row, leaving me with a set of columns where the value is NULL in all rows. Of course I could manually sort every column descending, but that'd take too long as I'm dealing with loads of tables and columns. I estimate it to be 400 tables with up to 50 (!) columns per table.
Is there any way I can get this information from the information_schema?
EDIT:
Here's an example:
column_a column_b column_c column_d
NULL NULL NULL 1
NULL 1 NULL 1
NULL 1 NULL NULL
NULL NULL NULL NULL
The output should be 'column_a' and 'column_c', for being the only columns without any filled in values.
You can avoid using a procedure by dynamically creating (from the INFORMATION_SCHEMA.COLUMNS table) a string that contains the SQL you wish to execute, then preparing a statement from that string and executing it.
The SQL we wish to build will look like:
SELECT * FROM (
SELECT 'tableA' AS `table`,
IF(COUNT(`column_a`), NULL, 'column_a') AS `column`
FROM tableA
UNION ALL
SELECT 'tableB' AS `table`,
IF(COUNT(`column_b`), NULL, 'column_b') AS `column`
FROM tableB
UNION ALL
-- etc.
) t WHERE `column` IS NOT NULL
This can be done using the following:
SET group_concat_max_len = 4294967295; -- to overcome default 1KB limitation
SELECT CONCAT(
'SELECT * FROM ('
, GROUP_CONCAT(
'SELECT ', QUOTE(TABLE_NAME), ' AS `table`,'
, 'IF('
, 'COUNT(`', REPLACE(COLUMN_NAME, '`', '``'), '`),'
, 'NULL,'
, QUOTE(COLUMN_NAME)
, ') AS `column` '
, 'FROM `', REPLACE(TABLE_NAME, '`', '``'), '`'
SEPARATOR ' UNION ALL '
)
, ') t WHERE `column` IS NOT NULL'
)
INTO #sql
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = DATABASE();
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
See it on sqlfiddle.
I am not an expert in SQL procedures, hence giving general idea using SQL queries and a PHP/python script.
use SHOW TABLES or some other query on INFORMATION_SCHEMA database to get all tables in your database MY_DATABASE
do a query to generate a statement to get all column names in a particular table, this will be used in next query.
SELECT Group_concat(Concat( "MAX(", column_name, ")" ))
FROM information_schema.columns
WHERE table_schema = 'MY_DATABSE'
AND table_name = 'MY_TABLE'
ORDER BY table_name,ordinal_position
You will get an output like MAX(column_a),MAX(column_b),MAX(column_c),MAX(column_d)
Use this output to generate final query :
SELECT Max(column_a), Max(column_b), Max(column_c), Max(column_d) FROM MY_DATABASE.MY_TABLE
The output would be :
MAX(column_a) MAX(column_b) MAX(column_c) MAX(column_d)
NULL 1 NULL 1
All the columns with Max value as NULL are the ones which have all values NULL
You can take advantage of the behavior of COUNT aggregate function regarding NULLs. By passing the field as argument, the COUNT function returns the number of non-NULL values while COUNT(*) returns the total number of rows. Thus you can calculate the ratio of NULL to "acceptable" values.
I will give an example with the following table structure:
CREATE TABLE `t1` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`col_1` int(10) unsigned DEFAULT NULL,
`col_2` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`id`)
) ;
-- let's fill the table with random values
INSERT INTO t1(col_1,col_2) VALUES(1,2);
INSERT INTO t1(col_1,col_2)
SELECT
IF(RAND() > 0.5, NULL ,FLOOR(RAND()*1000),
IF(RAND() > 0.5, NULL ,FLOOR(RAND()*1000) FROM t1;
-- run the last INSERT-SELECT statement a few times
SELECT COUNT(col_1)/COUNT(*) AS col_1_ratio,
COUNT(col_2)/COUNT(*) AS col_2_ratio FROM t1;
You can write a function that automatically constructs a query from the
INFORMATION_SCHEMA database by passing the table name as input variable.
Here's how to obtain the structure data directly from INFORMATION_SCHEMA tables:
SET #query:=CONCAT("SELECT #column_list:=GROUP_CONCAT(col) FROM (
SELECT CONCAT('COUNT(',c.COLUMN_NAME,')/COUNT(*)') AS col
FROM INFORMATION_SCHEMA.COLUMNS c
WHERE NOT COLUMN_KEY IN('PRI') AND TABLE_SCHEMA=DATABASE()
AND TABLE_NAME='t1' ORDER BY ORDINAL_POSITION ) q");
PREPARE COLUMN_SELECT FROM #query;
EXECUTE COLUMN_SELECT;
SET #null_counters_sql := CONCAT('SELECT ',#column_list, ' FROM t1');
PREPARE NULL_COUNTERS FROM #null_counters_sql;
EXECUTE NULL_COUNTERS;
SQL Fiddle Demo Link
I have created 4 tables. Three for demo and one nullcolumns is the compulsory part of solution. Among three tables, only salary and dept have columns with all values null (you may have a look at their script).
The compulsory table and the procedure are given at the end
You can copy paste and run (the compulsory part or all) as sql (just you have to change the delimiter to //) in your desired database on your localhost and then --- call get(); and see the results
CREATE TABLE IF NOT EXISTS `dept` (
`did` int(11) NOT NULL,
`dname` varchar(50) DEFAULT NULL,
PRIMARY KEY (`did`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `dept` (`did`, `dname`) VALUES
(1, NULL),
(2, NULL),
(3, NULL),
(4, NULL),
(5, NULL);
CREATE TABLE IF NOT EXISTS `emp` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`ename` varchar(50) NOT NULL,
`did` int(11) NOT NULL,
PRIMARY KEY (`ename`),
KEY `deptid` (`did`),
KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ;
INSERT INTO `emp` (`id`, `ename`, `did`) VALUES
(1, 'e1', 4),
(2, 'e2', 4),
(3, 'e3', 2),
(4, 'e4', 4),
(5, 'e5', 3);
CREATE TABLE IF NOT EXISTS `salary` (
`EmpCode` varchar(50) NOT NULL,
`Amount` int(11) DEFAULT NULL,
`Date` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `salary` (`EmpCode`, `Amount`, `Date`) VALUES
('1', 344, NULL),
('2', NULL, NULL);
------------------------------------------------------------------------
------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS `nullcolumns` (
`Table_Name` varchar(100) NOT NULL,
`Column_Name` varchar(100) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--Only one procedure Now
CREATE PROCEDURE get(dn varchar(100))
BEGIN
declare c1 int; declare b1 int default 0; declare tn varchar(30);
declare c2 int; declare b2 int; declare cn varchar(30);
select count(*) into c1 from information_schema.tables where table_schema=dn;
delete from nullcolumns;
while b1<c1 do
select table_name into tn from information_schema.tables where
table_schema=dn limit b1,1;
select count(*) into c2 from information_schema.columns where
table_schema=dn and table_name=tn;
set b2=0;
while b2<c2 do
select column_name into cn from information_schema.columns where
table_schema=dn and table_name=tn limit b2,1;
set #nor := 0;
set #query := concat("select count(*) into #nor from ", dn,".",tn);
prepare s1 from #query;
execute s1;deallocate prepare s1;
if #nor>0 then set #res := 0;
set #query := concat("select ((select max(",cn,") from ", dn,".",tn,")
is NULL) into #res");
prepare s1 from #query;
execute s1;deallocate prepare s1;
if #res=1 then
insert into nullcolumns values(tn,cn);
end if; end if;
set b2=b2+1;
end while;
set b1=b1+1;
end while;
select * from nullcolumns;
END;
You can easily execute stored procedure easily as sql in your phpmyadin 'as it is' just change the Delimiters (at the bottom of SQL quesry box) to // Then
call get();
And Enjoy :)
You can see Now the table nullcolumns showing all columns having 100/100 null values along with the table Names
In procedure code if #nor>0 restricts that no empty table should be included in results you can remove that restriction.
I think you can do this with GROUP_CONCAT and GROUP BY:
select length(replace(GROUP_CONCAT(my_col), ',', ''))
from my_table
group by my_col
(untested)
EDIT: the docs don't seem to state that GROUP_CONCAT needs a corresponding GROUP BY, so try this:
select
length(replace(GROUP_CONCAT(col_a), ',', '')) as len_a
, length(replace(GROUP_CONCAT(col_b), ',', '')) as len_b
, length(replace(GROUP_CONCAT(col_c), ',', '')) as Len_c
from my_table
You can do it with a prepared statement fed by MySQL's information scheme:
SET #TABLE_NAME= '...';
SET SESSION group_concat_max_len = 1000000;
SELECT
CONCAT('SELECT * FROM (',
Group_concat(CONCAT("SELECT '", COLUMN_NAME, "' AS n, MAX(", COLUMN_NAME, ") AS v FROM ", #TABLE_NAME ) SEPARATOR ' UNION ALL ')
, ") x WHERE v IS NOT null"
)
INTO #q
FROM information_schema.columns
WHERE table_schema = (SELECT DATABASE())
AND table_name = #TABLE_NAME
ORDER BY table_name,ordinal_position
;
PREPARE ps FROM #q;
EXECUTE ps;
select column_name
from user_tab_columns
where table_name='Table_name' and num_nulls>=1;
Just by simple query you will get those two columns.