I want to compare the contents of table with regex pattern and column_name which is saved as variable in a procedure. Regexp_like with variables v_column_name, v_column_regexp are then in the if statement.
CREATE OR REPLACE PROCEDURE TBL_COLUMN_REGEX (
p_data IN VARCHAR2,
p_table_name IN VARCHAR2)
AS
v_data VARCHAR2 (50);
v_table_name VARCHAR2 (200);
v_column_name VARCHAR2 (100);
v_column_regexp VARCHAR2 (100);
v_row_rownum NUMBER;
BEGIN
v_data := p_data;
v_table_name := p_table_name;
FOR i
IN (SELECT column_name, t1.column_type, column_regexp
FROM T_TBL_COLUMN t1
INNER JOIN t_column_regexp t2
ON t1.column_type = t2.column_type
WHERE data = v_data AND table_name = v_table_name)
LOOP
v_column_name := i.column_name;
v_column_regexp := i.column_regexp;
INSERT INTO T_LOG_TBL_COLUMN (DATA, TABLE_NAME, LOG_TEXT)
VALUES ( v_data, v_table_name, v_column_name || ' REGEXP Check starts with ' || v_column_regexp);
FOR r_row IN (SELECT v_column_name, ROWNUM FROM T_TEST)
LOOP
v_row_rownum := r_row.ROWNUM;
IF NOT REGEXP_LIKE (v_column_name, v_column_regexp)--v_column_name:='DATE' with content as '202311', v_column_regexp:='^\d{4}(0[1-9]|1[012])$'
THEN
INSERT INTO T_LOG_TBL_COLUMN (DATA,
TABLE_NAME,
LOG_TEXT)
VALUES ( v_data, v_table_name, 'In '|| v_row_rownum || ': ' || v_column_name);
COMMIT;
END IF;
COMMIT;
END LOOP;
END LOOP;
END;
/
It doesn't match in the if statement, even though I get a match if I use regexp_like in a select statement.
SELECT DISTINCT rownum, DATE
FROM T_TEST
WHERE REGEXP_LIKE (DATE, '^\d{4}(0[1-9]|1[012])$')
1 202311
2 202311
3 202311
4 202311
Your query SELECT v_column_name, ROWNUM FROM T_TEST_4
will get the literal value of the variable (i.e. the column name) for every row in your table, not the column value.
You can see that in this simplified demo:
declare
v_column_name all_tab_columns.column_name%type := 'DUMMY';
begin
for r_row in (select v_column_name as col from dual)
loop
dbms_output.put_line(r_row.col);
end loop;
end;
/
dbms_output:
DUMMY
It's showing the column name, DUMMY, not the value, X.
If you use a dynamic SQL cursor loop then you get the value instead:
declare
v_column_name all_tab_columns.column_name%type := 'DUMMY';
v_cursor sys_refcursor;
v_value varchar2(4000);
begin
open v_cursor for 'select "' || v_column_name || '" from dual';
loop
fetch v_cursor into v_value;
exit when v_cursor%notfound;
dbms_output.put_line(v_value);
end loop;
end;
/
dbms_output:
X
You can adapt your code to do the same thing; add variable declarations for the cursor and results:
v_cursor sys_refcursor;
v_column_value varchar2(4000);
v_rownum number;
and change your loop from:
FOR r_row IN (SELECT v_column_name, ROWNUM FROM T_TEST_4)
LOOP
v_row_rownum := r_row.ROWNUM;
IF NOT REGEXP_LIKE (v_column_name, v_column_regexp)
...
to
OPEN v_cursor FOR 'SELECT "' || v_column_name || '", ROWNUM FROM T_TEST_4';
LOOP
FETCH v_cursor INTO v_column_value, v_row_rownum;
EXIT WHEN v_cursor%NOTFOUND;
IF NOT REGEXP_LIKE (v_column_value, v_column_regexp)
...
and presumably change v_column_name
to v_column_value
when you insert into your log table too. (You probably don't want to be committing after every insert...)