Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/76.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql POSTGRES-计算(子)表达式错误为NULL_Sql_Postgresql_Rdbms - Fatal编程技术网

Sql POSTGRES-计算(子)表达式错误为NULL

Sql POSTGRES-计算(子)表达式错误为NULL,sql,postgresql,rdbms,Sql,Postgresql,Rdbms,我在Postgres表中有传感器数据测量值,其中列有id,时间戳,s0,s1,s2 此外,在(id,timestamp)列上还有一个索引。我希望允许动态数学表达式(在下面的示例中:sin(s3)*0.1000/s5)用于计算派生值 SELECT timestamp, trunc((sin(s3) * 0.1000/s5)::numeric, 3) AS "calculated" FROM measurements WHERE id = 42 ORDER BY timestamp DESC

我在Postgres表中有传感器数据
测量值
,其中列有
id
时间戳
s0
s1
s2

此外,在
(id,timestamp)
列上还有一个索引。我希望允许动态数学表达式(在下面的示例中:
sin(s3)*0.1000/s5
)用于计算派生值

SELECT
  timestamp,
  trunc((sin(s3) * 0.1000/s5)::numeric, 3) AS "calculated"
FROM measurements
WHERE id = 42
ORDER BY timestamp DESC
LIMIT 10000;
显然,这很容易出现“零除”错误,这将导致查询失败。是否有方法捕获此错误并返回可能发生错误的计算值,例如
NULL

灵感来自

我已经尝试定义一个
postgres
函数
eval_numeric(sensors int[],formula text)
,该函数解析公式并在异常时返回
NULL
。上面SQL语句的第三行现在读取

trunc(eval_numeric(ARRAY[s3,s5],'sin(var1)*0.1/var2'), 3) AS "calculated"
这提供了所需的行为,但是
EXPLAIN ANALYZE
报告的执行时间增加了20倍(~20ms->~400ms)。还有其他想法吗


更新


要计算的动态表达式来自web应用程序用户。因此,上面的公式只是一个示例(可能需要检查平方根的负参数)。我宁愿有一个通用的错误检查的可能性,也不愿意在数学表达式中有逻辑。这对最终用户来说会更容易,我可以验证允许的数学,例如使用数学解析器,从而防止SQL注入。

您能将表达式更改为此吗

SELECT timestamp,
       trunc((sin(s3) * 0.1000/nullif(s5, 0))::numeric, 3) AS "calculated",
FROM measurements
WHERE id = 42
ORDER BY timestamp DESC
LIMIT 10000;

这是完成您想做的事情的最简单方法。

您还可以使用
大小写表达式:

SELECT
    timestamp,
    CASE WHEN s5 != 0
         THEN trunc((sin(s3) * 0.1000/s5)::numeric, 3)
         ELSE NULL AS "calculated",
FROM measurements
WHERE id = 42
ORDER BY timestamp DESC
LIMIT 10000;
这样做的潜在好处是,您可以使用任何您想要的内容替换该值,包括
NULL


另一种选择是,如果您不关心会触发被零除的行,只需将检查
s5
添加到
WHERE
子句中,并在除法发生之前过滤掉这些行。

感谢您这么快的回答。这似乎是可行的,而且速度很快。我宁愿数学表达式中没有逻辑。关于这一点,我将更新我的问题。但也许这是另一个问题。我接受你的回答。