在两个不同的表中查找两列之间的匹配字符串

时间:2017-03-16 16:50:33

标签: string oracle plsql plsqldeveloper

select * from all_tables 取出数据库中的所有表格

   Table A
    Name     Shortform
    Generate GNRT
    Support  SPRT  
    and so onn..

大约有100个表名和50个英文名以及缩写 每个表名都使用缩写形式创建,例如SELECT * FROM GNRT_SPRT
如果新人尝试创建表并且不遵循缩写,那么应该在名为results的新表中提取这些表名。

FOR example:      
select * from gnrte_sche

上面的示例与短格式不匹配,因此应将表名插入名为results的新表中。我需要使用select * from all_tables

检查所有表
-output-
Table Results
Diff_tables--column name
gnrte_sche

1 个答案:

答案 0 :(得分:0)

已编辑以包含保存不匹配 这没有调整,可能还有其他更简单的解决方案,但以下可能会做你想要的。

此块将打印出任何不仅仅由SHORTFORM个单词和下划线组成的表名,并找到第一个(唯一的)非短形式。它还会将所有匹配保存到名为NON_SHORTFORM的示例表中。它允许使用前缀和后缀下划线,并允许使用“$”字符,所以它在SHORTFORM中就可以了。

这将从SHORTFORM读取TABLE A,并评估ALL_TABLES中的所有内容,以检查每个是否由SHORTFORM组成。如果遇到格式错误的TABLE_NAME,则会通过DBMS_OUTPUT将其与不匹配的字词一起打印出来,并保存不匹配的记录。

首先,创建一个示例A TABLE

CREATE TABLE A(
  NAME VARCHAR2(200) NOT NULL PRIMARY KEY,
  SHORTFORM VARCHAR2(30) UNIQUE NOT NULL
);

INSERT INTO A VALUES('Generate','GNRT');
INSERT INTO A VALUES('Support','SPRT');
INSERT INTO A VALUES('Hobbit','HOBT');
INSERT INTO A VALUES('Wookie','WOKI');
INSERT INTO A VALUES('Adventure','AVNTR');

然后创建一些示例TABLE来检查

CREATE TABLE GNRT_SPRT(X NUMBER);
CREATE TABLE WOKI_SPRT(X NUMBER);
CREATE TABLE HOBT_WOKI_AVNTR(X NUMBER);
CREATE TABLE ROBOTS(X NUMBER);
CREATE TABLE GNRTE_SCHE(X NUMBER);

然后创建一个TABLE以保存不匹配(请注意,这只允许每个表保存一个不匹配。如果您的用例不同,可以根据需要进行调整):

CREATE TABLE NON_SHORTFORM(
OWNER VARCHAR2(128) NOT NULL,
TABLE_NAME VARCHAR2(128) NOT NULL,
MISMATCHED_WORD VARCHAR2(128) NOT NULL,
CONSTRAINT NON_SHORTFORM_PK PRIMARY KEY (OWNER, TABLE_NAME));

然后创建一个BLOCK进行评估(如果愿意,可以是FUNCTION等等)。请注意,这允许“$”和数字。如果你想排除这些,下面也可以改编:

DECLARE
  TYPE V_STRING_LIST IS TABLE OF VARCHAR2(128);
  V_SHORT_FORM_SET V_STRING_LIST;
  V_SHORT_FORM_MATCHED NUMBER(1,0) := 0;
  V_TABLE_NAME VARCHAR2(128);
  V_TABLE_NAME_WORK_SPACE VARCHAR2(128);
  V_TABLE_TOKEN VARCHAR2(128);
BEGIN
  SELECT SHORTFORM BULK COLLECT INTO V_SHORT_FORM_SET FROM A;
  DBMS_OUTPUT.PUT_LINE('MALFORMED TABLE-NAMES:');
<<TABLE_NAME_LOOP>>
FOR TABLE_POINTER IN (  SELECT ALL_TABLES.OWNER, ALL_TABLES.TABLE_NAME FROM ALL_TABLES   WHERE ALL_TABLES.TABLE_NAME <> 'A')
  LOOP
    V_TABLE_NAME_WORK_SPACE := REGEXP_REPLACE(TABLE_POINTER.TABLE_NAME,'((^[_]{1,})|([_]{1,}$))',NULL);
  <<SHORT_FORM_LOOP>>
    LOOP
      V_TABLE_NAME_WORK_SPACE := REGEXP_REPLACE(V_TABLE_NAME_WORK_SPACE,'((^[_]{1,})|([_]{1,}$))',NULL);
      EXIT WHEN NOT (REGEXP_LIKE(COALESCE(V_TABLE_NAME_WORK_SPACE,'!'),'^[_A-Z0-9$]{1,}$'));
      V_TABLE_TOKEN := REGEXP_SUBSTR(V_TABLE_NAME_WORK_SPACE,'^[A-Z0-9$]{1,}');
      V_TABLE_NAME_WORK_SPACE := REGEXP_REPLACE(V_TABLE_NAME_WORK_SPACE,'^[A-Z0-9$]{1,}',NULL);
      SELECT COUNT(*) INTO V_SHORT_FORM_MATCHED FROM A
      WHERE A.SHORTFORM = V_TABLE_TOKEN;

      IF NOT V_SHORT_FORM_MATCHED = 1
      THEN DBMS_OUTPUT.PUT_LINE(UTL_LMS.FORMAT_MESSAGE('Table-Name:%s,Mismatched-Shortform:%s',TABLE_POINTER.TABLE_NAME,V_TABLE_TOKEN));
MERGE INTO NON_SHORTFORM USING (
    SELECT TABLE_POINTER.OWNER AS OWNER,
    TABLE_POINTER.TABLE_NAME AS TABLE_NAME,
    V_TABLE_TOKEN AS MISMATCHED_WORD
    FROM DUAL) CANDIDATE_MISMATCH
  ON (NON_SHORTFORM.OWNER = CANDIDATE_MISMATCH.OWNER
  AND NON_SHORTFORM.TABLE_NAME = CANDIDATE_MISMATCH.TABLE_NAME)
  WHEN MATCHED THEN UPDATE SET NON_SHORTFORM.MISMATCHED_WORD = CANDIDATE_MISMATCH.MISMATCHED_WORD
  WHEN NOT MATCHED THEN INSERT (OWNER, TABLE_NAME, MISMATCHED_WORD)
  VALUES (CANDIDATE_MISMATCH.OWNER, CANDIDATE_MISMATCH.TABLE_NAME, CANDIDATE_MISMATCH.MISMATCHED_WORD);
        EXIT;
      END IF;
    END LOOP SHORT_FORM_LOOP;
  END LOOP TABLE_NAME_LOOP;
END;
/

然后运行它(我希望它忽略GNRT_SPRTWOKI_SPRT等等,因为它们有SHORTFORMs,但要列出ROBOTSGNRTE_SCHE

SET SERVEROUTPUT ON;
-- CODE BLOCK FROM GOES HERE
MALFORMED TABLE-NAMES:
... other TABLEs omitted ...
Table-Name:ROBOTS,Mismatched-Shortform:ROBOTS
Table-Name:GNRTE_SCHE,Mismatched-Shortform:GNRTE

检查保存的不匹配(注意在此示例中,发现第一个不匹配。如果要保存每个不匹配,则需要相应地更新上述块):

SELECT * FROM NON_SHORTFORM;
OWNER  TABLE_NAME  MISMATCHED_WORD
-- Other records omitted
LIMS   ROBOTS      ROBOTS
LIMS   GNRTE_SCHE  GNRTE