Hãy chọn một bảng mẫu trên máy của tôi:
mysql> show create table weisci_jaws_staging2.users\G
*************************** 1. row ***************************
Table: users
Create Table: CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(32) NOT NULL DEFAULT '',
`passwd` varchar(32) NOT NULL DEFAULT '',
`user_type` tinyint(4) DEFAULT '2',
`recovery_key` varchar(48) DEFAULT NULL,
`name` varchar(255) DEFAULT NULL,
`email` varchar(255) DEFAULT NULL,
`url` varchar(255) DEFAULT NULL,
`timezone` varchar(5) DEFAULT NULL,
`language` varchar(5) DEFAULT NULL,
`theme` varchar(24) DEFAULT NULL,
`editor` varchar(24) DEFAULT NULL,
`last_login` datetime DEFAULT NULL,
`createtime` datetime DEFAULT NULL,
`updatetime` datetime DEFAULT NULL,
`change_passwd` tinyint(1) NOT NULL DEFAULT '1',
`never_expire` tinyint(1) NOT NULL DEFAULT '1',
`bad_passwd_count` smallint(6) DEFAULT '0',
`last_access` bigint(20) DEFAULT '0',
`enabled` tinyint(1) NOT NULL DEFAULT '1',
PRIMARY KEY (`id`),
UNIQUE KEY `users_username_idx` (`username`)
) ENGINE=MyISAM AUTO_INCREMENT=160 DEFAULT CHARSET=utf8
1 row in set (0.02 sec)
mysql> select count(1) from weisci_jaws_staging2.users;
+----------+
| count(1) |
+----------+
| 117 |
+----------+
1 row in set (0.00 sec)
mysql>
Với bảng này, đây là hai câu hỏi:
- Những cột nào là nullable?
- Những cột nào là nullable?
Truy vấn này sẽ tìm ra cho bạn:
select is_nullable,GROUP_CONCAT(column_name) column_list
from information_schema.columns
where table_schema = 'weisci_jaws_staging2'
and table_name = 'users'
group by is_nullable;
Kiểm tra kết quả của truy vấn đó cho bảng:
mysql> select is_nullable,GROUP_CONCAT(column_name) column_list
-> from information_schema.columns
-> where table_schema = 'weisci_jaws_staging2'
-> and table_name = 'users'
-> group by is_nullable;
+-------------+------------------------------------------------------------------------------------------------------------------------------------+
| is_nullable | column_list |
+-------------+------------------------------------------------------------------------------------------------------------------------------------+
| NO | id,never_expire,change_passwd,enabled,username,passwd |
| YES | recovery_key,last_access,bad_passwd_count,updatetime,createtime,last_login,editor,user_type,language,timezone,url,email,name,theme |
+-------------+------------------------------------------------------------------------------------------------------------------------------------+
2 rows in set (0.01 sec)
mysql>
OK, chúng tôi có hai danh sách. chúng ta học được gì từ việc này?
- Nếu bạn nhận được hai danh sách, không cần kiểm tra bảng thực tế vì bảng có các cột không phải NULL theo định nghĩa.
- Nếu bạn nhận được một danh sách, thì
- Nếu bạn chỉ nhận được is_nullable = 'NO', không cần kiểm tra bảng thực tế vì bảng có các cột không phải NULL theo định nghĩa.
- Nếu bạn chỉ nhận được is_nullable = 'CÓ', bảng thực tế sẽ hơi giòn. Sẽ không có KHÓA CHÍNH, bạn nghèo, tâm hồn đau khổ !!! NGAY BÂY GIỜ, bạn phải dùng đến việc đọc mọi hàng từ bảng thực tế.
Nếu bạn đang tìm kiếm chỉ các cột không null, thì đây sẽ là truy vấn mong muốn của bạn:
select GROUP_CONCAT(column_name) nonnull_columns
from information_schema.columns
where table_schema = 'weisci_jaws_staging2'
and table_name = 'users'
and is_nullable = 'NO';
Đây là đầu ra của truy vấn này:
mysql> select GROUP_CONCAT(column_name) nonnull_columns
-> from information_schema.columns
-> where table_schema = 'weisci_jaws_staging2'
-> and table_name = 'users'
-> and is_nullable = 'NO';
+-------------------------------------------------------+
| nonnull_columns |
+-------------------------------------------------------+
| id,username,passwd,change_passwd,never_expire,enabled |
+-------------------------------------------------------+
1 row in set (0.01 sec)
mysql>
Xóa GROUP_CONCAT, bạn sẽ nhận được điều này:
mysql> select column_name nonnull_column
-> from information_schema.columns
-> where table_schema = 'weisci_jaws_staging2'
-> and table_name = 'users'
-> and is_nullable = 'NO';
+----------------+
| nonnull_column |
+----------------+
| id |
| username |
| passwd |
| change_passwd |
| never_expire |
| enabled |
+----------------+
6 rows in set (0.01 sec)
mysql>
Hãy thử một lần !!!
LƯU Ý : Xin lưu ý rằng tôi không cần phải đọc nội dung dữ liệu của bảng thực tế. Điều đó hiệu quả hơn nhiều so với việc đọc toàn bộ bảng.
CẬP NHẬT 2012-11-15 13:40 EDT
Mã từ câu trả lời của @ Sensware đưa ra NULL
các cột. Các câu hỏi ban đầu yêu cầu cho non-NULL
các cột. Tôi đã tăng mã để kiểm tra bảng của mình:
SET group_concat_max_len = 4294967295; -- to overcome default 1KB limitation
SELECT CONCAT(
'SELECT * FROM ('
, GROUP_CONCAT(
CONCAT(
'SELECT ', QUOTE(TABLE_NAME), ' AS `table`,'
, 'IF('
, 'COUNT(`', REPLACE(COLUMN_NAME, '`', '``'), '`),'
, 'NULL,'
, QUOTE(COLUMN_NAME)
, ') AS `column` '
, 'FROM `',
REPLACE(TABLE_SCHEMA, '`', '``'), '`.`',
REPLACE(TABLE_NAME, '`', '``'), '`'
)
SEPARATOR ' UNION ALL '
)
, ') t WHERE `column` IS NOT NULL'
)
INTO @sql
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'weisci_jaws_staging2'
AND TABLE_NAME = 'users';
SELECT @sql\G
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Đây là đầu ra:
mysql> SET group_concat_max_len = 4294967295; -- to overcome default 1KB limitation
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT CONCAT(
-> 'SELECT * FROM ('
-> , GROUP_CONCAT(
-> CONCAT(
-> 'SELECT ', QUOTE(TABLE_NAME), ' AS `table`,'
-> , 'IF('
-> , 'COUNT(`', REPLACE(COLUMN_NAME, '`', '``'), '`),'
-> , 'NULL,'
-> , QUOTE(COLUMN_NAME)
-> , ') AS `column` '
-> , 'FROM `',
-> REPLACE(TABLE_SCHEMA, '`', '``'), '`.`',
-> REPLACE(TABLE_NAME, '`', '``'), '`'
-> )
-> SEPARATOR ' UNION ALL '
-> )
-> , ') t WHERE `column` IS NOT NULL'
-> )
-> INTO @sql
-> FROM INFORMATION_SCHEMA.COLUMNS
-> WHERE TABLE_SCHEMA = 'weisci_jaws_staging2'
-> AND TABLE_NAME = 'users';
Query OK, 1 row affected (0.02 sec)
mysql> SELECT @sql\G
*************************** 1. row ***************************
@sql: SELECT * FROM (SELECT 'users' AS `table`,IF(COUNT(`id`),NULL,'id') AS `column` FROM `weisci_jaws_staging2`.`users` UNION ALL SELECT 'users' AS `table`,IF(COUNT(`username`),NULL,'username') AS `column` FROM `weisci_jaws_staging2`.`users` UNION ALL SELECT 'users' AS `table`,IF(COUNT(`passwd`),NULL,'passwd') AS `column` FROM `weisci_jaws_staging2`.`users` UNION ALL SELECT 'users' AS `table`,IF(COUNT(`user_type`),NULL,'user_type') AS `column` FROM `weisci_jaws_staging2`.`users` UNION ALL SELECT 'users' AS `table`,IF(COUNT(`recovery_key`),NULL,'recovery_key') AS `column` FROM `weisci_jaws_staging2`.`users` UNION ALL SELECT 'users' AS `table`,IF(COUNT(`name`),NULL,'name') AS `column` FROM `weisci_jaws_staging2`.`users` UNION ALL SELECT 'users' AS `table`,IF(COUNT(`email`),NULL,'email') AS `column` FROM `weisci_jaws_staging2`.`users` UNION ALL SELECT 'users' AS `table`,IF(COUNT(`url`),NULL,'url') AS `column` FROM `weisci_jaws_staging2`.`users` UNION ALL SELECT 'users' AS `table`,IF(COUNT(`timezone`),NULL,'timezone') AS `column` FROM `weisci_jaws_staging2`.`users` UNION ALL SELECT 'users' AS `table`,IF(COUNT(`language`),NULL,'language') AS `column` FROM `weisci_jaws_staging2`.`users` UNION ALL SELECT 'users' AS `table`,IF(COUNT(`theme`),NULL,'theme') AS `column` FROM `weisci_jaws_staging2`.`users` UNION ALL SELECT 'users' AS `table`,IF(COUNT(`editor`),NULL,'editor') AS `column` FROM `weisci_jaws_staging2`.`users` UNION ALL SELECT 'users' AS `table`,IF(COUNT(`last_login`),NULL,'last_login') AS `column` FROM `weisci_jaws_staging2`.`users` UNION ALL SELECT 'users' AS `table`,IF(COUNT(`createtime`),NULL,'createtime') AS `column` FROM `weisci_jaws_staging2`.`users` UNION ALL SELECT 'users' AS `table`,IF(COUNT(`updatetime`),NULL,'updatetime') AS `column` FROM `weisci_jaws_staging2`.`users` UNION ALL SELECT 'users' AS `table`,IF(COUNT(`change_passwd`),NULL,'change_passwd') AS `column` FROM `weisci_jaws_staging2`.`users` UNION ALL SELECT 'users' AS `table`,IF(COUNT(`never_expire`),NULL,'never_expire') AS `column` FROM `weisci_jaws_staging2`.`users` UNION ALL SELECT 'users' AS `table`,IF(COUNT(`bad_passwd_count`),NULL,'bad_passwd_count') AS `column` FROM `weisci_jaws_staging2`.`users` UNION ALL SELECT 'users' AS `table`,IF(COUNT(`last_access`),NULL,'last_access') AS `column` FROM `weisci_jaws_staging2`.`users` UNION ALL SELECT 'users' AS `table`,IF(COUNT(`enabled`),NULL,'enabled') AS `column` FROM `weisci_jaws_staging2`.`users`) t WHERE `column` IS NOT NULL
1 row in set (0.00 sec)
mysql> PREPARE stmt FROM @sql;
Query OK, 0 rows affected (0.01 sec)
Statement prepared
mysql> EXECUTE stmt;
+-------+--------+
| table | column |
+-------+--------+
| users | theme |
+-------+--------+
1 row in set (0.00 sec)
mysql> DEALLOCATE PREPARE stmt;
Query OK, 0 rows affected (0.00 sec)
mysql>
Điều này cung cấp cho cột NULL. Câu hỏi ban đầu được yêu cầu cho các cột không phải NULL. Tôi sẽ thay đổi mã thành không phải NULL. Tôi sẽ làm điều đó bằng cách lật thứ tự của IF..COUNT
:
SET group_concat_max_len = 4294967295; -- to overcome default 1KB limitation
SELECT CONCAT(
'SELECT * FROM ('
, GROUP_CONCAT(
CONCAT(
'SELECT ', QUOTE(TABLE_NAME), ' AS `table`,'
, 'IF('
, 'COUNT(`', REPLACE(COLUMN_NAME, '`', '``'), '`),'
, QUOTE(COLUMN_NAME)
, ',NULL'
, ') AS `column` '
, 'FROM `',
REPLACE(TABLE_SCHEMA, '`', '``'), '`.`',
REPLACE(TABLE_NAME, '`', '``'), '`'
)
SEPARATOR ' UNION ALL '
)
, ') t WHERE `column` IS NOT NULL'
)
INTO @sql
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'weisci_jaws_staging2'
AND TABLE_NAME = 'users';
SELECT @sql\G
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Hãy chạy ngay bây giờ ...
mysql> SET group_concat_max_len = 4294967295; -- to overcome default 1KB limitation
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT CONCAT(
-> 'SELECT * FROM ('
-> , GROUP_CONCAT(
-> CONCAT(
-> 'SELECT ', QUOTE(TABLE_NAME), ' AS `table`,'
-> , 'IF('
-> , 'COUNT(`', REPLACE(COLUMN_NAME, '`', '``'), '`),'
-> , QUOTE(COLUMN_NAME)
-> , ',NULL'
-> , ') AS `column` '
-> , 'FROM `',
-> REPLACE(TABLE_SCHEMA, '`', '``'), '`.`',
-> REPLACE(TABLE_NAME, '`', '``'), '`'
-> )
-> SEPARATOR ' UNION ALL '
-> )
-> , ') t WHERE `column` IS NOT NULL'
-> )
-> INTO @sql
-> FROM INFORMATION_SCHEMA.COLUMNS
-> WHERE TABLE_SCHEMA = 'weisci_jaws_staging2'
-> AND TABLE_NAME = 'users';
Query OK, 1 row affected (0.01 sec)
mysql> SELECT @sql\G
*************************** 1. row ***************************
@sql: SELECT * FROM (SELECT 'users' AS `table`,IF(COUNT(`id`),'id',NULL) AS `column` FROM `weisci_jaws_staging2`.`users` UNION ALL SELECT 'users' AS `table`,IF(COUNT(`username`),'username',NULL) AS `column` FROM `weisci_jaws_staging2`.`users` UNION ALL SELECT 'users' AS `table`,IF(COUNT(`passwd`),'passwd',NULL) AS `column` FROM `weisci_jaws_staging2`.`users` UNION ALL SELECT 'users' AS `table`,IF(COUNT(`user_type`),'user_type',NULL) AS `column` FROM `weisci_jaws_staging2`.`users` UNION ALL SELECT 'users' AS `table`,IF(COUNT(`recovery_key`),'recovery_key',NULL) AS `column` FROM `weisci_jaws_staging2`.`users` UNION ALL SELECT 'users' AS `table`,IF(COUNT(`name`),'name',NULL) AS `column` FROM `weisci_jaws_staging2`.`users` UNION ALL SELECT 'users' AS `table`,IF(COUNT(`email`),'email',NULL) AS `column` FROM `weisci_jaws_staging2`.`users` UNION ALL SELECT 'users' AS `table`,IF(COUNT(`url`),'url',NULL) AS `column` FROM `weisci_jaws_staging2`.`users` UNION ALL SELECT 'users' AS `table`,IF(COUNT(`timezone`),'timezone',NULL) AS `column` FROM `weisci_jaws_staging2`.`users` UNION ALL SELECT 'users' AS `table`,IF(COUNT(`language`),'language',NULL) AS `column` FROM `weisci_jaws_staging2`.`users` UNION ALL SELECT 'users' AS `table`,IF(COUNT(`theme`),'theme',NULL) AS `column` FROM `weisci_jaws_staging2`.`users` UNION ALL SELECT 'users' AS `table`,IF(COUNT(`editor`),'editor',NULL) AS `column` FROM `weisci_jaws_staging2`.`users` UNION ALL SELECT 'users' AS `table`,IF(COUNT(`last_login`),'last_login',NULL) AS `column` FROM `weisci_jaws_staging2`.`users` UNION ALL SELECT 'users' AS `table`,IF(COUNT(`createtime`),'createtime',NULL) AS `column` FROM `weisci_jaws_staging2`.`users` UNION ALL SELECT 'users' AS `table`,IF(COUNT(`updatetime`),'updatetime',NULL) AS `column` FROM `weisci_jaws_staging2`.`users` UNION ALL SELECT 'users' AS `table`,IF(COUNT(`change_passwd`),'change_passwd',NULL) AS `column` FROM `weisci_jaws_staging2`.`users` UNION ALL SELECT 'users' AS `table`,IF(COUNT(`never_expire`),'never_expire',NULL) AS `column` FROM `weisci_jaws_staging2`.`users` UNION ALL SELECT 'users' AS `table`,IF(COUNT(`bad_passwd_count`),'bad_passwd_count',NULL) AS `column` FROM `weisci_jaws_staging2`.`users` UNION ALL SELECT 'users' AS `table`,IF(COUNT(`last_access`),'last_access',NULL) AS `column` FROM `weisci_jaws_staging2`.`users` UNION ALL SELECT 'users' AS `table`,IF(COUNT(`enabled`),'enabled',NULL) AS `column` FROM `weisci_jaws_staging2`.`users`) t WHERE `column` IS NOT NULL
1 row in set (0.00 sec)
mysql> PREPARE stmt FROM @sql;
Query OK, 0 rows affected (0.00 sec)
Statement prepared
mysql> EXECUTE stmt;
+-------+------------------+
| table | column |
+-------+------------------+
| users | id |
| users | username |
| users | passwd |
| users | user_type |
| users | recovery_key |
| users | name |
| users | email |
| users | url |
| users | timezone |
| users | language |
| users | editor |
| users | last_login |
| users | createtime |
| users | updatetime |
| users | change_passwd |
| users | never_expire |
| users | bad_passwd_count |
| users | last_access |
| users | enabled |
+-------+------------------+
19 rows in set (0.01 sec)
mysql> DEALLOCATE PREPARE stmt;
Query OK, 0 rows affected (0.00 sec)
mysql>
OK nó hoạt động ngay bây giờ. Có một vấn đề vẫn còn hiện diện. Truy vấn yêu cầu đọc toàn bộ bảng. Bảng thử nghiệm của tôi chỉ có 117 hàng và 20 cột. Còn những bảng lớn hơn với hàng triệu hàng hoặc hàng chục cột thì sao? Tôi sẽ không suy đoán bởi vì tôi biết rằng mã sẽ là thứ tự cường độ tồi tệ hơn.
Đó là lý do tại sao tôi khuyên bạn nên trả lời
select GROUP_CONCAT(column_name) nonnull_columns
from information_schema.columns
where table_schema = 'weisci_jaws_staging2'
and table_name = 'users'
and is_nullable = 'NO';
hoặc là
select column_name nonnull_column
from information_schema.columns
where table_schema = 'weisci_jaws_staging2'
and table_name = 'users'
and is_nullable = 'NO';
bởi vì nội dung dữ liệu thực tế không phải kiểm tra.
Mã tăng mà tôi đã tạo chỉ nên được sử dụng trên một bảng trong đó tất cả các cột cho phép NULL
các giá trị, cực kỳ hiếm.