使用动态SQL获取具有非空字段的自定义表结构

目录

介绍

背景

使用代码

兴趣点


我如何才能从查询中获取非空字段?是的,您可以使用现代的编程语言轻松完成此操作,但是通过从表中获取冗余信息可能会浪费资源,而且很多时候,它可能会添加冗余代码。从5.3版开始,此任务仅面向MySQL

介绍

您拥有大量的信息,其中包含大量的电子表格,csvxmlbin,日志或纯文本文件,并且经过简化后,表中有几列没有值,当然也没有NULL 值。对于桌面用户,这可能只是一个烦恼。另一方面,对于云用户,您可能没有便宜的资源,而成本仅需支付少量账单。对于DBA,那些NULL占很大空间,它们没有数据。但是事实是,ETL作业仅带来数据,而在此无罪。出于教学目的,本文使用非常流行的MySQL数据库引擎解决了这种情况。

背景

我借助一个基于流视频商店服务公司的名为cinemashop的数据库,给出了这种情况的示例。它在MySQL上运行,但对于MariaDBPercona分支也将起作用。这些方面的工作可以从这里进一步推进。

使用代码

cinemashop数据库内部,有一个包含几列的customer表,因为行大小可以放在那里(到目前为止,超过1000列)。

MySQL ETL作业将信息放在此处,仅需要从无null值的列中获取数据。下图显示了前几个寄存器的一小部分:

因此,值得检查该字段中的所有寄存器是否至少仅具有一个数据。仅此一项数据就可以改变数据湖/数据仓库/报告服务输入的模型,可能占总人口的1%。由于这种情况,下面叫check_field_null的存储过程产生此行为。该存储过程使用PREPAREEXECUTE以及DEALLOCATE语句来管理SQL动态。它将COUNT标量函数的结果存储在QN变量中。因此,有可能获得多少个寄存器是NULL值的值。

/*======================================================
    Classroom:    SQL Level 3
    Database:    cinemashop
  ======================================================*/
use cinemashop;
drop procedure if exists check_field_null;

set delimiter //

create procedure check_field_null(col varchar(64), schemaname varchar(255), _
                                  tablename varchar(255), out QN int)
BEGIN
    SET @sSQL = concat('SELECT  @N := COUNT(*) FROM ', schemaname, '.', _
                        tablename , ' WHERE (', col, ' <=> NULL);');
    prepare stm from @sSQL;
    execute stm;
    set QN =@N;
    deallocate prepare stm;
    
END
//

set delimiter ;

下面的代码说明了上述功能的作用。关于customer_id字段,它表明存在值。

set @p = 0; 
call check_field_null('customer_id', 'cinemashop', 'customer', @p); 

/* This field customer_id has NOT null values */ 

select @p;

另一方面,如果像这样的字段gender仅具有NULL值,则计数器将检查预期结果:

set @p = 0;
call check_field_null('gender', 'cinemashop', 'customer', @p);

/* This field gender has null values */

select @p;

最后,工作包括获取表中各列的字段名称。今天,它可能是一个数据结构,但是明天,它可能会按需更改,并且当然可以在那里显示NULL值。这种方式在称为cur_cs_customer的存储过程中使用了CURSOR技术。它仅在information_schema允许提取时才有效,因此,那里需要一些权限。请注意,Count_Null变量的使用方式与之前的p变量相同。同样,allcols变量将MYCOL变量中每列的所有字段存储为没有任何NULL值。

/*======================================================
    Classroom:    SQL Level 3
    Database:    cinemashop
    Table name:    customer
  ======================================================*/
use cinemashop;
drop procedure if exists cur_cs_customer;

set delimiter //

create procedure cur_cs_customer(inout allcols varchar(255))
BEGIN
    DECLARE Count_Null  int default 0;
    DECLARE initial INT DEFAULT 0;
    DECLARE MYCOL   char(64);
    DECLARE ch_done INT DEFAULT 0;
    DECLARE cs_cur1 CURSOR FOR SELECT C.COLUMN_NAME
                               FROM information_schema.COLUMNS C
                               WHERE C.TABLE_SCHEMA = 'cinemashop' _
                               AND C.TABLE_NAME ='customer';
    
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET ch_done = true;
    
    open cs_cur1;
    
    read_cs_cur1:
    LOOP
        FETCH cs_cur1 INTO MYCOL;
    
        IF (ch_done ) THEN
            LEAVE read_cs_cur1;
        END IF;
    
        IF NOT isnull(MYCOL) THEN
            
            call check_field_null(MYCOL, 'cinemashop', 'customer', Count_Null);
            
            if Count_Null = 0 then
                /* Only it includes fields with not null values */
                set initial = initial + 1;
            
                if initial = 1 then
                    SET allcols =  MYCOL;
                else                
                    SET allcols  = concat( cast(allcols as char(255)), ',', MYCOL);
                end if;
            end if;
        END IF;
        
    END LOOP read_cs_cur1;
    
    close cs_cur1;
    
    select allcols;
END
//

放在一起,我们可以使用非交互式语句使用@my_args变量,例如所有没有NULL值的列中的string

set delimiter ; 
call cur_cs_customer(@my_args); 
select @my_args; 
set @stm = concat('SELECT ', @my_args, ' FROM cinemashop.customer;'); 
PREPARE stmt1 FROM @stm; 
execute stmt1; 
deallocate prepare stmt1;

进程运行时,将获得以下输出:

当然,可以使用动态SQL创建cur_cs_customer存储过程以供一般使用,但是稍后我们可能会检查此存储过程。我目前的目的只是获得第一解决方案。

兴趣点

MySQL不是我最喜欢的数据库引擎,但是由于使用Web开发中许多编程语言的简单性,许多大型网站都具有RDBMS。另外,我的工作重点是平台集成,其中cookbook有一些ETL、数据仓库、数据管道、数据湖、数据中心的任务,当然,还有用于数据挖掘和数据科学任务的数据库。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章