Oracle

遍歷欄位列表,檢查查找表

  • March 29, 2017

我有一個欄位列表:

FIELD_DOMAIN_ENG_VW

+-------------+------------+-------------+
| TABLE_NAME  | FIELD_NAME | DOMAIN_NAME |
+-------------+------------+-------------+
| ENG.TABLE_1 | FIELD_1    | DOMAIN_ABC  |
| ENG.TABLE_1 | FIELD_2    | DOMAIN_XYZ  |
| ENG.TABLE_2 | FIELD_1    | DOMAIN_XYZ  |
+-------------+------------+-------------+

該視圖查看地理數據庫中的所有表,並列出具有與其關聯的域的所有欄位(域是 GIS 的查找表/驗證表等價物)。

基礎表如下所示:

表格1

+--------------+--------------+
| FIELD_1      | FIELD_2      |
| {DOMAIN_ABC} | {DOMAIN_XYZ} |
+--------------+--------------+
| A            | X            |
| B            | Y            |
| C            | zzzz         |
| BLACK SHEEP  |              |
+--------------+--------------+

表_2

+--------------+--------------+
| FIELD_1      | FIELD_2      |
| {DOMAIN_XYZ} |              |
+--------------+--------------+
| Z            | ...          |
| Y            |              |
| X            |              |
| asdf         |              |
+--------------+--------------+

域如下所示:

DOMAIN_VALUES_VW

+------------+------+-------------+
| DOMAIN     | CODE | DESCRIPTION |
+------------+------+-------------+
| DOMAIN_ABC | A    | EH          |
| DOMAIN_ABC | B    | BEE         |
| DOMAIN_ABC | C    | SEE         |
+------------+------+-------------+
| DOMAIN_XYZ | X    | EX          |
| DOMAIN_XYZ | Y    | WHY         |
| DOMAIN_XYZ | Z    | ZEE         |
+------------+------+-------------+

源是單個系統表中的xml 列;我已將所有域提取到此視圖中。

出於驗證目的,我進行了一個查詢,該查詢將檢查欄位中是否存在與相應域不匹配的值:

INSERT INTO ENG.CV_ERRORS
(TABLE_NAME, FIELD_NAME, ERROR)
SELECT
   'TABLE_1' AS TABLE_NAME
   ,'FIELD_1' AS FIELD_NAME
   ,FIELD_1 AS ERROR
FROM 
   ENG.TABLE_1 
   LEFT JOIN 
       (
       SELECT CODE
       FROM  INFRASTR.D_CV_ENG_VW
       WHERE DOMAIN = 'DOMAIN_ABC'
       )
       ON FIELD_1 = CODE
WHERE 
   FIELD_1 IS NOT NULL
   AND CODE IS NULL
+------------+------------+-------------+
| TABLE_NAME | FIELD_NAME | ERROR       |
+------------+------------+-------------+
| TABLE_1    | FIELD_1    | BLACK SHEEP |
+------------+------------+-------------+

但是,此查詢被硬編碼為一次在單個表中的單個欄位上執行。我需要以程式方式檢查數據庫中所有表中的所有域欄位。

我怎樣才能做到這一點?我很確定這可以用 PL/SQL 和動態 SQL 來完成,但是我對 PL/SQL 太陌生了,以至於它被證明是相當困難的。

本機動態 SQL(在 PL/SQL 匿名塊中):

01    DECLARE
02        l_table_name VARCHAR2(100);
03        l_field_name VARCHAR2(100);
04        l_domain_name VARCHAR2(100);
05    BEGIN
06        DELETE FROM ENG.CV_ERRORS;
07        FOR list_fields IN (
08            SELECT 
09                TABLE_NAME
10                ,FIELD_NAME
11                ,DOMAIN_NAME 
12            FROM 
13                ENG.FIELD_DOMAIN_ENG_VW 
14            WHERE 
15                TABLE_NAME NOT LIKE '%ANNO%' 
16            )
17        LOOP
18            l_table_name := list_fields.TABLE_NAME;
19            l_field_name := list_fields.FIELD_NAME;
20            l_domain_name := list_fields.DOMAIN_NAME;
21    
22            EXECUTE IMMEDIATE
23            'INSERT INTO ENG.CV_ERRORS
24            (TABLE_NAME, FIELD_NAME, ERROR)
25            SELECT
26                :bv1 AS TABLE_NAME
27                ,:bv2 AS FIELD_NAME
28                , ' || l_field_name || ' AS ERROR
29            FROM ' || 
30                l_table_name ||
31                ' LEFT JOIN
32                (
33                SELECT CODE
34                FROM  ENG.D_CV_ENG_VW
35                WHERE DOMAIN = :bv3
36                )
37                ON ' || l_field_name || ' = CODE
40            WHERE
41                ' || l_field_name || ' IS NOT NULL
42                AND 
43                CODE IS NULL'
44    
45            USING l_table_name, l_field_name, l_domain_name;
46    
47        END LOOP;
48    COMMIT;
49    END;

結果集

+------------+------------+-------------+
| TABLE_NAME | FIELD_NAME |    ERROR    |
+------------+------------+-------------+
| TABLE_1    | FIELD_1    | BLACK SHEEP |
| TABLE_1    | FIELD_2    | zzzz        |
| TABLE_2    | FIELD_1    | asdf        |
+------------+------------+-------------+

腳步

  1. 刪除所有現有行ENG.CV_ERRORS(奇怪的是,我正在使用的 ODBC 連接沒有截斷表的權限)。
  2. 循環遍歷FIELD_DOMAIN_ENG_VW.
  3. 對於每個欄位,生成一個動態查詢以查找與相應域不匹配的值。然後將它們插入ENG.CV_ERRORS.

現在一切都說了又做了,這並不那麼複雜。最難的部分是圍繞綁定變數與字元串連接變數(正確的術語?)以及何時使用它們(儘管我還不完全理解這一點)。

相關問題

綁定變數與字元串連接變數

初學者 PL/SQL:從動態 SQL 函式(函式,而不是循環)返回行值

對於欄位列表中的每個欄位名稱,獲取唯一值(聯合)

引用自:https://dba.stackexchange.com/questions/159851