postgresql - 通过在 postgresql 上声明变量来选择查询

标签 postgresql postgis

我是 postgresql 和 pgadmin4 的新手。我写了一个非常简单的查询。

我在公共(public)架构上有一个名为 PgFinalLocationsTable 的表。在我的表中有几个字段。其中一个字段是 UserName。我想声明一个变量并且最后根据这个变量在我的表上进行选择,如下所示:

DO $$
DECLARE myvar text default 'sa';
BEGIN
    select * from public."PgFinalLocationsTable" where "UserName" = myvar;
END $$;

但为什么我收到这些消息:

ERROR:  query has no destination for result data
HINT:  If you want to discard the results of a SELECT, use PERFORM instead.
CONTEXT:  PL/pgSQL function inline_code_block line 4 at SQL statement
SQL state: 42601

这是一个简单的查询!!!

谷歌搜索并查看堆栈上的帖子后,我将查询更改为如下:

CREATE OR REPLACE FUNCTION fun(text myvar) RETURNS text AS $$
--DECLARE myvar text;
BEGIN
    select * from public."PgFinalLocationsTable" where "UserName" = myvar;
END;
$$ language plpgsql;

select fun('sa'); 

我想返回我所有的字段,我不想使用 plpgsql。我想使用 PostgreSQL。无论如何我得到了这个错误:

ERROR:  type myvar does not exist
SQL state: 42704

我的第一个查询和第二个查询有什么问题?当我想传递一个变量时,我是否应该为选择查询创建一个函数?

我做所有的事情因为我想创建这个 sql 查询:

"IF (NOT EXISTS(SELECT 1 FROM [dbo].[{0}] WHERE [UserId] = @UserId And [DeviceId] = @DeviceId)) " +
"BEGIN " +
"INSERT INTO [dbo].[{0}]([Id], [Location], [Timestamp], [UserId], [DeviceId], [AllowDomains], [Topic], [UserName], [FirstName], [LastName], [JobLocationName], [LocationId], [AppVersion], [AppName]) " +
"VALUES(@Id, GEOGRAPHY::Point(@X, @Y, 4326), @Timestamp, @UserId, @DeviceId, @AllowDomains, @Topic, @UserName, @FirstName, @LastName, @JobLocationName,  @LocationId,  @AppVersion, @AppName) " +
"END "

最佳答案

你不理解 DO 命令。 DO 命令是没有声明的匿名函数,并且因为它没有声明输出,所以除了调试流之外不可能有任何其他结果。

所以你的第一个例子在 PostgreSQL 中没有意义。 MSSQL 中取消绑定(bind)查询的结果作为 MS SQL 过程的结果返回。在 PostgreSQL 中不可能有任何类似的东西。 PostgreSQL 只知道可以返回标量值、复合值或关系(只有一个)的函数。当您来自 MS SQL 时,尽您所能,尝试忘记几乎所有来自 MS SQL 的知识。

ERROR:  type myvar does not exist
SQL state: 42704

这个错误是干净的——你切换变量名和类型名——实际上类型 myvar 不存在。

一些返回表的函数如下所示:

CREATE OR REPLACE FUNCTION fx1(myvar text)
RETURNS SETOF public."PgFinalLocationsTable" AS $$
BEGIN
  RETURN QUERY SELECT * FROM public."PgFinalLocationsTable" WHERE "UserName" = myvar;
END;
$$ LANGUAGE plpgsql;

或者你可以只使用 SQL 语言

CREATE OR REPLACE FUNCTION fx1(myvar text)
RETURNS SETOF public."PgFinalLocationsTable" AS $$
  SELECT * FROM public."PgFinalLocationsTable" WHERE "UserName" = $1;
$$ LANGUAGE sql;

因为PostgreSQL不支持解除绑定(bind)查询,所以不允许。您应该使用 RETURN QUERY 命令 - 在 PLpgSQL 语言中。

因为使用存储过程编程在 PostgreSQL 和 MSSQL 之间确实不同(MSSQL 与任何其他的都不相似),请尝试阅读文档 - 它不错 https://www.postgresql.org/docs/current/static/plpgsql.html

你的函数在 Postgres 中看起来像(我不知道使用的类型)

CREATE OR REPLACE FUNCTION fx("_UserId" int,
                              "_DeviceId" int,
                              "_X" int,
                              "_Y" int, 
                              ...
BEGIN
  IF NOT EXISTS(SELECT * FROM /* I don't know what [{0}] means */
                 WHERE "UserId" = "_UserId" AND "DeviceId" = "_DeviceId")
  THEN
    INSERT INTO ..
  END IF;
END;
$$ LANGUAGE plpgsql;

可能您的片段可以通过 INSERT INTO ON CONFLICT DO NOTHING 命令解决而无需程序扩展 https://www.postgresql.org/docs/current/static/sql-insert.html - 什么更好。

注意 - 使用区分大小写的标识符是通往 hell 的捷径。

关于postgresql - 通过在 postgresql 上声明变量来选择查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51491628/

相关文章:

postgresql - 为什么 emacs 找不到 psql?

node.js - 如何修复多行 node-postgres 插入 - 语法错误等于或接近 $4

sql - 动态SQL合并纵横表

node.js - Node js 应用程序中的 knex 迁移错误

postgresql - 使用从表本身中选择的表插入数据

database - 使用 PostGIS 从点数据生成热图/密度图

xml - 使用渗透将 POSTGIS 表转换为 .OSM

java - 使用 JPA 进行 GIS 几何映射后的异常

postgresql - 应该使用哪种数据类型来存储 GeoJSON 对 Postgres 的响应

postgis - 如何在deck.gl 中将超集数据显示为多边形