Postgresql:select 与 func() 不同 *;

Postgresql : select distinct * from func() ;

----------------     PostgreSQL:    ---------------------

drop table if exists test;
CREATE TABLE test
(
"Id" SERIAL NOT NULL,
"User" VARCHAR(64) NOT NULL,
"Name" VARCHAR(50) NOT NULL,
"DId" INTEGER NOT NULL,
PRIMARY KEY("User"));
----------------- CREATE  TABLE ---------------------


truncate table test;

insert into test values
(1655,'1000000000','1000000000',6),
(844,'111','111',6),
(847,'114','114',6),
(849,'116','116',6),
(864,'131','131',6),
(884,'151','151',6),
(3242,'201919-11:29:3:340','sizhanerLD',6),
(3241,'201919-11:28:17:506','sizhanerZB',6),
(3240,'201919-11:27:37:15','sizhanerLD',6),
(3239,'201919-11:25:57:629','sizhanerZB',6);
----------------- INSERT  DATA ----------------------

create TYPE "public"."BPI" as (
        "Id" integer,
        "DId"   integer,
        "User"  VARCHAR(64), 
        "Name"  VARCHAR(50) 
);

---------------------------------CREATE TYPE --------------------------------------------------




--------------CREATE 3 FUNC()-----------------

CREATE OR REPLACE FUNCTION "QBP_1"()
RETURNS TABLE("Item" "BPI")
AS $$
declare
    "MyCsr" refcursor;
     "SqlStr" varchar(10240) := 'SELECT "Id", "DId", "User", "Name" from test ORDER BY "Name" ASC LIMIT 10 OFFSET 0';
BEGIN
    raise notice 'SQL :%', "SqlStr";
    open "MyCsr" for EXECUTE "SqlStr";   
     fetch "MyCsr" into "Item";
     while FOUND loop
        return next;
        fetch "MyCsr" into "Item";
     end loop;
     close "MyCsr";
     return ;
--select distinct * from "QBP_1"();
END;
$$ language plpgsql;

-----------------------------------------------------------------------


CREATE OR REPLACE FUNCTION "QBP_2"()
RETURNS TABLE("Id" integer,
                "DId"   integer,
                "User"  VARCHAR(64), 
                "Name"  VARCHAR(64) )
AS $$
declare
    "MyCsr" refcursor;
     "SqlStr" varchar(10240) := 'SELECT "Id", "DId", "User", "Name" from test ORDER BY "Name" ASC LIMIT 10 OFFSET 0';
BEGIN
    raise notice 'SQL :%', "SqlStr";
    return query execute "SqlStr";
--select distinct * from "QBP_2"();
END;
$$ language plpgsql;


---------------------------------------------------------------


CREATE OR REPLACE FUNCTION "QBP_3"()
RETURNS SETOF  "BPI"
AS $$
declare
    "Item"  "BPI";
     "SqlStr" varchar(10240) := 'SELECT "Id", "DId", "User", "Name" from test ORDER BY "Name" ASC LIMIT 10 OFFSET 0';
BEGIN
    raise notice 'SQL :%', "SqlStr";
    for "Item" in execute "SqlStr" LOOP
        return next "Item";
    end LOOP;
--select distinct * from "QBP_3"();
END;
$$ language plpgsql;

SQL1: select distinct * from "QBP_1"();

SQL2: select distinct * from "QBP_2"();

SQL3: select distinct * from "QBP_3"();

SQL4: SELECT distinct "Id", "DId", "User", "Name" from test ORDER BY "Name" ASC LIMIT 10 OFFSET 0;

returning:

postgres=# select distinct * from "QBP_1"();
NOTICE:  SQL :SELECT "Id", "DId", "User", "Name" from test ORDER BY "Name" ASC LIMIT 10 OFFSET 0
  Id  | DId |        User         |    Name
------+-----+---------------------+------------
  844 |   6 | 111                 | 111
 3242 |   6 | 201919-11:29:3:340  | sizhanerLD
  884 |   6 | 151                 | 151
  864 |   6 | 131                 | 131
  847 |   6 | 114                 | 114
  849 |   6 | 116                 | 116
 3241 |   6 | 201919-11:28:17:506 | sizhanerZB
 3239 |   6 | 201919-11:25:57:629 | sizhanerZB
 3240 |   6 | 201919-11:27:37:15  | sizhanerLD
 1655 |   6 | 1000000000          | 1000000000
(10 rows)

postgres=# select distinct * from "QBP_2"();
NOTICE:  SQL :SELECT "Id", "DId", "User", "Name" from test ORDER BY "Name" ASC LIMIT 10 OFFSET 0
  Id  | DId |        User         |    Name
------+-----+---------------------+------------
  844 |   6 | 111                 | 111
 3242 |   6 | 201919-11:29:3:340  | sizhanerLD
  884 |   6 | 151                 | 151
  864 |   6 | 131                 | 131
  847 |   6 | 114                 | 114
  849 |   6 | 116                 | 116
 3241 |   6 | 201919-11:28:17:506 | sizhanerZB
 3239 |   6 | 201919-11:25:57:629 | sizhanerZB
 3240 |   6 | 201919-11:27:37:15  | sizhanerLD
 1655 |   6 | 1000000000          | 1000000000
(10 rows)

postgres=# select distinct * from "QBP_3"();
NOTICE:  SQL :SELECT "Id", "DId", "User", "Name" from test ORDER BY "Name" ASC LIMIT 10 OFFSET 0
  Id  | DId |        User         |    Name
------+-----+---------------------+------------
  844 |   6 | 111                 | 111
 3242 |   6 | 201919-11:29:3:340  | sizhanerLD
  884 |   6 | 151                 | 151
  864 |   6 | 131                 | 131
  847 |   6 | 114                 | 114
  849 |   6 | 116                 | 116
 3241 |   6 | 201919-11:28:17:506 | sizhanerZB
 3239 |   6 | 201919-11:25:57:629 | sizhanerZB
 3240 |   6 | 201919-11:27:37:15  | sizhanerLD
 1655 |   6 | 1000000000          | 1000000000
(10 rows)

postgres=# SELECT distinct "Id", "DId", "User", "Name" from test ORDER BY "Name" ASC LIMIT 10 OFFSET 0;
  Id  | DId |        User         |    Name
------+-----+---------------------+------------
 1655 |   6 | 1000000000          | 1000000000
  844 |   6 | 111                 | 111
  847 |   6 | 114                 | 114
  849 |   6 | 116                 | 116
  864 |   6 | 131                 | 131
  884 |   6 | 151                 | 151
 3242 |   6 | 201919-11:29:3:340  | sizhanerLD
 3240 |   6 | 201919-11:27:37:15  | sizhanerLD
 3241 |   6 | 201919-11:28:17:506 | sizhanerZB
 3239 |   6 | 201919-11:25:57:629 | sizhanerZB
(10 rows)


如上代码所示。我为一个简单的测试创建了 3 个函数。但是好像SQL123returns命令错了。 (如果我删除 "distinct",返回的顺序是正确的)我是否错误地使用了 "distinct"?为什么?

最后,我为我糟糕的英语道歉。希望不影响阅读

关系数据库中的表表示关系。关系是一种特殊类型的(多)集合。集合没有顺序。因此 SQL 中的查询结果可以按任何顺序排列,除非 最外层 查询明确地使用 ORDER BY 子句对结果进行排序。

当然输出的结果是有物理顺序的。但重要的一点是,当缺少 ORDER BY 子句时,引擎可以按任何顺序 return 结果。在您的情况下,引擎可能会以 "good" 的方式处理函数的中间结果以进行重复数据删除(DISTINCT),并且可以 "reorder" 元组(甚至可能每次都以另一个顺序发出查询)。

如果您想要一个有序的结果,请在最外层的查询中包含一个 ORDER BY 子句,例如

SELECT DISTINCT
       *
       FROM "QBP_1"()
       ORDER BY "Name";

和其他功能的模拟。否则你不能期望某个顺序,即也没有 "wrong order" 然后。

附带说明:考虑不要使用这种始终需要引号的驼峰式标识符。这可能非常令人困惑。只使用不带引号(小写)的标识符可以省去一些麻烦。