在 Oracle 中评估字符串作为条件
Evaluate a string as condition in Oracle
例如,如果我有一个像
这样的字符串
my_string := ' ''a'' = ''a'' and 1 > 0 '
我可以在 procedure/function
中做这样的事情来评估它
execute immediate 'select CASE WHEN(' || my_string || ') THEN 1 ELSE 0 END from dual'
但是有没有不用立即执行的方法呢?有没有办法像在查询中写入的那样评估字符串?
我想要这样做是因为我在 table 中有通用条件,例如“COD1 像 '%x%' OR COD2 = 'Z'”。所以我用这个字符串做了一些替换,但是我想让它们用约束条件来评估,以不使用用户定义的函数,所以没有“立即执行”
不可能,据我所知。这就是动态 SQL(即 execute immediate
)的用途。
例如,如果您只将一个条件(为简单起见)放入 table:
SQL> select * from test;
MY_STRING
---------------------
'a' = 'a' and 1 > 0
并将它交叉连接到另一个 table (因为,我希望 所有东西 都返回,因为总是满足该条件),你会得到一个错误:
SQL> select *
2 from dept d cross join test t
3 where t.mystring;
where t.mystring
*
ERROR at line 3:
ORA-00920: invalid relational operator
while - 如果按字面意思将条件放入 where
子句,它 有效 :
SQL> select *
2 from dept d cross join test t
3 where 'a' = 'a' and 1 > 0;
DEPTNO DNAME LOC MY_STRING
---------- -------------- ------------- ---------------------
10 ACCOUNTING NEW YORK 'a' = 'a' and 1 > 0
20 RESEARCH DALLAS 'a' = 'a' and 1 > 0
30 SALES CHICAGO 'a' = 'a' and 1 > 0
40 OPERATIONS BOSTON 'a' = 'a' and 1 > 0
SQL>
所以,恐怕是动态的 SQL。
is there a way to do that without using execute immediate
您可以使用替换变量作为替代方法,例如
SQL> SELECT CASE WHEN(&str) THEN 1 ELSE 0 END
2 FROM dual;
CASEWHEN('A'='A'AND1>0)THEN1EL
------------------------------
1
其中 'a' = 'a' and 1 > 0
在出现提示时输入 &str
是的,但是……实际上您必须编写自己的表达式解析器:
如果你有表格:
CREATE TABLE table_name (a, b, c, d) AS
SELECT 'x', 'x', 'x', 'x' FROM DUAL UNION ALL
SELECT 'w', 'x', 'y', 'z' FROM DUAL;
CREATE TABLE filters (filter) AS
SELECT 'a = b AND c <= d' FROM DUAL UNION ALL
SELECT 'a < b AND b < c AND c < d' FROM DUAL UNION ALL
SELECT 'a < ''y''' FROM DUAL UNION ALL
SELECT 'c LIKE ''%y%''' FROM DUAL;
并且您想将 filters
应用到 table_name
然后,从 Oracle 12,您可以使用:
WITH split_filters ( id, filter, left_operand, operator, right_operand, expr, num_expr ) AS (
SELECT ROWID,
filter,
REGEXP_SUBSTR(
filter,
'(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- left_operand
|| '\s*([<>!]?=|[<>]|LIKE)' -- operator
|| '\s*(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- right_operand
|| '\s*($|\sAND\s+)', -- expression concatenator
1,
1,
'i',
1
),
REGEXP_SUBSTR(
filter,
'(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- left_operand
|| '\s*([<>!]?=|[<>]|LIKE)' -- operator
|| '\s*(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- right_operand
|| '\s*($|\sAND\s+)', -- expression concatenator
1,
1,
'i',
3
),
REGEXP_SUBSTR(
filter,
'(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- left_operand
|| '\s*([<>!]?=|[<>]|LIKE)' -- operator
|| '\s*(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- right_operand
|| '\s*($|\sAND\s+)', -- expression concatenator
1,
1,
'i',
4
),
1,
REGEXP_COUNT(
filter,
'(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- left_operand
|| '\s*([<>!]?=|[<>]|LIKE)' -- operator
|| '\s*(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- right_operand
|| '\s*($|\sAND\s+)', -- expression concatenator
1,
'i'
)
FROM filters
UNION ALL
SELECT id,
filter,
REGEXP_SUBSTR(
filter,
'(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- left_operand
|| '\s*([<>!]?=|[<>]|LIKE)' -- operator
|| '\s*(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- right_operand
|| '\s*($|\sAND\s+)', -- expression concatenator
1,
expr + 1,
'i',
1
),
REGEXP_SUBSTR(
filter,
'(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- left_operand
|| '\s*([<>!]?=|[<>]|LIKE)' -- operator
|| '\s*(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- right_operand
|| '\s*($|\sAND\s+)', -- expression concatenator
1,
expr + 1,
'i',
3
),
REGEXP_SUBSTR(
filter,
'(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- left_operand
|| '\s*([<>!]?=|[<>]|LIKE)' -- operator
|| '\s*(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- right_operand
|| '\s*($|\sAND\s+)', -- expression concatenator
1,
expr + 1,
'i',
4
),
expr + 1,
num_expr
FROM split_filters
WHERE expr < num_expr
)
SELECT *
FROM table_name t
CROSS JOIN LATERAL (
SELECT MAX(filter) AS filter
FROM (
SELECT id,
filter,
CASE
WHEN UPPER(left_operand) = 'A' THEN t.a
WHEN UPPER(left_operand) = 'B' THEN t.b
WHEN UPPER(left_operand) = 'C' THEN t.c
WHEN UPPER(left_operand) = 'D' THEN t.d
WHEN left_operand LIKE '''%''' THEN REPLACE(SUBSTR(left_operand, 2, LENGTH(left_operand) - 2), '''''', '''')
END AS l_op,
operator AS op,
CASE
WHEN UPPER(right_operand) = 'A' THEN t.a
WHEN UPPER(right_operand) = 'B' THEN t.b
WHEN UPPER(right_operand) = 'C' THEN t.c
WHEN UPPER(right_operand) = 'D' THEN t.d
WHEN right_operand LIKE '''%''' THEN REPLACE(SUBSTR(right_operand, 2, LENGTH(right_operand) - 2), '''''', '''')
END AS r_op,
num_expr
FROM split_filters
)
WHERE CASE
WHEN op = '=' AND l_op = r_op THEN 1
WHEN op = '!=' AND l_op != r_op THEN 1
WHEN op = '<' AND l_op < r_op THEN 1
WHEN op = '>' AND l_op > r_op THEN 1
WHEN op = '<=' AND l_op <= r_op THEN 1
WHEN op = '>=' AND l_op >= r_op THEN 1
WHEN op = 'LIKE' AND l_op LIKE r_op THEN 1
END = 1
GROUP BY id
HAVING COUNT(*) = MAX(num_expr)
);
输出:
A
B
C
D
FILTER
x
x
x
x
a = b AND c <= d
x
x
x
x
a < 'y'
w
x
y
z
a < b AND b < c AND c < d
w
x
y
z
a < 'y'
w
x
y
z
c LIKE '%y%'
db<>fiddle here
在 Oracle 11g 中,您可以将其重写为:
WITH split_filters ( id, filter, left_operand, operator, right_operand, expr, num_expr ) AS (
SELECT ROWID,
filter,
REGEXP_SUBSTR(
filter,
'(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- left_operand
|| '\s*([<>!]?=|[<>]|LIKE)' -- operator
|| '\s*(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- right_operand
|| '\s*($|\sAND\s+)', -- expression concatenator
1,
1,
'i',
1
),
REGEXP_SUBSTR(
filter,
'(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- left_operand
|| '\s*([<>!]?=|[<>]|LIKE)' -- operator
|| '\s*(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- right_operand
|| '\s*($|\sAND\s+)', -- expression concatenator
1,
1,
'i',
3
),
REGEXP_SUBSTR(
filter,
'(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- left_operand
|| '\s*([<>!]?=|[<>]|LIKE)' -- operator
|| '\s*(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- right_operand
|| '\s*($|\sAND\s+)', -- expression concatenator
1,
1,
'i',
4
),
1,
REGEXP_COUNT(
filter,
'(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- left_operand
|| '\s*([<>!]?=|[<>]|LIKE)' -- operator
|| '\s*(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- right_operand
|| '\s*($|\sAND\s+)', -- expression concatenator
1,
'i'
)
FROM filters
UNION ALL
SELECT id,
filter,
REGEXP_SUBSTR(
filter,
'(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- left_operand
|| '\s*([<>!]?=|[<>]|LIKE)' -- operator
|| '\s*(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- right_operand
|| '\s*($|\sAND\s+)', -- expression concatenator
1,
expr + 1,
'i',
1
),
REGEXP_SUBSTR(
filter,
'(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- left_operand
|| '\s*([<>!]?=|[<>]|LIKE)' -- operator
|| '\s*(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- right_operand
|| '\s*($|\sAND\s+)', -- expression concatenator
1,
expr + 1,
'i',
3
),
REGEXP_SUBSTR(
filter,
'(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- left_operand
|| '\s*([<>!]?=|[<>]|LIKE)' -- operator
|| '\s*(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- right_operand
|| '\s*($|\sAND\s+)', -- expression concatenator
1,
expr + 1,
'i',
4
),
expr + 1,
num_expr
FROM split_filters
WHERE expr < num_expr
),
operand_substitutions (t_id, f_id, a, b, c, d, filter, l_op, op, r_op, num_expr) AS (
SELECT t.ROWID,
f.id,
t.a,
t.b,
t.c,
t.d,
filter,
CASE
WHEN UPPER(left_operand) = 'A' THEN t.a
WHEN UPPER(left_operand) = 'B' THEN t.b
WHEN UPPER(left_operand) = 'C' THEN t.c
WHEN UPPER(left_operand) = 'D' THEN t.d
WHEN left_operand LIKE '''%''' THEN REPLACE(SUBSTR(left_operand, 2, LENGTH(left_operand) - 2), '''''', '''')
END,
operator,
CASE
WHEN UPPER(right_operand) = 'A' THEN t.a
WHEN UPPER(right_operand) = 'B' THEN t.b
WHEN UPPER(right_operand) = 'C' THEN t.c
WHEN UPPER(right_operand) = 'D' THEN t.d
WHEN right_operand LIKE '''%''' THEN REPLACE(SUBSTR(right_operand, 2, LENGTH(right_operand) - 2), '''''', '''')
END,
num_expr
FROM split_filters f
CROSS JOIN table_name t
)
SELECT MAX(a) AS a,
MAX(b) AS b,
MAX(c) AS c,
MAX(d) AS d,
MAX(filter) AS filter
FROM operand_substitutions
WHERE CASE
WHEN op = '=' AND l_op = r_op THEN 1
WHEN op = '!=' AND l_op != r_op THEN 1
WHEN op = '<' AND l_op < r_op THEN 1
WHEN op = '>' AND l_op > r_op THEN 1
WHEN op = '<=' AND l_op <= r_op THEN 1
WHEN op = '>=' AND l_op >= r_op THEN 1
WHEN op = 'LIKE' AND l_op LIKE r_op THEN 1
END = 1
GROUP BY t_id, f_id
HAVING COUNT(*) = MAX(num_expr);
db<>fiddle here
例如,如果我有一个像
这样的字符串my_string := ' ''a'' = ''a'' and 1 > 0 '
我可以在 procedure/function
中做这样的事情来评估它execute immediate 'select CASE WHEN(' || my_string || ') THEN 1 ELSE 0 END from dual'
但是有没有不用立即执行的方法呢?有没有办法像在查询中写入的那样评估字符串?
我想要这样做是因为我在 table 中有通用条件,例如“COD1 像 '%x%' OR COD2 = 'Z'”。所以我用这个字符串做了一些替换,但是我想让它们用约束条件来评估,以不使用用户定义的函数,所以没有“立即执行”
不可能,据我所知。这就是动态 SQL(即 execute immediate
)的用途。
例如,如果您只将一个条件(为简单起见)放入 table:
SQL> select * from test;
MY_STRING
---------------------
'a' = 'a' and 1 > 0
并将它交叉连接到另一个 table (因为,我希望 所有东西 都返回,因为总是满足该条件),你会得到一个错误:
SQL> select *
2 from dept d cross join test t
3 where t.mystring;
where t.mystring
*
ERROR at line 3:
ORA-00920: invalid relational operator
while - 如果按字面意思将条件放入 where
子句,它 有效 :
SQL> select *
2 from dept d cross join test t
3 where 'a' = 'a' and 1 > 0;
DEPTNO DNAME LOC MY_STRING
---------- -------------- ------------- ---------------------
10 ACCOUNTING NEW YORK 'a' = 'a' and 1 > 0
20 RESEARCH DALLAS 'a' = 'a' and 1 > 0
30 SALES CHICAGO 'a' = 'a' and 1 > 0
40 OPERATIONS BOSTON 'a' = 'a' and 1 > 0
SQL>
所以,恐怕是动态的 SQL。
is there a way to do that without using execute immediate
您可以使用替换变量作为替代方法,例如
SQL> SELECT CASE WHEN(&str) THEN 1 ELSE 0 END
2 FROM dual;
CASEWHEN('A'='A'AND1>0)THEN1EL
------------------------------
1
其中 'a' = 'a' and 1 > 0
在出现提示时输入 &str
是的,但是……实际上您必须编写自己的表达式解析器:
如果你有表格:
CREATE TABLE table_name (a, b, c, d) AS
SELECT 'x', 'x', 'x', 'x' FROM DUAL UNION ALL
SELECT 'w', 'x', 'y', 'z' FROM DUAL;
CREATE TABLE filters (filter) AS
SELECT 'a = b AND c <= d' FROM DUAL UNION ALL
SELECT 'a < b AND b < c AND c < d' FROM DUAL UNION ALL
SELECT 'a < ''y''' FROM DUAL UNION ALL
SELECT 'c LIKE ''%y%''' FROM DUAL;
并且您想将 filters
应用到 table_name
然后,从 Oracle 12,您可以使用:
WITH split_filters ( id, filter, left_operand, operator, right_operand, expr, num_expr ) AS (
SELECT ROWID,
filter,
REGEXP_SUBSTR(
filter,
'(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- left_operand
|| '\s*([<>!]?=|[<>]|LIKE)' -- operator
|| '\s*(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- right_operand
|| '\s*($|\sAND\s+)', -- expression concatenator
1,
1,
'i',
1
),
REGEXP_SUBSTR(
filter,
'(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- left_operand
|| '\s*([<>!]?=|[<>]|LIKE)' -- operator
|| '\s*(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- right_operand
|| '\s*($|\sAND\s+)', -- expression concatenator
1,
1,
'i',
3
),
REGEXP_SUBSTR(
filter,
'(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- left_operand
|| '\s*([<>!]?=|[<>]|LIKE)' -- operator
|| '\s*(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- right_operand
|| '\s*($|\sAND\s+)', -- expression concatenator
1,
1,
'i',
4
),
1,
REGEXP_COUNT(
filter,
'(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- left_operand
|| '\s*([<>!]?=|[<>]|LIKE)' -- operator
|| '\s*(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- right_operand
|| '\s*($|\sAND\s+)', -- expression concatenator
1,
'i'
)
FROM filters
UNION ALL
SELECT id,
filter,
REGEXP_SUBSTR(
filter,
'(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- left_operand
|| '\s*([<>!]?=|[<>]|LIKE)' -- operator
|| '\s*(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- right_operand
|| '\s*($|\sAND\s+)', -- expression concatenator
1,
expr + 1,
'i',
1
),
REGEXP_SUBSTR(
filter,
'(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- left_operand
|| '\s*([<>!]?=|[<>]|LIKE)' -- operator
|| '\s*(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- right_operand
|| '\s*($|\sAND\s+)', -- expression concatenator
1,
expr + 1,
'i',
3
),
REGEXP_SUBSTR(
filter,
'(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- left_operand
|| '\s*([<>!]?=|[<>]|LIKE)' -- operator
|| '\s*(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- right_operand
|| '\s*($|\sAND\s+)', -- expression concatenator
1,
expr + 1,
'i',
4
),
expr + 1,
num_expr
FROM split_filters
WHERE expr < num_expr
)
SELECT *
FROM table_name t
CROSS JOIN LATERAL (
SELECT MAX(filter) AS filter
FROM (
SELECT id,
filter,
CASE
WHEN UPPER(left_operand) = 'A' THEN t.a
WHEN UPPER(left_operand) = 'B' THEN t.b
WHEN UPPER(left_operand) = 'C' THEN t.c
WHEN UPPER(left_operand) = 'D' THEN t.d
WHEN left_operand LIKE '''%''' THEN REPLACE(SUBSTR(left_operand, 2, LENGTH(left_operand) - 2), '''''', '''')
END AS l_op,
operator AS op,
CASE
WHEN UPPER(right_operand) = 'A' THEN t.a
WHEN UPPER(right_operand) = 'B' THEN t.b
WHEN UPPER(right_operand) = 'C' THEN t.c
WHEN UPPER(right_operand) = 'D' THEN t.d
WHEN right_operand LIKE '''%''' THEN REPLACE(SUBSTR(right_operand, 2, LENGTH(right_operand) - 2), '''''', '''')
END AS r_op,
num_expr
FROM split_filters
)
WHERE CASE
WHEN op = '=' AND l_op = r_op THEN 1
WHEN op = '!=' AND l_op != r_op THEN 1
WHEN op = '<' AND l_op < r_op THEN 1
WHEN op = '>' AND l_op > r_op THEN 1
WHEN op = '<=' AND l_op <= r_op THEN 1
WHEN op = '>=' AND l_op >= r_op THEN 1
WHEN op = 'LIKE' AND l_op LIKE r_op THEN 1
END = 1
GROUP BY id
HAVING COUNT(*) = MAX(num_expr)
);
输出:
A B C D FILTER x x x x a = b AND c <= d x x x x a < 'y' w x y z a < b AND b < c AND c < d w x y z a < 'y' w x y z c LIKE '%y%'
db<>fiddle here
在 Oracle 11g 中,您可以将其重写为:
WITH split_filters ( id, filter, left_operand, operator, right_operand, expr, num_expr ) AS (
SELECT ROWID,
filter,
REGEXP_SUBSTR(
filter,
'(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- left_operand
|| '\s*([<>!]?=|[<>]|LIKE)' -- operator
|| '\s*(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- right_operand
|| '\s*($|\sAND\s+)', -- expression concatenator
1,
1,
'i',
1
),
REGEXP_SUBSTR(
filter,
'(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- left_operand
|| '\s*([<>!]?=|[<>]|LIKE)' -- operator
|| '\s*(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- right_operand
|| '\s*($|\sAND\s+)', -- expression concatenator
1,
1,
'i',
3
),
REGEXP_SUBSTR(
filter,
'(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- left_operand
|| '\s*([<>!]?=|[<>]|LIKE)' -- operator
|| '\s*(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- right_operand
|| '\s*($|\sAND\s+)', -- expression concatenator
1,
1,
'i',
4
),
1,
REGEXP_COUNT(
filter,
'(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- left_operand
|| '\s*([<>!]?=|[<>]|LIKE)' -- operator
|| '\s*(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- right_operand
|| '\s*($|\sAND\s+)', -- expression concatenator
1,
'i'
)
FROM filters
UNION ALL
SELECT id,
filter,
REGEXP_SUBSTR(
filter,
'(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- left_operand
|| '\s*([<>!]?=|[<>]|LIKE)' -- operator
|| '\s*(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- right_operand
|| '\s*($|\sAND\s+)', -- expression concatenator
1,
expr + 1,
'i',
1
),
REGEXP_SUBSTR(
filter,
'(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- left_operand
|| '\s*([<>!]?=|[<>]|LIKE)' -- operator
|| '\s*(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- right_operand
|| '\s*($|\sAND\s+)', -- expression concatenator
1,
expr + 1,
'i',
3
),
REGEXP_SUBSTR(
filter,
'(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- left_operand
|| '\s*([<>!]?=|[<>]|LIKE)' -- operator
|| '\s*(''([^'']|'''')*''|[A-Z][A-Z0-9_]*)' -- right_operand
|| '\s*($|\sAND\s+)', -- expression concatenator
1,
expr + 1,
'i',
4
),
expr + 1,
num_expr
FROM split_filters
WHERE expr < num_expr
),
operand_substitutions (t_id, f_id, a, b, c, d, filter, l_op, op, r_op, num_expr) AS (
SELECT t.ROWID,
f.id,
t.a,
t.b,
t.c,
t.d,
filter,
CASE
WHEN UPPER(left_operand) = 'A' THEN t.a
WHEN UPPER(left_operand) = 'B' THEN t.b
WHEN UPPER(left_operand) = 'C' THEN t.c
WHEN UPPER(left_operand) = 'D' THEN t.d
WHEN left_operand LIKE '''%''' THEN REPLACE(SUBSTR(left_operand, 2, LENGTH(left_operand) - 2), '''''', '''')
END,
operator,
CASE
WHEN UPPER(right_operand) = 'A' THEN t.a
WHEN UPPER(right_operand) = 'B' THEN t.b
WHEN UPPER(right_operand) = 'C' THEN t.c
WHEN UPPER(right_operand) = 'D' THEN t.d
WHEN right_operand LIKE '''%''' THEN REPLACE(SUBSTR(right_operand, 2, LENGTH(right_operand) - 2), '''''', '''')
END,
num_expr
FROM split_filters f
CROSS JOIN table_name t
)
SELECT MAX(a) AS a,
MAX(b) AS b,
MAX(c) AS c,
MAX(d) AS d,
MAX(filter) AS filter
FROM operand_substitutions
WHERE CASE
WHEN op = '=' AND l_op = r_op THEN 1
WHEN op = '!=' AND l_op != r_op THEN 1
WHEN op = '<' AND l_op < r_op THEN 1
WHEN op = '>' AND l_op > r_op THEN 1
WHEN op = '<=' AND l_op <= r_op THEN 1
WHEN op = '>=' AND l_op >= r_op THEN 1
WHEN op = 'LIKE' AND l_op LIKE r_op THEN 1
END = 1
GROUP BY t_id, f_id
HAVING COUNT(*) = MAX(num_expr);
db<>fiddle here