使用SQLAlchemy从PostgreSQL行对象获取单个值

2024-06-02 13:31:03 发布

您现在位置:Python中文网/ 问答频道 /正文

我将Python与SQLAlchemy一起使用(在我的特定情况下是GeoAlchemy),并且我有一个查询,结果是一列行对象。我希望从这些row对象中提取特定的值,但是SQLAlchemy将row对象解释为单个实体(如果我是正确的,将它们作为字符串返回)。在不使用Python解析它们的情况下,如何更清晰地获取这些单独的值?在

我的真实生活用例: PostgreSQL的PostGIS扩展提供了一个名为^{}的函数。此函数用于返回valid_detail行,该行由布尔valid、字符串reason和发生无效的几何体location。因为我觉得这个问题比那个问题更普遍,所以我不提PostGIS标签了。我的查询类似于SELECT ST_IsValidDetail('POINT(1 1)'::GEOMETRY);(当然,还有更复杂的几何体)。在


Tags: 对象函数字符串实体sqlalchemypostgresql情况location
2条回答

您可以使用:

SELECT (ST_IsValidDetail(the_value)).* FROM the_table;

。。。但是不幸的是,PostgreSQL实际上对每一行执行一次ST_IsValidDetail函数。作为一种解决方法,您可以将查询稍微弄乱一点,通过一个公共表表达式具体化,然后在第二个过程中提取元组:

^{pr2}$

需要(v)周围的paren来告诉解析器您引用的是一个值,而不是表名。在

演示:

CREATE OR REPLACE FUNCTION multirows(x IN integer, a OUT integer, b OUT integer, c OUT integer) AS
$$
BEGIN
    RAISE NOTICE 'multirows(%) invoked', x;
    a := x;
    b := x+1;
    c := x+2;
    RETURN;
END;
$$ LANGUAGE plpgsql;

craig=> SELECT multirows(x) FROM generate_series(1,2) x;
NOTICE:  multirows(1) invoked
NOTICE:  multirows(2) invoked
 multirows 
     -
 (1,2,3)
 (2,3,4)
(2 rows)

craig=> SELECT (multirows(x)).* FROM generate_series(1,2) x;
NOTICE:  multirows(1) invoked
NOTICE:  multirows(1) invoked
NOTICE:  multirows(1) invoked
NOTICE:  multirows(2) invoked
NOTICE:  multirows(2) invoked
NOTICE:  multirows(2) invoked
 a | b | c 
 -+ -+ -
 1 | 2 | 3
 2 | 3 | 4
(2 rows)




craig=> WITH interim(v) AS (SELECT multirows(x) FROM generate_series(1,2) x)
SELECT (v).* FROM interim;
NOTICE:  multirows(1) invoked
NOTICE:  multirows(2) invoked
 a | b | c 
 -+ -+ -
 1 | 2 | 3
 2 | 3 | 4
(2 rows)

我从ST_IsValidDetail页面上的例子中找到了一种方法。显然,以下语法是有效的:

SELECT gid, reason(ST_IsValidDetail(the_geom)), ST_AsText(location(ST_IsValidDetail(the_geom)))

注意reasonlocation“调用”围绕着函数调用;由ST_IsValidDetail返回的行中列的名称几乎被视为函数。结果证明你可以欺骗SQLAlchemy做同样的事情。(假设session是先前设置的Session对象,db_geom是一个地学几何对象。)

^{pr2}$

result[0]将包含原因,result[1]将包含该位置的WKT。(我们可以使用label来给出列的实际名称。)

要在不使用PostGIS功能的情况下对其进行修剪:

from sqlalchemy import func as sqlfunc
result = session.query(sqlfunc.columnname(sqlfunc.myrowfunc('some input string')).label('mylabel')).one()

这使得SQLAlchemy认为columnname是一个函数,并以以下形式向数据库发送SQL

SELECT columnname(myrowfunc('some input string')) AS mylabel;

我还没有尝试过它,但是如果有一种方法可以让SQLAlchemy将我们的行看作是我们选择的表FROM,那也可以。(请参阅ST_IsValidDetail页的最底部。)

相关问题 更多 >