postgresql - 从 CASE 语句中设置 PostgreSQL 变量
问题描述
目前使用 PostgresSQL 10 作为新手,并尽我所能遵循文档。欢迎大家帮忙。
我正在尝试根据 case 语句设置变量的值,以便可以在代码的下一部分中使用该值。我遇到了语法问题,老实说,我只是了解如何从 case 语句中设置值。
下面是我到目前为止的代码。
我正在尝试设置变量“AndSol”的值。根据案例陈述,该值将设置为 0 或 1。
带有注释“太阳辐射”的块是我在设置变量值时遇到问题的地方。其余代码仅供参考,以了解我想要实现的目标。我以THEN AndSol := 1;的方式结束每个 where 子句 ,我认为这就是错误所在。我不知道如何解决它。
基本流程:
确定变量应该是 0 还是 1。
设置变量。
在下一部分中使用该变量。
DO $$
DECLARE AndSol NUMERIC;
BEGIN
DROP MATERIALIZED VIEW IF EXISTS view_6day_mat;
CREATE MATERIALIZED VIEW view_6day_mat
AS
SELECT prod_qld_6km_grids.weather_cell_id,
prod_qld_6km_grids.latitude,
prod_qld_6km_grids.longitude,
/* Solar Radiation */
CASE
WHEN EXTRACT(MONTH FROM prod_weathergrids.dates) >= 8 AND EXTRACT(MONTH FROM prod_weathergrids.dates) <= 12 THEN AndSol := 1;
WHEN EXTRACT(MONTH FROM prod_weathergrids.dates) = 1 AND EXTRACT(MONTH FROM prod_weathergrids.dates) <= 2 AND prod_weathergrids.cloudcover < 30 then AndSol := 1;
ELSE AndSol := 0; END/* 0 END AS AndersonsSolarRad, */
/* Moisture Content */
CASE WHEN prod_weathergrids.rh > 0 AND prod_weathergrids.temperature > 0 THEN
ROUND(4.37+0.161*prod_weathergrids.rh-0.1*(prod_weathergrids.temperature-25)-AndSol*0.027*prod_weathergrids.rh), 2)
ELSE 0 END AS AndersonsHMC
FROM MyTable
ORDER BY prod_qld_6km_grids.weather_cell_id
END $$;
我从 pgAdmin 收到的错误消息是:
ERROR: syntax error at or near ":="
LINE 49: ...(MONTH FROM prod_weathergrids.dates) <= 12 THEN AndSol := 1;
^
SQL state: 42601
Character: 2440
我必须承认,我不知道如何克服这个错误,因为我看到的文档和示例大多都使用“:=”设置变量。
解决方案
您正在使用 SQLCASE
表达式。这个语句是有功能的。它会从一个值转换到第二个值,但它不能保存任何 PLpgSQL 语句。
PLpgSQL 支持CASE
具有类似语法的过程,允许分配语句。但此语句不能嵌套在其他 SQL 语句中。
DO $$
DECLARE is_monday boolean;
BEGIN
-- SQL case, functiona
is_monday = CASE EXTRACT(DOW FROM CURRENT_DATE)
WHEN 1 THEN true -- only a value or SQL expression is allowed there
ELSE false
END;
RAISE NOTICE 'Today is Monday %', is_monday;
-- procedural PLpgSQL case
-- cannot be used inside SQL statement
CASE EXTRACT(DOW FROM CURRENT_DATE)
WHEN 1 THEN
-- nesting PLpgSQL statements
is_monday := true;
RAISE NOTICE 'today is Monday';
ELSE
is_monday := true;
RAISE NOTICE 'today is Monday';
END CASE; -- ending with "END CASE"
END; $$;
在 Postgres 中,你想要的是不可能的(不是没有相对丑陋的解决方法,不仅是 SQL)。当您计算列值时,您不能重复使用在同一级别计算的任何信息。
您可以使用派生表。您可以更深入地计算一些信息,并且可以在更高级别上更多次使用此信息:
SELECT dt.x, dt.x + 1, dt.x * 10
FROM (SELECT random() * 10 AS x
FROM generate_series(1, 10)) dt; -- derived table
您的示例显示了有趣的错误 - 陷阱。您正在从 PLpgSQL 创建视图。但是这个视图将在没有 PLpgSQL 的情况下存在——所以你不能在那里使用 PLpgSQL 特性——比如变量。
推荐阅读
- r - 用正态分布覆盖直方图
- azure - 我可以对 Azure 应用服务进行实时威胁防护吗
- c# - 使用 EF Core 进行 CQRS/ES 投影重播
- jenkins - 重启后的 Jenkins 错误:java.lang.IllegalStateException:预期 1 个 hudson.model.User$AllUsers 实例但得到 0
- javascript - 动态获取keycloak.json?
- apache-kafka - 删除主题级别配置
- javascript - 从数组向 Chart.js 折线图添加数据
- javascript - iOS PWA - 打开地图返回空白屏幕
- python - 将字典列表转换为字典 python3
- encryption - 自我验证加密字符串 - 方法可行吗?