我正在尝试在SQL Developer中执行以下PL / SQL脚本。循环应该返回空值的计数,但不知何故每次返回0。 在
上设置serveroutputDECLARE
--v_count number;
v_count_null number;
BEGIN
execute immediate 'select count(*) from SP_MOSAIX' into v_count;
FOR i in (select column_name from all_tab_COLUMNS where table_name = 'SP_MOSAIX')
LOOP
select count(*) into v_count_null from SP_MOSAIX where i.column_name IS NULL ;
dbms_output.put_line(v_count_null);
END LOOP;
END;
所以当我运行这个时,输出就是我得到的:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
但是如果我手动执行查询替换column_name,我会得到结果。
select count(*) into v_count_null from SP_MOSAIX where i.column_name IS NULL;
有人可以提供帮助吗?
答案 0 :(得分:2)
这里有一些你需要注意的事情。首先,正如您所提到的,您的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;
答案 1 :(得分:1)
您需要使用动态SQL,这将允许您引用每一列:
FOR i in (select column_name from all_tab_COLUMNS where table_name = 'SP_MOSAIX')
LOOP
execute immediate 'select count(*) from SP_MOSAIX where '||i.column_name||' IS NULL'
into v_count_null ;
dbms_output.put_line(i.column_name||' = '||v_count_null);
END LOOP;