Oracle 为动态 SQL 创建公式以防止被零除

我有一个带有公式列的表,该表具有可获取到动态 SQL LIKE n5/n14+n3

的公式

我的问题是当公式有除法时,我应该尝试转换公式以防止错误divide by zero

我目前的想法是将公式转换为CASE,当它有神圣时,例如n5/n14+n3CASE WHEN n14 = 0 THEN 0 ELSE n5/n14+n3 END

但我只能在公式只有 1 个除法的情况下进行转换,并且在公式有 > 1 个除法(例如 n5/n4+n3/n2,或公式除以表达式(例如 n5/(n4+n3))的情况下无法转换。

有人能解决这个问题吗?

WITH tmp AS 
(
    SELECT 'n5/n14+n3' AS formula FROM dual UNION ALL 
    SELECT 'n5/n14+n3/n1-n2' AS formula FROM dual UNION ALL 
    SELECT 'n8/(n17*n6)-n5/n4+n3/n1-n2' AS formula FROM dual UNION ALL 
    SELECT 'n5/(n14+n3*n2)-n1' AS formula FROM dual 
)
SELECT
    formula,CASE
         WHEN formula NOT LIKE '%/%' OR REPLACE(formula,' ','') LIKE '%/(%' OR (LENGTH(formula) - LENGTH(REPLACE(formula,'/',''))) > 1 THEN  formula
         ELSE 'CASE WHEN ' || SUBSTR(REGEXP_SUBSTR(REPLACE(formula,''),'/(n\d+)'),2) || ' = 0 THEN 0 ELSE ' || formula || ' END'
     END AS formula1,'CASE WHEN ' || SUBSTR(REGEXP_SUBSTR(REPLACE(formula,2) || ' = 0 THEN 0 ELSE ' || formula || ' END' AS formula2
 FROM tmp t;

当前结果不是预期的输出(只有第 1 行解决除以零错误):

formula                     formula1                                    formula2
n5/n14+n3                   CASE WHEN n14 = 0 THEN 0 ELSE n5/n14+n3 END CASE WHEN n14 = 0 THEN 0 ELSE n5/n14+n3 END                
n5/n14+n3/n1-n2             n5/n14+n3/n1-n2                             CASE WHEN n14 = 0 THEN 0 ELSE n5/n14+n3/n1-n2 END          
n8/(n17*n6)-n5/n4+n3/n1-n2  n8/(n17*n6)-n5/n4+n3/n1-n2                  CASE WHEN n4 = 0 THEN 0 ELSE n8/(n17*n6)-n5/n4+n3/n1-n2 END
n5/(n14+n3*n2)-n1           n5/(n14+n3*n2)-n1                           CASE WHEN  = 0 THEN 0 ELSE n5/(n14+n3*n2)-n1 END           

   
ptxncxf 回答:Oracle 为动态 SQL 创建公式以防止被零除

您可以使用 NULLIF() 来防止错误。结果将是 NULL

(
    SELECT 'n5/nullif(n14,0)+n3' AS formula FROM dual UNION ALL 
    SELECT 'n5/nullif(n14,0)+n3/nullif(n1,0)-n2' AS formula FROM dual UNION ALL 
    SELECT 'n8/nullif(n17*n6,0)-n5/nullif(n4,0)-n2' AS formula FROM dual UNION ALL 
    SELECT 'n5/nullif((n14+n3*n2,0)-n1' AS formula FROM dual 
)
,

感谢@Linoff 先生的建议,我确实使用`` 来使用 NULLIF 来获取和转换公式

WITH tmp AS 
(
    SELECT 'n5/n14+n3' AS formula FROM dual UNION ALL 
    SELECT 'n5/n14+n3/n1-n2' AS formula FROM dual UNION ALL 
    SELECT 'n8/(n17*n6)-n5/n4+n3/n1-n2' AS formula FROM dual UNION ALL 
    SELECT 'n5/(n14+n3*n2)-n1' AS formula FROM dual 
)
SELECT formula,REGEXP_REPLACE(REPLACE(formula,' ',''),'\/(n\d+)|\/(\([^\)]*\))','/NULLIF(\1\2,0)') AS formula1
FROM tmp;

结果:

formula                     formula1                                    
n5/n14+n3                   n5/NULLIF(n14,0)+n3                                     
n5/n14+n3/n1-n2             n5/NULLIF(n14,0)+n3/NULLIF(n1,0)-n2                     
n8/(n17*n6)-n5/n4+n3/n1-n2  n8/NULLIF((n17*n6),0)-n5/NULLIF(n4,0)-n2
n5/(n14+n3*n2)-n1           n5/NULLIF((n14+n3*n2),0)-n1                             

                     
,
  • 用 Java 编写一个解析器来解析您的表达式(或使用现有的解析器)。
  • 编写一个静态 Java 函数,将解析器生成的抽象语法树转换为您需要的输出,并用 NULLIFCASE 表达式将除法中的每个分母包装起来,以防止被零除引发异常。
  • 使用 loadjava utility 将其加载到数据库中。
  • 编写一个 PL/SQL 函数来包装 Java 函数。
  • 使用 PL/SQL 函数将您的动态代码转换为更安全的代码。
本文链接:https://www.f2er.com/6800.html

大家都在问