使用動態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、數據倉庫、數據管道、數據湖、數據中心的任務,當然,還有用於數據挖掘和數據科學任務的數據庫。

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