这里有几件事你需要注意。首先,正如您所提到的,您的 COUNT 查询正在使用 i.column_name 的值执行,该值永远不会为 NULL。
其次,COUNT(*)
返回与您的子句条件匹配的行数,而不考虑值。如果要计算特定列中有多少值,则必须显式地计算该列中的值。WHERE
NULL
NOT NULL
COUNT
请参阅以下示例(SQL Fiddle):
Oracle 11g R2 模式设置:
CREATE TABLE null_col_vals (
col_without_nulls INTEGER NOT NULL
, col_with_nulls INTEGER
, col_with_mix INTEGER
)
/
INSERT INTO null_col_vals (col_without_nulls, col_with_nulls, col_with_mix)
VALUES (1, NULL, NULL)
/
INSERT INTO null_col_vals (col_without_nulls, col_with_nulls, col_with_mix)
VALUES (1, NULL, 1)
/
INSERT INTO null_col_vals (col_without_nulls, col_with_nulls, col_with_mix)
VALUES (1, NULL, NULL)
/
查询 1:
SELECT
COUNT(col_without_nulls) col_without_nulls
, COUNT(col_with_nulls) col_with_nulls
, COUNT(col_with_mix) col_with_mix
, COUNT(*) all_rows
FROM null_col_vals
结果:
| COL_WITHOUT_NULLS | COL_WITH_NULLS | COL_WITH_MIX | ALL_ROWS |
----------------------------------------------------------------
| 3 | 0 | 1 | 3 |
如您所见,COUNT(*)
总是返回存在的行数,但其他的结果会有所不同,具体取决于NULL
指定列中是否存在值。
您需要使用EXECUTE IMMEDIATE
将列名转换为查询的一部分。这样的事情可能会完成这项工作:
查询 2:
DECLARE
l_count INTEGER;
BEGIN
FOR r_col IN (
SELECT *
FROM all_tab_columns atc
WHERE atc.table_name = 'NULL_COL_VALS'
)
LOOP
dbms_output.put_line(r_col.column_name);
EXECUTE IMMEDIATE 'SELECT COUNT(' || r_col.column_name || ') FROM null_col_vals'
INTO l_count;
dbms_output.put_line(l_count);
END LOOP;
END;