postgres- plsql 函数获取具有空数据的特定列的行数

问题描述 投票:0回答:2

我需要获取具有空值的特定列的行计数,并将相同的行计数输出插入到具有查询结果集的表中。对于这个要求,我尝试在 postgres 中使用下面的 pl/sql 代码块,但它不起作用,因为我收到以下错误。有人可以建议我在这里做错了什么吗?

SQL Error [42601]: ERROR: syntax error at or near "null"
  Where: PL/pgSQL function inline_code_block line 14 at EXECUTE
DO $$
DECLARE
  tab RECORD;
  l_schema VARCHAR := 'test';
  l_sql text;
  l1_sql text;
  RSE_ROW_COUNT int;
BEGIN
  for tab in (select table_name,column_name from  INFORMATION_SCHEMA.columns where table_schema='public' and  is_nullable='NO' and data_type  not in  ('integer')
and column_default is null order by table_name,column_name)
  LOOP
    l_sql := format('SELECT COUNT(1) FROM ' || tab.table_name || 'where ' ||  tab.column_name || 'is null'); 
    RAISE NOTICE '%', l_sql;
    EXECUTE l_sql INTO RSE_ROW_COUNT;
    l1_sql := 'INSERT INTO RSE_TABLE_COUNT (TABLE_NAME, Table_column_name,ROW_COUNT, DATE_LAST_UPDATED) 
           VALUES  ( '|| tab.table_name ||','|| tab.column_name ||','|| rse_row_count ||','|| 'SYSDATE)'; 
    RAISE NOTICE '%', l1_sql;
    EXECUTE l1_sql;
  end loop;
end
$$;

尝试了多种选项但无法修复。

sql postgresql plpgsql plsqldeveloper
2个回答
0
投票

@Paul T. 正确显示了第一个问题 - 列名称和

IS
关键字之间缺少空格。

这种使用动态 SQL 值的方式可能很危险(容易受到 SQL 注入攻击)。您应该使用带有正确占位符的函数

format
或函数
quote_ident
。您使用函数
format
,但不正确:

l_sql := format('SELECT COUNT(1) FROM %I where %I is null', tab.table_name, tab.column_name); 

我看到另一个问题 - Postgres 无法运行

sysdate
。请使用
current_date
来代替。


0
投票

还有很多需要改进的地方,尤其是format()的使用。在当前的方法中,当参数不是标准 PostgreSQL 格式或者甚至容易发生 SQL 注入时,查询仍然会失败。您没有使用占位符和正确的类型。

DO
$$
    DECLARE
        tab           RECORD;
        l_schema      VARCHAR := 'test';
        l_sql         TEXT;
        l1_sql        TEXT;
        rse_row_count INT;
    BEGIN
        FOR tab IN (SELECT table_name, column_name
                    FROM information_schema.columns
                    WHERE table_schema = l_schema -- Correct?
                      AND is_nullable = 'NO'
                      AND data_type NOT IN ('integer')
                      AND column_default IS NULL
                    ORDER BY table_name, column_name)
            LOOP
                -- use placeholders for Identifiers:
                l_sql := FORMAT('SELECT COUNT(1) FROM %I.%I WHERE %I IS NULL;'
                            , l_schema -- Correct?
                            , tab.table_name
                            , tab.column_name
                         );
                RAISE NOTICE '%', l_sql;
                EXECUTE l_sql INTO rse_row_count;
                l1_sql := FORMAT('INSERT INTO RSE_TABLE_COUNT (TABLE_NAME, Table_column_name,ROW_COUNT, DATE_LAST_UPDATED)
                        VALUES  (%L,%L,%L, %L);'
                            , tab.table_name
                            , tab.column_name
                            , rse_row_count
                            , NOW()
                          );
                RAISE NOTICE '%', l1_sql;
                EXECUTE l1_sql;
            END LOOP;
    END;
$$;
© www.soinside.com 2019 - 2024. All rights reserved.